linux/arch/i386/mach-es7000/es7000plat.c
<<
>>
Prefs
   1/*
   2 * Written by: Garry Forsgren, Unisys Corporation
   3 *             Natalie Protasevich, Unisys Corporation
   4 * This file contains the code to configure and interface
   5 * with Unisys ES7000 series hardware system manager.
   6 *
   7 * Copyright (c) 2003 Unisys Corporation.  All Rights Reserved.
   8 *
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms of version 2 of the GNU General Public License as
  11 * published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it would be useful, but
  14 * WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16 *
  17 * You should have received a copy of the GNU General Public License along
  18 * with this program; if not, write the Free Software Foundation, Inc., 59
  19 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
  20 *
  21 * Contact information: Unisys Corporation, Township Line & Union Meeting
  22 * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
  23 *
  24 * http://www.unisys.com
  25 */
  26
  27#include <linux/module.h>
  28#include <linux/types.h>
  29#include <linux/kernel.h>
  30#include <linux/smp.h>
  31#include <linux/string.h>
  32#include <linux/spinlock.h>
  33#include <linux/errno.h>
  34#include <linux/notifier.h>
  35#include <linux/reboot.h>
  36#include <linux/init.h>
  37#include <linux/acpi.h>
  38#include <asm/io.h>
  39#include <asm/nmi.h>
  40#include <asm/smp.h>
  41#include <asm/apicdef.h>
  42#include "es7000.h"
  43#include <mach_mpparse.h>
  44
  45/*
  46 * ES7000 Globals
  47 */
  48
  49volatile unsigned long  *psai = NULL;
  50struct mip_reg          *mip_reg;
  51struct mip_reg          *host_reg;
  52int                     mip_port;
  53unsigned long           mip_addr, host_addr;
  54
  55/*
  56 * GSI override for ES7000 platforms.
  57 */
  58
  59static unsigned int base;
  60
  61static int
  62es7000_rename_gsi(int ioapic, int gsi)
  63{
  64        if (es7000_plat == ES7000_ZORRO)
  65                return gsi;
  66
  67        if (!base) {
  68                int i;
  69                for (i = 0; i < nr_ioapics; i++)
  70                        base += nr_ioapic_registers[i];
  71        }
  72
  73        if (!ioapic && (gsi < 16)) 
  74                gsi += base;
  75        return gsi;
  76}
  77
  78void __init
  79setup_unisys(void)
  80{
  81        /*
  82         * Determine the generation of the ES7000 currently running.
  83         *
  84         * es7000_plat = 1 if the machine is a 5xx ES7000 box
  85         * es7000_plat = 2 if the machine is a x86_64 ES7000 box
  86         *
  87         */
  88        if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
  89                es7000_plat = ES7000_ZORRO;
  90        else
  91                es7000_plat = ES7000_CLASSIC;
  92        ioapic_renumber_irq = es7000_rename_gsi;
  93}
  94
  95/*
  96 * Parse the OEM Table
  97 */
  98
  99int __init
 100parse_unisys_oem (char *oemptr)
 101{
 102        int                     i;
 103        int                     success = 0;
 104        unsigned char           type, size;
 105        unsigned long           val;
 106        char                    *tp = NULL;
 107        struct psai             *psaip = NULL;
 108        struct mip_reg_info     *mi;
 109        struct mip_reg          *host, *mip;
 110
 111        tp = oemptr;
 112
 113        tp += 8;
 114
 115        for (i=0; i <= 6; i++) {
 116                type = *tp++;
 117                size = *tp++;
 118                tp -= 2;
 119                switch (type) {
 120                case MIP_REG:
 121                        mi = (struct mip_reg_info *)tp;
 122                        val = MIP_RD_LO(mi->host_reg);
 123                        host_addr = val;
 124                        host = (struct mip_reg *)val;
 125                        host_reg = __va(host);
 126                        val = MIP_RD_LO(mi->mip_reg);
 127                        mip_port = MIP_PORT(mi->mip_info);
 128                        mip_addr = val;
 129                        mip = (struct mip_reg *)val;
 130                        mip_reg = __va(mip);
 131                        Dprintk("es7000_mipcfg: host_reg = 0x%lx \n",
 132                                (unsigned long)host_reg);
 133                        Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n",
 134                                (unsigned long)mip_reg);
 135                        success++;
 136                        break;
 137                case MIP_PSAI_REG:
 138                        psaip = (struct psai *)tp;
 139                        if (tp != NULL) {
 140                                if (psaip->addr)
 141                                        psai = __va(psaip->addr);
 142                                else
 143                                        psai = NULL;
 144                                success++;
 145                        }
 146                        break;
 147                default:
 148                        break;
 149                }
 150                tp += size;
 151        }
 152
 153        if (success < 2) {
 154                es7000_plat = NON_UNISYS;
 155        } else
 156                setup_unisys();
 157        return es7000_plat;
 158}
 159
 160#ifdef CONFIG_ACPI
 161int __init
 162find_unisys_acpi_oem_table(unsigned long *oem_addr)
 163{
 164        struct acpi_table_header *header = NULL;
 165        int i = 0;
 166        while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) {
 167                if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) {
 168                        struct oem_table *t = (struct oem_table *)header;
 169                        *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr,
 170                                                                    t->OEMTableSize);
 171                        return 0;
 172                }
 173        }
 174        return -1;
 175}
 176#endif
 177
 178/*
 179 * This file also gets compiled if CONFIG_X86_GENERICARCH is set. Generic
 180 * arch already has got following function definitions (asm-generic/es7000.c)
 181 * hence no need to define these for that case.
 182 */
 183#ifndef CONFIG_X86_GENERICARCH
 184void es7000_sw_apic(void);
 185void __init enable_apic_mode(void)
 186{
 187        es7000_sw_apic();
 188        return;
 189}
 190
 191__init int mps_oem_check(struct mp_config_table *mpc, char *oem,
 192                char *productid)
 193{
 194        if (mpc->mpc_oemptr) {
 195                struct mp_config_oemtable *oem_table =
 196                        (struct mp_config_oemtable *)mpc->mpc_oemptr;
 197                if (!strncmp(oem, "UNISYS", 6))
 198                        return parse_unisys_oem((char *)oem_table);
 199        }
 200        return 0;
 201}
 202#ifdef CONFIG_ACPI
 203/* Hook from generic ACPI tables.c */
 204int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 205{
 206        unsigned long oem_addr;
 207        if (!find_unisys_acpi_oem_table(&oem_addr)) {
 208                if (es7000_check_dsdt())
 209                        return parse_unisys_oem((char *)oem_addr);
 210                else {
 211                        setup_unisys();
 212                        return 1;
 213                }
 214        }
 215        return 0;
 216}
 217#else
 218int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 219{
 220        return 0;
 221}
 222#endif
 223#endif /* COFIG_X86_GENERICARCH */
 224
 225static void
 226es7000_spin(int n)
 227{
 228        int i = 0;
 229
 230        while (i++ < n)
 231                rep_nop();
 232}
 233
 234static int __init
 235es7000_mip_write(struct mip_reg *mip_reg)
 236{
 237        int                     status = 0;
 238        int                     spin;
 239
 240        spin = MIP_SPIN;
 241        while (((unsigned long long)host_reg->off_38 &
 242                (unsigned long long)MIP_VALID) != 0) {
 243                        if (--spin <= 0) {
 244                                printk("es7000_mip_write: Timeout waiting for Host Valid Flag");
 245                                return -1;
 246                        }
 247                es7000_spin(MIP_SPIN);
 248        }
 249
 250        memcpy(host_reg, mip_reg, sizeof(struct mip_reg));
 251        outb(1, mip_port);
 252
 253        spin = MIP_SPIN;
 254
 255        while (((unsigned long long)mip_reg->off_38 &
 256                (unsigned long long)MIP_VALID) == 0) {
 257                if (--spin <= 0) {
 258                        printk("es7000_mip_write: Timeout waiting for MIP Valid Flag");
 259                        return -1;
 260                }
 261                es7000_spin(MIP_SPIN);
 262        }
 263
 264        status = ((unsigned long long)mip_reg->off_0 &
 265                (unsigned long long)0xffff0000000000ULL) >> 48;
 266        mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 &
 267                (unsigned long long)~MIP_VALID);
 268        return status;
 269}
 270
 271int
 272es7000_start_cpu(int cpu, unsigned long eip)
 273{
 274        unsigned long vect = 0, psaival = 0;
 275
 276        if (psai == NULL)
 277                return -1;
 278
 279        vect = ((unsigned long)__pa(eip)/0x1000) << 16;
 280        psaival = (0x1000000 | vect | cpu);
 281
 282        while (*psai & 0x1000000)
 283                ;
 284
 285        *psai = psaival;
 286
 287        return 0;
 288
 289}
 290
 291int
 292es7000_stop_cpu(int cpu)
 293{
 294        int startup;
 295
 296        if (psai == NULL)
 297                return -1;
 298
 299        startup= (0x1000000 | cpu);
 300
 301        while ((*psai & 0xff00ffff) != startup)
 302                ;
 303
 304        startup = (*psai & 0xff0000) >> 16;
 305        *psai &= 0xffffff;
 306
 307        return 0;
 308
 309}
 310
 311void __init
 312es7000_sw_apic()
 313{
 314        if (es7000_plat) {
 315                int mip_status;
 316                struct mip_reg es7000_mip_reg;
 317
 318                printk("ES7000: Enabling APIC mode.\n");
 319                memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
 320                es7000_mip_reg.off_0 = MIP_SW_APIC;
 321                es7000_mip_reg.off_38 = (MIP_VALID);
 322                while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
 323                        printk("es7000_sw_apic: command failed, status = %x\n",
 324                                mip_status);
 325                return;
 326        }
 327}
 328
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.