13db880b6SDavid Hildenbrand /* 23db880b6SDavid Hildenbrand * s390x SCLP driver 33db880b6SDavid Hildenbrand * 43db880b6SDavid Hildenbrand * Copyright (c) 2017 Red Hat Inc 53db880b6SDavid Hildenbrand * 63db880b6SDavid Hildenbrand * Authors: 73db880b6SDavid Hildenbrand * David Hildenbrand <david@redhat.com> 83db880b6SDavid Hildenbrand * 93db880b6SDavid Hildenbrand * This code is free software; you can redistribute it and/or modify it 103db880b6SDavid Hildenbrand * under the terms of the GNU Library General Public License version 2. 113db880b6SDavid Hildenbrand */ 123db880b6SDavid Hildenbrand 133db880b6SDavid Hildenbrand #include <libcflat.h> 143db880b6SDavid Hildenbrand #include <asm/page.h> 153db880b6SDavid Hildenbrand #include <asm/arch_def.h> 163db880b6SDavid Hildenbrand #include <asm/interrupt.h> 173db880b6SDavid Hildenbrand #include "sclp.h" 18*92bbd322SDavid Hildenbrand #include <alloc_phys.h> 19*92bbd322SDavid Hildenbrand 20*92bbd322SDavid Hildenbrand extern unsigned long stacktop; 213db880b6SDavid Hildenbrand 223db880b6SDavid Hildenbrand static uint64_t storage_increment_size; 233db880b6SDavid Hildenbrand static uint64_t max_ram_size; 243db880b6SDavid Hildenbrand static uint64_t ram_size; 253db880b6SDavid Hildenbrand 26*92bbd322SDavid Hildenbrand static void mem_init(phys_addr_t mem_end) 27*92bbd322SDavid Hildenbrand { 28*92bbd322SDavid Hildenbrand phys_addr_t freemem_start = (phys_addr_t)&stacktop; 29*92bbd322SDavid Hildenbrand 30*92bbd322SDavid Hildenbrand phys_alloc_init(freemem_start, mem_end - freemem_start); 31*92bbd322SDavid Hildenbrand } 32*92bbd322SDavid Hildenbrand 333db880b6SDavid Hildenbrand void sclp_memory_setup(void) 343db880b6SDavid Hildenbrand { 353db880b6SDavid Hildenbrand ReadInfo *ri = (void *)_sccb; 363db880b6SDavid Hildenbrand uint64_t rnmax, rnsize; 373db880b6SDavid Hildenbrand int cc; 383db880b6SDavid Hildenbrand 393db880b6SDavid Hildenbrand ri->h.length = SCCB_SIZE; 403db880b6SDavid Hildenbrand sclp_service_call(SCLP_CMDW_READ_SCP_INFO_FORCED, ri); 413db880b6SDavid Hildenbrand 423db880b6SDavid Hildenbrand /* calculate the storage increment size */ 433db880b6SDavid Hildenbrand rnsize = ri->rnsize; 443db880b6SDavid Hildenbrand if (!rnsize) { 453db880b6SDavid Hildenbrand rnsize = ri->rnsize2; 463db880b6SDavid Hildenbrand } 473db880b6SDavid Hildenbrand storage_increment_size = rnsize << 20; 483db880b6SDavid Hildenbrand 493db880b6SDavid Hildenbrand /* calculate the maximum memory size */ 503db880b6SDavid Hildenbrand rnmax = ri->rnmax; 513db880b6SDavid Hildenbrand if (!rnmax) { 523db880b6SDavid Hildenbrand rnmax = ri->rnmax2; 533db880b6SDavid Hildenbrand } 543db880b6SDavid Hildenbrand max_ram_size = rnmax * storage_increment_size; 553db880b6SDavid Hildenbrand 563db880b6SDavid Hildenbrand /* lowcore is always accessible, so the first increment is accessible */ 573db880b6SDavid Hildenbrand ram_size = storage_increment_size; 583db880b6SDavid Hildenbrand 593db880b6SDavid Hildenbrand /* probe for r/w memory up to max memory size */ 603db880b6SDavid Hildenbrand while (ram_size < max_ram_size) { 613db880b6SDavid Hildenbrand expect_pgm_int(); 623db880b6SDavid Hildenbrand cc = tprot(ram_size + storage_increment_size - 1); 633db880b6SDavid Hildenbrand /* stop once we receive an exception or have protected memory */ 643db880b6SDavid Hildenbrand if (clear_pgm_int() || cc != 0) 653db880b6SDavid Hildenbrand break; 663db880b6SDavid Hildenbrand ram_size += storage_increment_size; 673db880b6SDavid Hildenbrand } 68*92bbd322SDavid Hildenbrand 69*92bbd322SDavid Hildenbrand mem_init(ram_size); 703db880b6SDavid Hildenbrand } 71