Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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