linux/arch/ppc/platforms/pplus.c
<<
>>
Prefs
   1/*
   2 * Board and PCI setup routines for MCG PowerPlus
   3 *
   4 * Author: Randy Vinson <rvinson@mvista.com>
   5 *
   6 * Derived from original PowerPlus PReP work by
   7 * Cort Dougan, Johnnie Peters, Matt Porter, and
   8 * Troy Benjegerdes.
   9 *
  10 * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
  11 * the terms of the GNU General Public License version 2.  This program
  12 * is licensed "as is" without any warranty of any kind, whether express
  13 * or implied.
  14 */
  15
  16#include <linux/kernel.h>
  17#include <linux/interrupt.h>
  18#include <linux/init.h>
  19#include <linux/ioport.h>
  20#include <linux/console.h>
  21#include <linux/pci.h>
  22#include <linux/ide.h>
  23#include <linux/seq_file.h>
  24#include <linux/root_dev.h>
  25
  26#include <asm/system.h>
  27#include <asm/io.h>
  28#include <asm/pgtable.h>
  29#include <asm/dma.h>
  30#include <asm/machdep.h>
  31#include <asm/prep_nvram.h>
  32#include <asm/vga.h>
  33#include <asm/i8259.h>
  34#include <asm/open_pic.h>
  35#include <asm/hawk.h>
  36#include <asm/todc.h>
  37#include <asm/bootinfo.h>
  38#include <asm/kgdb.h>
  39#include <asm/reg.h>
  40
  41#include "pplus.h"
  42
  43#undef DUMP_DBATS
  44
  45TODC_ALLOC();
  46
  47extern void pplus_setup_hose(void);
  48extern void pplus_set_VIA_IDE_native(void);
  49
  50extern unsigned long loops_per_jiffy;
  51unsigned char *Motherboard_map_name;
  52
  53/* Tables for known hardware */
  54
  55/* Motorola Mesquite */
  56static inline int
  57mesquite_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
  58{
  59        static char pci_irq_table[][4] =
  60            /*
  61             *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
  62             *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
  63             *      PCI IDSEL/INTPIN->INTLINE
  64             *         A   B   C   D
  65             */
  66        {
  67                {18,  0,  0,  0},       /* IDSEL 14 - Enet 0 */
  68                { 0,  0,  0,  0},       /* IDSEL 15 - unused */
  69                {19, 19, 19, 19},       /* IDSEL 16 - PMC Slot 1 */
  70                { 0,  0,  0,  0},       /* IDSEL 17 - unused */
  71                { 0,  0,  0,  0},       /* IDSEL 18 - unused */
  72                { 0,  0,  0,  0},       /* IDSEL 19 - unused */
  73                {24, 25, 26, 27},       /* IDSEL 20 - P2P bridge (to cPCI 1) */
  74                { 0,  0,  0,  0},       /* IDSEL 21 - unused */
  75                {28, 29, 30, 31}        /* IDSEL 22 - P2P bridge (to cPCI 2) */
  76        };
  77
  78        const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
  79        return PCI_IRQ_TABLE_LOOKUP;
  80}
  81
  82/* Motorola Sitka */
  83static inline int
  84sitka_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
  85{
  86        static char pci_irq_table[][4] =
  87            /*
  88             *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
  89             *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
  90             *      PCI IDSEL/INTPIN->INTLINE
  91             *         A   B   C   D
  92             */
  93        {
  94                {18,  0,  0,  0},       /* IDSEL 14 - Enet 0 */
  95                { 0,  0,  0,  0},       /* IDSEL 15 - unused */
  96                {25, 26, 27, 28},       /* IDSEL 16 - PMC Slot 1 */
  97                {28, 25, 26, 27},       /* IDSEL 17 - PMC Slot 2 */
  98                { 0,  0,  0,  0},       /* IDSEL 18 - unused */
  99                { 0,  0,  0,  0},       /* IDSEL 19 - unused */
 100                {20,  0,  0,  0}        /* IDSEL 20 - P2P bridge (to cPCI) */
 101        };
 102
 103        const long min_idsel = 14, max_idsel = 20, irqs_per_slot = 4;
 104        return PCI_IRQ_TABLE_LOOKUP;
 105}
 106
 107/* Motorola MTX */
 108static inline int
 109MTX_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 110{
 111        static char pci_irq_table[][4] =
 112            /*
 113             *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
 114             *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
 115             *      PCI IDSEL/INTPIN->INTLINE
 116             *         A   B   C   D
 117             */
 118        {
 119                {19,  0,  0,  0},       /* IDSEL 12 - SCSI   */
 120                { 0,  0,  0,  0},       /* IDSEL 13 - unused */
 121                {18,  0,  0,  0},       /* IDSEL 14 - Enet   */
 122                { 0,  0,  0,  0},       /* IDSEL 15 - unused */
 123                {25, 26, 27, 28},       /* IDSEL 16 - PMC Slot 1 */
 124                {26, 27, 28, 25},       /* IDSEL 17 - PMC Slot 2 */
 125                {27, 28, 25, 26}        /* IDSEL 18 - PCI Slot 3 */
 126        };
 127
 128        const long min_idsel = 12, max_idsel = 18, irqs_per_slot = 4;
 129        return PCI_IRQ_TABLE_LOOKUP;
 130}
 131
 132/* Motorola MTX Plus */
 133/* Secondary bus interrupt routing is not supported yet */
 134static inline int
 135MTXplus_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 136{
 137        static char pci_irq_table[][4] =
 138            /*
 139             *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
 140             *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
 141             *      PCI IDSEL/INTPIN->INTLINE
 142             *         A   B   C   D
 143             */
 144        {
 145                {19,  0,  0,  0},       /* IDSEL 12 - SCSI   */
 146                { 0,  0,  0,  0},       /* IDSEL 13 - unused */
 147                {18,  0,  0,  0},       /* IDSEL 14 - Enet 1 */
 148                { 0,  0,  0,  0},       /* IDSEL 15 - unused */
 149                {25, 26, 27, 28},       /* IDSEL 16 - PCI Slot 1P */
 150                {26, 27, 28, 25},       /* IDSEL 17 - PCI Slot 2P */
 151                {27, 28, 25, 26},       /* IDSEL 18 - PCI Slot 3P */
 152                {26,  0,  0,  0},       /* IDSEL 19 - Enet 2 */
 153                { 0,  0,  0,  0}        /* IDSEL 20 - P2P Bridge */
 154        };
 155
 156        const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
 157        return PCI_IRQ_TABLE_LOOKUP;
 158}
 159
 160static inline int
 161Genesis2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 162{
 163        /* 2600
 164         * Raven 31
 165         * ISA   11
 166         * SCSI  12 - IRQ3
 167         * Univ  13
 168         * eth   14 - IRQ2
 169         * VGA   15 - IRQ4
 170         * PMC1  16 - IRQ9,10,11,12 = PMC1 A-D
 171         * PMC2  17 - IRQ12,9,10,11 = A-D
 172         * SCSI2 18 - IRQ11
 173         * eth2  19 - IRQ10
 174         * PCIX  20 - IRQ9,10,11,12 = PCI A-D
 175         */
 176
 177        /* 2400
 178         * Hawk 31
 179         * ISA  11
 180         * Univ 13
 181         * eth  14 - IRQ2
 182         * PMC1 16 - IRQ9,10,11,12 = PMC A-D
 183         * PMC2 17 - IRQ12,9,10,11 = PMC A-D
 184         * PCIX 20 - IRQ9,10,11,12 = PMC A-D
 185         */
 186
 187        /* 2300
 188         * Raven 31
 189         * ISA   11
 190         * Univ  13
 191         * eth   14 - IRQ2
 192         * PMC1  16 - 9,10,11,12 = A-D
 193         * PMC2  17 - 9,10,11,12 = B,C,D,A
 194         */
 195
 196        static char pci_irq_table[][4] =
 197            /*
 198             *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
 199             *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
 200             *      PCI IDSEL/INTPIN->INTLINE
 201             *         A   B   C   D
 202             */
 203        {
 204                {19,  0,  0,  0},       /* IDSEL 12 - SCSI   */
 205                { 0,  0,  0,  0},       /* IDSEL 13 - Universe PCI - VME */
 206                {18,  0,  0,  0},       /* IDSEL 14 - Enet 1 */
 207                { 0,  0,  0,  0},       /* IDSEL 15 - unused */
 208                {25, 26, 27, 28},       /* IDSEL 16 - PCI/PMC Slot 1P */
 209                {28, 25, 26, 27},       /* IDSEL 17 - PCI/PMC Slot 2P */
 210                {27, 28, 25, 26},       /* IDSEL 18 - PCI Slot 3P */
 211                {26,  0,  0,  0},       /* IDSEL 19 - Enet 2 */
 212                {25, 26, 27, 28}        /* IDSEL 20 - P2P Bridge */
 213        };
 214
 215        const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
 216        return PCI_IRQ_TABLE_LOOKUP;
 217}
 218
 219#define MOTOROLA_CPUTYPE_REG    0x800
 220#define MOTOROLA_BASETYPE_REG   0x803
 221#define MPIC_RAVEN_ID           0x48010000
 222#define MPIC_HAWK_ID            0x48030000
 223#define MOT_PROC2_BIT           0x800
 224
 225static u_char pplus_openpic_initsenses[] __initdata = {
 226        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */
 227        (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_FALCN_ECC_ERR */
 228        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_ETHERNET */
 229        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */
 230        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_GRAPHICS */
 231        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME0 */
 232        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME1 */
 233        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME2 */
 234        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME3 */
 235        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTA */
 236        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTB */
 237        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTC */
 238        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTD */
 239        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG0 */
 240        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG1 */
 241        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),
 242};
 243
 244int mot_entry = -1;
 245int prep_keybd_present = 1;
 246int mot_multi = 0;
 247
 248struct brd_info {
 249        /* 0x100 mask assumes for Raven and Hawk boards that the level/edge
 250         * are set */
 251        int cpu_type;
 252        /* 0x200 if this board has a Hawk chip. */
 253        int base_type;
 254        /* or'ed with 0x80 if this board should be checked for multi CPU */
 255        int max_cpu;
 256        const char *name;
 257        int (*map_irq) (struct pci_dev *, unsigned char, unsigned char);
 258};
 259struct brd_info mot_info[] = {
 260        {0x300, 0x00, 0x00, "MVME 2400", Genesis2_map_irq},
 261        {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", mesquite_map_irq},
 262        {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", sitka_map_irq},
 263        {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", mesquite_map_irq},
 264        {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_map_irq},
 265        {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_map_irq},
 266        {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_map_irq},
 267        {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_map_irq},
 268        {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_map_irq},
 269        {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_map_irq},
 270        {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_map_irq},
 271        {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_map_irq},
 272        {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_map_irq},
 273        {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_map_irq},
 274        {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_map_irq},
 275        {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_map_irq},
 276        {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_map_irq},
 277        {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_map_irq},
 278        {0x000, 0x00, 0x00, "", NULL}
 279};
 280
 281void __init pplus_set_board_type(void)
 282{
 283        unsigned char cpu_type;
 284        unsigned char base_mod;
 285        int entry;
 286        unsigned short devid;
 287        unsigned long *ProcInfo = NULL;
 288
 289        cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
 290        base_mod = inb(MOTOROLA_BASETYPE_REG);
 291        early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
 292
 293        for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
 294                /* Check for Hawk chip */
 295                if (mot_info[entry].cpu_type & 0x200) {
 296                        if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK)
 297                                continue;
 298                } else {
 299                        /* store the system config register for later use. */
 300                        ProcInfo =
 301                            (unsigned long *)ioremap(PPLUS_SYS_CONFIG_REG, 4);
 302
 303                        /* Check non hawk boards */
 304                        if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
 305                                continue;
 306
 307                        if (mot_info[entry].base_type == 0) {
 308                                mot_entry = entry;
 309                                break;
 310                        }
 311
 312                        if (mot_info[entry].base_type != base_mod)
 313                                continue;
 314                }
 315
 316                if (!(mot_info[entry].max_cpu & 0x80)) {
 317                        mot_entry = entry;
 318                        break;
 319                }
 320
 321                /* processor 1 not present and max processor zero indicated */
 322                if ((*ProcInfo & MOT_PROC2_BIT)
 323                    && !(mot_info[entry].max_cpu & 0x7f)) {
 324                        mot_entry = entry;
 325                        break;
 326                }
 327
 328                /* processor 1 present and max processor zero indicated */
 329                if (!(*ProcInfo & MOT_PROC2_BIT)
 330                    && (mot_info[entry].max_cpu & 0x7f)) {
 331                        mot_entry = entry;
 332                        break;
 333                }
 334
 335                /* Indicate to system if this is a multiprocessor board */
 336                if (!(*ProcInfo & MOT_PROC2_BIT))
 337                        mot_multi = 1;
 338        }
 339
 340        if (mot_entry == -1)
 341                /* No particular cpu type found - assume Mesquite (MCP750) */
 342                mot_entry = 1;
 343
 344        Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
 345        ppc_md.pci_map_irq = mot_info[mot_entry].map_irq;
 346}
 347void __init pplus_pib_init(void)
 348{
 349        unsigned char reg;
 350        unsigned short short_reg;
 351
 352        struct pci_dev *dev = NULL;
 353
 354        /*
 355         * Perform specific configuration for the Via Tech or
 356         * or Winbond PCI-ISA-Bridge part.
 357         */
 358        if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
 359                                   PCI_DEVICE_ID_VIA_82C586_1, dev))) {
 360                /*
 361                 * PPCBUG does not set the enable bits
 362                 * for the IDE device. Force them on here.
 363                 */
 364                pci_read_config_byte(dev, 0x40, &reg);
 365
 366                reg |= 0x03;    /* IDE: Chip Enable Bits */
 367                pci_write_config_byte(dev, 0x40, reg);
 368        }
 369
 370        if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
 371                                   PCI_DEVICE_ID_VIA_82C586_2,
 372                                   dev)) && (dev->devfn = 0x5a)) {
 373                /* Force correct USB interrupt */
 374                dev->irq = 11;
 375                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 376        }
 377
 378        if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
 379                                   PCI_DEVICE_ID_WINBOND_83C553, dev))) {
 380                /* Clear PCI Interrupt Routing Control Register. */
 381                short_reg = 0x0000;
 382                pci_write_config_word(dev, 0x44, short_reg);
 383                /* Route IDE interrupts to IRQ 14 */
 384                reg = 0xEE;
 385                pci_write_config_byte(dev, 0x43, reg);
 386        }
 387
 388        if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
 389                                   PCI_DEVICE_ID_WINBOND_82C105, dev))) {
 390                /*
 391                 * Disable LEGIRQ mode so PCI INTS are routed
 392                 * directly to the 8259 and enable both channels
 393                 */
 394                pci_write_config_dword(dev, 0x40, 0x10ff0033);
 395
 396                /* Force correct IDE interrupt */
 397                dev->irq = 14;
 398                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 399        }
 400        pci_dev_put(dev);
 401}
 402
 403void __init pplus_set_VIA_IDE_legacy(void)
 404{
 405        unsigned short vend, dev;
 406
 407        early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
 408        early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
 409
 410        if ((vend == PCI_VENDOR_ID_VIA) &&
 411                        (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
 412                unsigned char temp;
 413
 414                /* put back original "standard" port base addresses */
 415                early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
 416                                         PCI_BASE_ADDRESS_0, 0x1f1);
 417                early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
 418                                         PCI_BASE_ADDRESS_1, 0x3f5);
 419                early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
 420                                         PCI_BASE_ADDRESS_2, 0x171);
 421                early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
 422                                         PCI_BASE_ADDRESS_3, 0x375);
 423                early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
 424                                         PCI_BASE_ADDRESS_4, 0xcc01);
 425
 426                /* put into legacy mode */
 427                early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
 428                                       &temp);
 429                temp &= ~0x05;
 430                early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
 431                                        temp);
 432        }
 433}
 434
 435void pplus_set_VIA_IDE_native(void)
 436{
 437        unsigned short vend, dev;
 438
 439        early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
 440        early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
 441
 442        if ((vend == PCI_VENDOR_ID_VIA) &&
 443                        (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
 444                unsigned char temp;
 445
 446                /* put into native mode */
 447                early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
 448                                       &temp);
 449                temp |= 0x05;
 450                early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
 451                                        temp);
 452        }
 453}
 454
 455void __init pplus_pcibios_fixup(void)
 456{
 457
 458        unsigned char reg;
 459        unsigned short devid;
 460        unsigned char base_mod;
 461
 462        printk(KERN_INFO "Setting PCI interrupts for a \"%s\"\n",
 463                        Motherboard_map_name);
 464
 465        /* Setup the Winbond or Via PIB */
 466        pplus_pib_init();
 467
 468        /* Set up floppy in PS/2 mode */
 469        outb(0x09, SIO_CONFIG_RA);
 470        reg = inb(SIO_CONFIG_RD);
 471        reg = (reg & 0x3F) | 0x40;
 472        outb(reg, SIO_CONFIG_RD);
 473        outb(reg, SIO_CONFIG_RD);       /* Have to write twice to change! */
 474
 475        /* This is a hack.  If this is a 2300 or 2400 mot board then there is
 476         * no keyboard controller and we have to indicate that.
 477         */
 478
 479        early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
 480        base_mod = inb(MOTOROLA_BASETYPE_REG);
 481        if ((devid == PCI_DEVICE_ID_MOTOROLA_HAWK) ||
 482            (base_mod == 0xF9) || (base_mod == 0xFA) || (base_mod == 0xE1))
 483                prep_keybd_present = 0;
 484}
 485
 486void __init pplus_find_bridges(void)
 487{
 488        struct pci_controller *hose;
 489
 490        hose = pcibios_alloc_controller();
 491        if (!hose)
 492                return;
 493
 494        hose->first_busno = 0;
 495        hose->last_busno = 0xff;
 496
 497        hose->pci_mem_offset = PREP_ISA_MEM_BASE;
 498        hose->io_base_virt = (void *)PREP_ISA_IO_BASE;
 499
 500        pci_init_resource(&hose->io_resource, PPLUS_PCI_IO_START,
 501                          PPLUS_PCI_IO_END, IORESOURCE_IO, "PCI host bridge");
 502        pci_init_resource(&hose->mem_resources[0], PPLUS_PROC_PCI_MEM_START,
 503                          PPLUS_PROC_PCI_MEM_END, IORESOURCE_MEM,
 504                          "PCI host bridge");
 505
 506        hose->io_space.start = PPLUS_PCI_IO_START;
 507        hose->io_space.end = PPLUS_PCI_IO_END;
 508        hose->mem_space.start = PPLUS_PCI_MEM_START;
 509        hose->mem_space.end = PPLUS_PCI_MEM_END - HAWK_MPIC_SIZE;
 510
 511        if (hawk_init(hose, PPLUS_HAWK_PPC_REG_BASE, PPLUS_PROC_PCI_MEM_START,
 512                                PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
 513                                PPLUS_PROC_PCI_IO_START, PPLUS_PROC_PCI_IO_END,
 514                                PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1)
 515                        != 0) {
 516                printk(KERN_CRIT "Could not initialize host bridge\n");
 517
 518        }
 519
 520        pplus_set_VIA_IDE_legacy();
 521
 522        hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
 523
 524        ppc_md.pcibios_fixup = pplus_pcibios_fixup;
 525        ppc_md.pci_swizzle = common_swizzle;
 526}
 527
 528static int pplus_show_cpuinfo(struct seq_file *m)
 529{
 530        seq_printf(m, "vendor\t\t: Motorola MCG\n");
 531        seq_printf(m, "machine\t\t: %s\n", Motherboard_map_name);
 532
 533        return 0;
 534}
 535
 536static void __init pplus_setup_arch(void)
 537{
 538        struct pci_controller *hose;
 539
 540        if (ppc_md.progress)
 541                ppc_md.progress("pplus_setup_arch: enter", 0);
 542
 543        /* init to some ~sane value until calibrate_delay() runs */
 544        loops_per_jiffy = 50000000;
 545
 546        if (ppc_md.progress)
 547                ppc_md.progress("pplus_setup_arch: find_bridges", 0);
 548
 549        /* Setup PCI host bridge */
 550        pplus_find_bridges();
 551
 552        hose = pci_bus_to_hose(0);
 553        isa_io_base = (ulong) hose->io_base_virt;
 554
 555        if (ppc_md.progress)
 556                ppc_md.progress("pplus_setup_arch: set_board_type", 0);
 557
 558        pplus_set_board_type();
 559
 560        /* Enable L2.  Assume we don't need to flush -- Cort */
 561        *(unsigned char *)(PPLUS_L2_CONTROL_REG) |= 3;
 562
 563#ifdef CONFIG_BLK_DEV_INITRD
 564        if (initrd_start)
 565                ROOT_DEV = Root_RAM0;
 566        else
 567#endif
 568#ifdef CONFIG_ROOT_NFS
 569                ROOT_DEV = Root_NFS;
 570#else
 571                ROOT_DEV = Root_SDA2;
 572#endif
 573
 574        printk(KERN_INFO "Motorola PowerPlus Platform\n");
 575        printk(KERN_INFO
 576               "Port by MontaVista Software, Inc. (source@mvista.com)\n");
 577
 578#ifdef CONFIG_VGA_CONSOLE
 579        /* remap the VGA memory */
 580        vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE,
 581                                                   0x08000000);
 582        conswitchp = &vga_con;
 583#endif
 584#ifdef CONFIG_PPCBUG_NVRAM
 585        /* Read in NVRAM data */
 586        init_prep_nvram();
 587
 588        /* if no bootargs, look in NVRAM */
 589        if (cmd_line[0] == '\0') {
 590                char *bootargs;
 591                bootargs = prep_nvram_get_var("bootargs");
 592                if (bootargs != NULL) {
 593                        strcpy(cmd_line, bootargs);
 594                        /* again.. */
 595                        strcpy(boot_command_line, cmd_line);
 596                }
 597        }
 598#endif
 599        if (ppc_md.progress)
 600                ppc_md.progress("pplus_setup_arch: exit", 0);
 601}
 602
 603static void pplus_restart(char *cmd)
 604{
 605        unsigned long i = 10000;
 606
 607        local_irq_disable();
 608
 609        /* set VIA IDE controller into native mode */
 610        pplus_set_VIA_IDE_native();
 611
 612        /* set exception prefix high - to the prom */
 613        _nmask_and_or_msr(0, MSR_IP);
 614
 615        /* make sure bit 0 (reset) is a 0 */
 616        outb(inb(0x92) & ~1L, 0x92);
 617        /* signal a reset to system control port A - soft reset */
 618        outb(inb(0x92) | 1, 0x92);
 619
 620        while (i != 0)
 621                i++;
 622        panic("restart failed\n");
 623}
 624
 625static void pplus_halt(void)
 626{
 627        /* set exception prefix high - to the prom */
 628        _nmask_and_or_msr(MSR_EE, MSR_IP);
 629
 630        /* make sure bit 0 (reset) is a 0 */
 631        outb(inb(0x92) & ~1L, 0x92);
 632        /* signal a reset to system control port A - soft reset */
 633        outb(inb(0x92) | 1, 0x92);
 634
 635        while (1) ;
 636        /*
 637         * Not reached
 638         */
 639}
 640
 641static void pplus_power_off(void)
 642{
 643        pplus_halt();
 644}
 645
 646static void __init pplus_init_IRQ(void)
 647{
 648        int i;
 649
 650        if (ppc_md.progress)
 651                ppc_md.progress("init_irq: enter", 0);
 652
 653        OpenPIC_InitSenses = pplus_openpic_initsenses;
 654        OpenPIC_NumInitSenses = sizeof(pplus_openpic_initsenses);
 655
 656        if (OpenPIC_Addr != NULL) {
 657
 658                openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
 659                openpic_init(NUM_8259_INTERRUPTS);
 660                openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
 661                                        i8259_irq);
 662                ppc_md.get_irq = openpic_get_irq;
 663        }
 664
 665        i8259_init(0, 0);
 666
 667        if (ppc_md.progress)
 668                ppc_md.progress("init_irq: exit", 0);
 669}
 670
 671#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 672/*
 673 * IDE stuff.
 674 */
 675static int pplus_ide_default_irq(unsigned long base)
 676{
 677        switch (base) {
 678        case 0x1f0:
 679                return 14;
 680        case 0x170:
 681                return 15;
 682        default:
 683                return 0;
 684        }
 685}
 686
 687static unsigned long pplus_ide_default_io_base(int index)
 688{
 689        switch (index) {
 690        case 0:
 691                return 0x1f0;
 692        case 1:
 693                return 0x170;
 694        default:
 695                return 0;
 696        }
 697}
 698
 699static void __init
 700pplus_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
 701                          unsigned long ctrl_port, int *irq)
 702{
 703        unsigned long reg = data_port;
 704        int i;
 705
 706        for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 707                hw->io_ports[i] = reg;
 708                reg += 1;
 709        }
 710
 711        if (ctrl_port)
 712                hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
 713        else
 714                hw->io_ports[IDE_CONTROL_OFFSET] =
 715                    hw->io_ports[IDE_DATA_OFFSET] + 0x206;
 716
 717        if (irq != NULL)
 718                *irq = pplus_ide_default_irq(data_port);
 719}
 720#endif
 721
 722#ifdef CONFIG_SMP
 723/* PowerPlus (MTX) support */
 724static int __init smp_pplus_probe(void)
 725{
 726        extern int mot_multi;
 727
 728        if (mot_multi) {
 729                openpic_request_IPIs();
 730                smp_hw_index[1] = 1;
 731                return 2;
 732        }
 733
 734        return 1;
 735}
 736
 737static void __init smp_pplus_kick_cpu(int nr)
 738{
 739        *(unsigned long *)KERNELBASE = nr;
 740        asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory");
 741        printk(KERN_INFO "CPU1 reset, waiting\n");
 742}
 743
 744static void __init smp_pplus_setup_cpu(int cpu_nr)
 745{
 746        if (OpenPIC_Addr)
 747                do_openpic_setup_cpu();
 748}
 749
 750static struct smp_ops_t pplus_smp_ops = {
 751        smp_openpic_message_pass,
 752        smp_pplus_probe,
 753        smp_pplus_kick_cpu,
 754        smp_pplus_setup_cpu,
 755        .give_timebase = smp_generic_give_timebase,
 756        .take_timebase = smp_generic_take_timebase,
 757};
 758#endif                          /* CONFIG_SMP */
 759
 760#ifdef DUMP_DBATS
 761static void print_dbat(int idx, u32 bat)
 762{
 763
 764        char str[64];
 765
 766        sprintf(str, "DBAT%c%c = 0x%08x\n",
 767                (char)((idx - DBAT0U) / 2) + '0', (idx & 1) ? 'L' : 'U', bat);
 768        ppc_md.progress(str, 0);
 769}
 770
 771#define DUMP_DBAT(x) \
 772        do { \
 773        u32 __temp = mfspr(x);\
 774        print_dbat(x, __temp); \
 775        } while (0)
 776
 777static void dump_dbats(void)
 778{
 779        if (ppc_md.progress) {
 780                DUMP_DBAT(DBAT0U);
 781                DUMP_DBAT(DBAT0L);
 782                DUMP_DBAT(DBAT1U);
 783                DUMP_DBAT(DBAT1L);
 784                DUMP_DBAT(DBAT2U);
 785                DUMP_DBAT(DBAT2L);
 786                DUMP_DBAT(DBAT3U);
 787                DUMP_DBAT(DBAT3L);
 788        }
 789}
 790#endif
 791
 792static unsigned long __init pplus_find_end_of_memory(void)
 793{
 794        unsigned long total;
 795
 796        if (ppc_md.progress)
 797                ppc_md.progress("pplus_find_end_of_memory", 0);
 798
 799#ifdef DUMP_DBATS
 800        dump_dbats();
 801#endif
 802
 803        total = hawk_get_mem_size(PPLUS_HAWK_SMC_BASE);
 804        return (total);
 805}
 806
 807static void __init pplus_map_io(void)
 808{
 809        io_block_mapping(PPLUS_ISA_IO_BASE, PPLUS_ISA_IO_BASE, 0x10000000,
 810                         _PAGE_IO);
 811        io_block_mapping(0xfef80000, 0xfef80000, 0x00080000, _PAGE_IO);
 812}
 813
 814static void __init pplus_init2(void)
 815{
 816#ifdef CONFIG_NVRAM
 817        request_region(PREP_NVRAM_AS0, 0x8, "nvram");
 818#endif
 819        request_region(0x20, 0x20, "pic1");
 820        request_region(0xa0, 0x20, "pic2");
 821        request_region(0x00, 0x20, "dma1");
 822        request_region(0x40, 0x20, "timer");
 823        request_region(0x80, 0x10, "dma page reg");
 824        request_region(0xc0, 0x20, "dma2");
 825}
 826
 827/*
 828 * Set BAT 2 to access 0x8000000 so progress messages will work and set BAT 3
 829 * to 0xf0000000 to access Falcon/Raven or Hawk registers
 830 */
 831static __inline__ void pplus_set_bat(void)
 832{
 833        /* wait for all outstanding memory accesses to complete */
 834        mb();
 835
 836        /* setup DBATs */
 837        mtspr(SPRN_DBAT2U, 0x80001ffe);
 838        mtspr(SPRN_DBAT2L, 0x8000002a);
 839        mtspr(SPRN_DBAT3U, 0xf0001ffe);
 840        mtspr(SPRN_DBAT3L, 0xf000002a);
 841
 842        /* wait for updates */
 843        mb();
 844}
 845
 846void __init
 847platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 848              unsigned long r6, unsigned long r7)
 849{
 850        parse_bootinfo(find_bootinfo());
 851
 852        /* Map in board regs, etc. */
 853        pplus_set_bat();
 854
 855        isa_io_base = PREP_ISA_IO_BASE;
 856        isa_mem_base = PREP_ISA_MEM_BASE;
 857        pci_dram_offset = PREP_PCI_DRAM_OFFSET;
 858        ISA_DMA_THRESHOLD = 0x00ffffff;
 859        DMA_MODE_READ = 0x44;
 860        DMA_MODE_WRITE = 0x48;
 861        ppc_do_canonicalize_irqs = 1;
 862
 863        ppc_md.setup_arch = pplus_setup_arch;
 864        ppc_md.show_cpuinfo = pplus_show_cpuinfo;
 865        ppc_md.init_IRQ = pplus_init_IRQ;
 866        /* this gets changed later on if we have an OpenPIC -- Cort */
 867        ppc_md.get_irq = i8259_irq;
 868        ppc_md.init = pplus_init2;
 869
 870        ppc_md.restart = pplus_restart;
 871        ppc_md.power_off = pplus_power_off;
 872        ppc_md.halt = pplus_halt;
 873
 874        TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1,
 875                  PREP_NVRAM_DATA, 8);
 876
 877        ppc_md.time_init = todc_time_init;
 878        ppc_md.set_rtc_time = todc_set_rtc_time;
 879        ppc_md.get_rtc_time = todc_get_rtc_time;
 880        ppc_md.calibrate_decr = todc_calibrate_decr;
 881        ppc_md.nvram_read_val = todc_m48txx_read_val;
 882        ppc_md.nvram_write_val = todc_m48txx_write_val;
 883
 884        ppc_md.find_end_of_memory = pplus_find_end_of_memory;
 885        ppc_md.setup_io_mappings = pplus_map_io;
 886
 887#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 888        ppc_ide_md.default_irq = pplus_ide_default_irq;
 889        ppc_ide_md.default_io_base = pplus_ide_default_io_base;
 890        ppc_ide_md.ide_init_hwif = pplus_ide_init_hwif_ports;
 891#endif
 892
 893#ifdef CONFIG_SERIAL_TEXT_DEBUG
 894        ppc_md.progress = gen550_progress;
 895#endif                          /* CONFIG_SERIAL_TEXT_DEBUG */
 896#ifdef CONFIG_KGDB
 897        ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
 898#endif
 899#ifdef CONFIG_SMP
 900        smp_ops = &pplus_smp_ops;
 901#endif                          /* CONFIG_SMP */
 902}
 903
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.