linux/arch/powerpc/platforms/powermac/nvram.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)
   3 *
   4 *  This program is free software; you can redistribute it and/or
   5 *  modify it under the terms of the GNU General Public License
   6 *  as published by the Free Software Foundation; either version
   7 *  2 of the License, or (at your option) any later version.
   8 *
   9 *  Todo: - add support for the OF persistent properties
  10 */
  11#include <linux/export.h>
  12#include <linux/kernel.h>
  13#include <linux/stddef.h>
  14#include <linux/string.h>
  15#include <linux/nvram.h>
  16#include <linux/init.h>
  17#include <linux/delay.h>
  18#include <linux/errno.h>
  19#include <linux/adb.h>
  20#include <linux/pmu.h>
  21#include <linux/bootmem.h>
  22#include <linux/completion.h>
  23#include <linux/spinlock.h>
  24#include <asm/sections.h>
  25#include <asm/io.h>
  26#include <asm/prom.h>
  27#include <asm/machdep.h>
  28#include <asm/nvram.h>
  29
  30#include "pmac.h"
  31
  32#define DEBUG
  33
  34#ifdef DEBUG
  35#define DBG(x...) printk(x)
  36#else
  37#define DBG(x...)
  38#endif
  39
  40#define NVRAM_SIZE              0x2000  /* 8kB of non-volatile RAM */
  41
  42#define CORE99_SIGNATURE        0x5a
  43#define CORE99_ADLER_START      0x14
  44
  45/* On Core99, nvram is either a sharp, a micron or an AMD flash */
  46#define SM_FLASH_STATUS_DONE    0x80
  47#define SM_FLASH_STATUS_ERR     0x38
  48
  49#define SM_FLASH_CMD_ERASE_CONFIRM      0xd0
  50#define SM_FLASH_CMD_ERASE_SETUP        0x20
  51#define SM_FLASH_CMD_RESET              0xff
  52#define SM_FLASH_CMD_WRITE_SETUP        0x40
  53#define SM_FLASH_CMD_CLEAR_STATUS       0x50
  54#define SM_FLASH_CMD_READ_STATUS        0x70
  55
  56/* CHRP NVRAM header */
  57struct chrp_header {
  58  u8            signature;
  59  u8            cksum;
  60  u16           len;
  61  char          name[12];
  62  u8            data[0];
  63};
  64
  65struct core99_header {
  66  struct chrp_header    hdr;
  67  u32                   adler;
  68  u32                   generation;
  69  u32                   reserved[2];
  70};
  71
  72/*
  73 * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
  74 */
  75static int nvram_naddrs;
  76static volatile unsigned char __iomem *nvram_data;
  77static int is_core_99;
  78static int core99_bank = 0;
  79static int nvram_partitions[3];
  80// XXX Turn that into a sem
  81static DEFINE_RAW_SPINLOCK(nv_lock);
  82
  83static int (*core99_write_bank)(int bank, u8* datas);
  84static int (*core99_erase_bank)(int bank);
  85
  86static char *nvram_image;
  87
  88
  89static unsigned char core99_nvram_read_byte(int addr)
  90{
  91        if (nvram_image == NULL)
  92                return 0xff;
  93        return nvram_image[addr];
  94}
  95
  96static void core99_nvram_write_byte(int addr, unsigned char val)
  97{
  98        if (nvram_image == NULL)
  99                return;
 100        nvram_image[addr] = val;
 101}
 102
 103static ssize_t core99_nvram_read(char *buf, size_t count, loff_t *index)
 104{
 105        int i;
 106
 107        if (nvram_image == NULL)
 108                return -ENODEV;
 109        if (*index > NVRAM_SIZE)
 110                return 0;
 111
 112        i = *index;
 113        if (i + count > NVRAM_SIZE)
 114                count = NVRAM_SIZE - i;
 115
 116        memcpy(buf, &nvram_image[i], count);
 117        *index = i + count;
 118        return count;
 119}
 120
 121static ssize_t core99_nvram_write(char *buf, size_t count, loff_t *index)
 122{
 123        int i;
 124
 125        if (nvram_image == NULL)
 126                return -ENODEV;
 127        if (*index > NVRAM_SIZE)
 128                return 0;
 129
 130        i = *index;
 131        if (i + count > NVRAM_SIZE)
 132                count = NVRAM_SIZE - i;
 133
 134        memcpy(&nvram_image[i], buf, count);
 135        *index = i + count;
 136        return count;
 137}
 138
 139static ssize_t core99_nvram_size(void)
 140{
 141        if (nvram_image == NULL)
 142                return -ENODEV;
 143        return NVRAM_SIZE;
 144}
 145
 146#ifdef CONFIG_PPC32
 147static volatile unsigned char __iomem *nvram_addr;
 148static int nvram_mult;
 149
 150static unsigned char direct_nvram_read_byte(int addr)
 151{
 152        return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
 153}
 154
 155static void direct_nvram_write_byte(int addr, unsigned char val)
 156{
 157        out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
 158}
 159
 160
 161static unsigned char indirect_nvram_read_byte(int addr)
 162{
 163        unsigned char val;
 164        unsigned long flags;
 165
 166        raw_spin_lock_irqsave(&nv_lock, flags);
 167        out_8(nvram_addr, addr >> 5);
 168        val = in_8(&nvram_data[(addr & 0x1f) << 4]);
 169        raw_spin_unlock_irqrestore(&nv_lock, flags);
 170
 171        return val;
 172}
 173
 174static void indirect_nvram_write_byte(int addr, unsigned char val)
 175{
 176        unsigned long flags;
 177
 178        raw_spin_lock_irqsave(&nv_lock, flags);
 179        out_8(nvram_addr, addr >> 5);
 180        out_8(&nvram_data[(addr & 0x1f) << 4], val);
 181        raw_spin_unlock_irqrestore(&nv_lock, flags);
 182}
 183
 184
 185#ifdef CONFIG_ADB_PMU
 186
 187static void pmu_nvram_complete(struct adb_request *req)
 188{
 189        if (req->arg)
 190                complete((struct completion *)req->arg);
 191}
 192
 193static unsigned char pmu_nvram_read_byte(int addr)
 194{
 195        struct adb_request req;
 196        DECLARE_COMPLETION_ONSTACK(req_complete);
 197        
 198        req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
 199        if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
 200                        (addr >> 8) & 0xff, addr & 0xff))
 201                return 0xff;
 202        if (system_state == SYSTEM_RUNNING)
 203                wait_for_completion(&req_complete);
 204        while (!req.complete)
 205                pmu_poll();
 206        return req.reply[0];
 207}
 208
 209static void pmu_nvram_write_byte(int addr, unsigned char val)
 210{
 211        struct adb_request req;
 212        DECLARE_COMPLETION_ONSTACK(req_complete);
 213        
 214        req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
 215        if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
 216                        (addr >> 8) & 0xff, addr & 0xff, val))
 217                return;
 218        if (system_state == SYSTEM_RUNNING)
 219                wait_for_completion(&req_complete);
 220        while (!req.complete)
 221                pmu_poll();
 222}
 223
 224#endif /* CONFIG_ADB_PMU */
 225#endif /* CONFIG_PPC32 */
 226
 227static u8 chrp_checksum(struct chrp_header* hdr)
 228{
 229        u8 *ptr;
 230        u16 sum = hdr->signature;
 231        for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
 232                sum += *ptr;
 233        while (sum > 0xFF)
 234                sum = (sum & 0xFF) + (sum>>8);
 235        return sum;
 236}
 237
 238static u32 core99_calc_adler(u8 *buffer)
 239{
 240        int cnt;
 241        u32 low, high;
 242
 243        buffer += CORE99_ADLER_START;
 244        low = 1;
 245        high = 0;
 246        for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
 247                if ((cnt % 5000) == 0) {
 248                        high  %= 65521UL;
 249                        high %= 65521UL;
 250                }
 251                low += buffer[cnt];
 252                high += low;
 253        }
 254        low  %= 65521UL;
 255        high %= 65521UL;
 256
 257        return (high << 16) | low;
 258}
 259
 260static u32 core99_check(u8* datas)
 261{
 262        struct core99_header* hdr99 = (struct core99_header*)datas;
 263
 264        if (hdr99->hdr.signature != CORE99_SIGNATURE) {
 265                DBG("Invalid signature\n");
 266                return 0;
 267        }
 268        if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
 269                DBG("Invalid checksum\n");
 270                return 0;
 271        }
 272        if (hdr99->adler != core99_calc_adler(datas)) {
 273                DBG("Invalid adler\n");
 274                return 0;
 275        }
 276        return hdr99->generation;
 277}
 278
 279static int sm_erase_bank(int bank)
 280{
 281        int stat;
 282        unsigned long timeout;
 283
 284        u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 285
 286        DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
 287
 288        out_8(base, SM_FLASH_CMD_ERASE_SETUP);
 289        out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
 290        timeout = 0;
 291        do {
 292                if (++timeout > 1000000) {
 293                        printk(KERN_ERR "nvram: Sharp/Micron flash erase timeout !\n");
 294                        break;
 295                }
 296                out_8(base, SM_FLASH_CMD_READ_STATUS);
 297                stat = in_8(base);
 298        } while (!(stat & SM_FLASH_STATUS_DONE));
 299
 300        out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
 301        out_8(base, SM_FLASH_CMD_RESET);
 302
 303        if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
 304                printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
 305                return -ENXIO;
 306        }
 307        return 0;
 308}
 309
 310static int sm_write_bank(int bank, u8* datas)
 311{
 312        int i, stat = 0;
 313        unsigned long timeout;
 314
 315        u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 316
 317        DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
 318
 319        for (i=0; i<NVRAM_SIZE; i++) {
 320                out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
 321                udelay(1);
 322                out_8(base+i, datas[i]);
 323                timeout = 0;
 324                do {
 325                        if (++timeout > 1000000) {
 326                                printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
 327                                break;
 328                        }
 329                        out_8(base, SM_FLASH_CMD_READ_STATUS);
 330                        stat = in_8(base);
 331                } while (!(stat & SM_FLASH_STATUS_DONE));
 332                if (!(stat & SM_FLASH_STATUS_DONE))
 333                        break;
 334        }
 335        out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
 336        out_8(base, SM_FLASH_CMD_RESET);
 337        if (memcmp(base, datas, NVRAM_SIZE)) {
 338                printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
 339                return -ENXIO;
 340        }
 341        return 0;
 342}
 343
 344static int amd_erase_bank(int bank)
 345{
 346        int stat = 0;
 347        unsigned long timeout;
 348
 349        u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 350
 351        DBG("nvram: AMD Erasing bank %d...\n", bank);
 352
 353        /* Unlock 1 */
 354        out_8(base+0x555, 0xaa);
 355        udelay(1);
 356        /* Unlock 2 */
 357        out_8(base+0x2aa, 0x55);
 358        udelay(1);
 359
 360        /* Sector-Erase */
 361        out_8(base+0x555, 0x80);
 362        udelay(1);
 363        out_8(base+0x555, 0xaa);
 364        udelay(1);
 365        out_8(base+0x2aa, 0x55);
 366        udelay(1);
 367        out_8(base, 0x30);
 368        udelay(1);
 369
 370        timeout = 0;
 371        do {
 372                if (++timeout > 1000000) {
 373                        printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
 374                        break;
 375                }
 376                stat = in_8(base) ^ in_8(base);
 377        } while (stat != 0);
 378        
 379        /* Reset */
 380        out_8(base, 0xf0);
 381        udelay(1);
 382
 383        if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
 384                printk(KERN_ERR "nvram: AMD flash erase failed !\n");
 385                return -ENXIO;
 386        }
 387        return 0;
 388}
 389
 390static int amd_write_bank(int bank, u8* datas)
 391{
 392        int i, stat = 0;
 393        unsigned long timeout;
 394
 395        u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 396
 397        DBG("nvram: AMD Writing bank %d...\n", bank);
 398
 399        for (i=0; i<NVRAM_SIZE; i++) {
 400                /* Unlock 1 */
 401                out_8(base+0x555, 0xaa);
 402                udelay(1);
 403                /* Unlock 2 */
 404                out_8(base+0x2aa, 0x55);
 405                udelay(1);
 406
 407                /* Write single word */
 408                out_8(base+0x555, 0xa0);
 409                udelay(1);
 410                out_8(base+i, datas[i]);
 411                
 412                timeout = 0;
 413                do {
 414                        if (++timeout > 1000000) {
 415                                printk(KERN_ERR "nvram: AMD flash write timeout !\n");
 416                                break;
 417                        }
 418                        stat = in_8(base) ^ in_8(base);
 419                } while (stat != 0);
 420                if (stat != 0)
 421                        break;
 422        }
 423
 424        /* Reset */
 425        out_8(base, 0xf0);
 426        udelay(1);
 427
 428        if (memcmp(base, datas, NVRAM_SIZE)) {
 429                printk(KERN_ERR "nvram: AMD flash write failed !\n");
 430                return -ENXIO;
 431        }
 432        return 0;
 433}
 434
 435static void __init lookup_partitions(void)
 436{
 437        u8 buffer[17];
 438        int i, offset;
 439        struct chrp_header* hdr;
 440
 441        if (pmac_newworld) {
 442                nvram_partitions[pmac_nvram_OF] = -1;
 443                nvram_partitions[pmac_nvram_XPRAM] = -1;
 444                nvram_partitions[pmac_nvram_NR] = -1;
 445                hdr = (struct chrp_header *)buffer;
 446
 447                offset = 0;
 448                buffer[16] = 0;
 449                do {
 450                        for (i=0;i<16;i++)
 451                                buffer[i] = ppc_md.nvram_read_val(offset+i);
 452                        if (!strcmp(hdr->name, "common"))
 453                                nvram_partitions[pmac_nvram_OF] = offset + 0x10;
 454                        if (!strcmp(hdr->name, "APL,MacOS75")) {
 455                                nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
 456                                nvram_partitions[pmac_nvram_NR] = offset + 0x110;
 457                        }
 458                        offset += (hdr->len * 0x10);
 459                } while(offset < NVRAM_SIZE);
 460        } else {
 461                nvram_partitions[pmac_nvram_OF] = 0x1800;
 462                nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
 463                nvram_partitions[pmac_nvram_NR] = 0x1400;
 464        }
 465        DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
 466        DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
 467        DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
 468}
 469
 470static void core99_nvram_sync(void)
 471{
 472        struct core99_header* hdr99;
 473        unsigned long flags;
 474
 475        if (!is_core_99 || !nvram_data || !nvram_image)
 476                return;
 477
 478        raw_spin_lock_irqsave(&nv_lock, flags);
 479        if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
 480                NVRAM_SIZE))
 481                goto bail;
 482
 483        DBG("Updating nvram...\n");
 484
 485        hdr99 = (struct core99_header*)nvram_image;
 486        hdr99->generation++;
 487        hdr99->hdr.signature = CORE99_SIGNATURE;
 488        hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
 489        hdr99->adler = core99_calc_adler(nvram_image);
 490        core99_bank = core99_bank ? 0 : 1;
 491        if (core99_erase_bank)
 492                if (core99_erase_bank(core99_bank)) {
 493                        printk("nvram: Error erasing bank %d\n", core99_bank);
 494                        goto bail;
 495                }
 496        if (core99_write_bank)
 497                if (core99_write_bank(core99_bank, nvram_image))
 498                        printk("nvram: Error writing bank %d\n", core99_bank);
 499 bail:
 500        raw_spin_unlock_irqrestore(&nv_lock, flags);
 501
 502#ifdef DEBUG
 503        mdelay(2000);
 504#endif
 505}
 506
 507static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
 508{
 509        int i;
 510        u32 gen_bank0, gen_bank1;
 511
 512        if (nvram_naddrs < 1) {
 513                printk(KERN_ERR "nvram: no address\n");
 514                return -EINVAL;
 515        }
 516        nvram_image = alloc_bootmem(NVRAM_SIZE);
 517        if (nvram_image == NULL) {
 518                printk(KERN_ERR "nvram: can't allocate ram image\n");
 519                return -ENOMEM;
 520        }
 521        nvram_data = ioremap(addr, NVRAM_SIZE*2);
 522        nvram_naddrs = 1; /* Make sure we get the correct case */
 523
 524        DBG("nvram: Checking bank 0...\n");
 525
 526        gen_bank0 = core99_check((u8 *)nvram_data);
 527        gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
 528        core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
 529
 530        DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
 531        DBG("nvram: Active bank is: %d\n", core99_bank);
 532
 533        for (i=0; i<NVRAM_SIZE; i++)
 534                nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
 535
 536        ppc_md.nvram_read_val   = core99_nvram_read_byte;
 537        ppc_md.nvram_write_val  = core99_nvram_write_byte;
 538        ppc_md.nvram_read       = core99_nvram_read;
 539        ppc_md.nvram_write      = core99_nvram_write;
 540        ppc_md.nvram_size       = core99_nvram_size;
 541        ppc_md.nvram_sync       = core99_nvram_sync;
 542        ppc_md.machine_shutdown = core99_nvram_sync;
 543        /* 
 544         * Maybe we could be smarter here though making an exclusive list
 545         * of known flash chips is a bit nasty as older OF didn't provide us
 546         * with a useful "compatible" entry. A solution would be to really
 547         * identify the chip using flash id commands and base ourselves on
 548         * a list of known chips IDs
 549         */
 550        if (of_device_is_compatible(dp, "amd-0137")) {
 551                core99_erase_bank = amd_erase_bank;
 552                core99_write_bank = amd_write_bank;
 553        } else {
 554                core99_erase_bank = sm_erase_bank;
 555                core99_write_bank = sm_write_bank;
 556        }
 557        return 0;
 558}
 559
 560int __init pmac_nvram_init(void)
 561{
 562        struct device_node *dp;
 563        struct resource r1, r2;
 564        unsigned int s1 = 0, s2 = 0;
 565        int err = 0;
 566
 567        nvram_naddrs = 0;
 568
 569        dp = of_find_node_by_name(NULL, "nvram");
 570        if (dp == NULL) {
 571                printk(KERN_ERR "Can't find NVRAM device\n");
 572                return -ENODEV;
 573        }
 574
 575        /* Try to obtain an address */
 576        if (of_address_to_resource(dp, 0, &r1) == 0) {
 577                nvram_naddrs = 1;
 578                s1 = resource_size(&r1);
 579                if (of_address_to_resource(dp, 1, &r2) == 0) {
 580                        nvram_naddrs = 2;
 581                        s2 = resource_size(&r2);
 582                }
 583        }
 584
 585        is_core_99 = of_device_is_compatible(dp, "nvram,flash");
 586        if (is_core_99) {
 587                err = core99_nvram_setup(dp, r1.start);
 588                goto bail;
 589        }
 590
 591#ifdef CONFIG_PPC32
 592        if (machine_is(chrp) && nvram_naddrs == 1) {
 593                nvram_data = ioremap(r1.start, s1);
 594                nvram_mult = 1;
 595                ppc_md.nvram_read_val   = direct_nvram_read_byte;
 596                ppc_md.nvram_write_val  = direct_nvram_write_byte;
 597        } else if (nvram_naddrs == 1) {
 598                nvram_data = ioremap(r1.start, s1);
 599                nvram_mult = (s1 + NVRAM_SIZE - 1) / NVRAM_SIZE;
 600                ppc_md.nvram_read_val   = direct_nvram_read_byte;
 601                ppc_md.nvram_write_val  = direct_nvram_write_byte;
 602        } else if (nvram_naddrs == 2) {
 603                nvram_addr = ioremap(r1.start, s1);
 604                nvram_data = ioremap(r2.start, s2);
 605                ppc_md.nvram_read_val   = indirect_nvram_read_byte;
 606                ppc_md.nvram_write_val  = indirect_nvram_write_byte;
 607        } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
 608#ifdef CONFIG_ADB_PMU
 609                nvram_naddrs = -1;
 610                ppc_md.nvram_read_val   = pmu_nvram_read_byte;
 611                ppc_md.nvram_write_val  = pmu_nvram_write_byte;
 612#endif /* CONFIG_ADB_PMU */
 613        } else {
 614                printk(KERN_ERR "Incompatible type of NVRAM\n");
 615                err = -ENXIO;
 616        }
 617#endif /* CONFIG_PPC32 */
 618bail:
 619        of_node_put(dp);
 620        if (err == 0)
 621                lookup_partitions();
 622        return err;
 623}
 624
 625int pmac_get_partition(int partition)
 626{
 627        return nvram_partitions[partition];
 628}
 629
 630u8 pmac_xpram_read(int xpaddr)
 631{
 632        int offset = pmac_get_partition(pmac_nvram_XPRAM);
 633
 634        if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
 635                return 0xff;
 636
 637        return ppc_md.nvram_read_val(xpaddr + offset);
 638}
 639
 640void pmac_xpram_write(int xpaddr, u8 data)
 641{
 642        int offset = pmac_get_partition(pmac_nvram_XPRAM);
 643
 644        if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
 645                return;
 646
 647        ppc_md.nvram_write_val(xpaddr + offset, data);
 648}
 649
 650EXPORT_SYMBOL(pmac_get_partition);
 651EXPORT_SYMBOL(pmac_xpram_read);
 652EXPORT_SYMBOL(pmac_xpram_write);
 653