/*
* PS3 address space management.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/memory_hotplug.h>
#include <linux/lmb.h>
#include <asm/firmware.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <asm/lv1call.h>
#include "platform.h"
#if defined(DEBUG)
#define DBG udbg_printf
#else
#define DBG pr_debug
#endif
enum {
#if defined(CONFIG_PS3_DYNAMIC_DMA)
USE_DYNAMIC_DMA = 1,
#else
USE_DYNAMIC_DMA = 0,
#endif
};
enum {
PAGE_SHIFT_4K = 12U,
PAGE_SHIFT_64K = 16U,
PAGE_SHIFT_16M = 24U,
};
static unsigned long make_page_sizes(unsigned long a, unsigned long b)
{
return (a << 56) | (b << 48);
}
enum {
ALLOCATE_MEMORY_TRY_ALT_UNIT = 0X04,
ALLOCATE_MEMORY_ADDR_ZERO = 0X08,
};
/* valid htab sizes are {18,19,20} = 256K, 512K, 1M */
enum {
HTAB_SIZE_MAX = 20U, /* HV limit of 1MB */
HTAB_SIZE_MIN = 18U, /* CPU limit of 256KB */
};
/*============================================================================*/
/* virtual address space routines */
/*============================================================================*/
/**
* struct mem_region - memory region structure
* @base: base address
* @size: size in bytes
* @offset: difference between base and rm.size
*/
struct mem_region {
u64 base;
u64 size;
unsigned long offset;
};
/**
* struct map - address space state variables holder
* @total: total memory available as reported by HV
* @vas_id - HV virtual address space id
* @htab_size: htab size in bytes
*
* The HV virtual address space (vas) allows for hotplug memory regions.
* Memory regions can be created and destroyed in the vas at runtime.
* @rm: real mode (bootmem) region
* @r1: hotplug memory region(s)
*
* ps3 addresses
* virt_addr: a cpu 'translated' effective address
* phys_addr: an address in what Linux thinks is the physical address space
* lpar_addr: an address in the HV virtual address space
* bus_addr: an io controller 'translated' address on a device bus
*/
struct map {
u64 total;
u64 vas_id;
u64 htab_size;
struct mem_region rm;
struct mem_region r1;
};
#define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__)
static void __maybe_unused _debug_dump_map(const struct map *m,
const char *func, int line)
{
DBG("%s:%d: map.total = %llxh\n", func, line, m->total);
DBG("%s:%d: map.rm.size = %llxh\n", func, line, m->rm.size);
DBG("%s:%d: map.vas_id = %llu\n", func, line, m->vas_id);
DBG("%s:%d: map.htab_size = %llxh\n", func, line, m->htab_size);
DBG("%s:%d: map.r1.base = %llxh\n", func, line, m->r1.base);
DBG("%s:%d: map.r1.offset = %lxh\n", func, line, m->r1.offset);
DBG("%s:%d: map.r1.size = %llxh\n", func, line, m->r1.size);
}
static struct map map;
/**
* ps3_mm_phys_to_lpar - translate a linux physical address to lpar address
* @phys_addr: linux physical address
*/
unsigned long