blob: 9a6ab1214a7bb1106e2cba63604f73bce261013a [file] [log] [blame]
/*
* Copyright (C) ST-Ericsson SA 2011
* Author: Maxime Coquelin <maxime.coquelin@stericsson.com> for ST-Ericsson.
* License terms: GNU General Public License (GPL), version 2
*
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef _LINUX_PASR_H
#define _LINUX_PASR_H
#include <linux/mm.h>
#include <linux/spinlock.h>
#ifdef CONFIG_PASR
#define PASR_MAX_SECTION_NR_PER_DIE 8
#define PASR_MAX_DIE_NR 4
extern u64 section_size;
extern unsigned int section_bit;
/**
* struct pasr_section - Represent either a DDR Bank or Segment depending on
* the DDR configuration (Bank-Row-Column or Row-Bank-Coloumn)
*
* @start: Start address of the segment.
* @pair: Pointer on another segment in case of dependency (e.g. interleaving).
* Masking of the dependant segments have to be done accordingly.
* @free_size: Represents the free memory size in the segment.
* @lock: Protect the free_size counter
* @die: Pointer to the Die the segment is part of.
*/
struct pasr_section {
phys_addr_t start;
struct pasr_section *pair;
u64 free_size;
spinlock_t *lock;
struct pasr_die *die;
};
/**
* struct pasr_die - Represent a DDR die
*
* @start: Start address of the die.
* @end: End address of the die.
* @idx: Index of the die.
* @nr_sections: Number of Bank or Segment in the die.
* @section: Table of the die's segments.
* @mem_reg: Represents the PASR mask of the die. It is either MR16 or MR17,
* depending on the addressing configuration (RBC or BRC).
* @apply_mask: Callback registred by the platform's PASR driver to apply the
* calculated PASR mask.
* @cookie: Private data for the platform's PASR driver.
*/
struct pasr_die {
phys_addr_t start;
phys_addr_t end;
int idx;
int nr_sections;
struct pasr_section section[PASR_MAX_SECTION_NR_PER_DIE];
u16 mem_reg; /* Either MR16 or MR17 */
void (*apply_mask)(u16 *mem_reg, void *cookie);
void *cookie;
};
/**
* struct pasr_map - Represent the DDR physical map
*
* @nr_dies: Number of DDR dies.
* @die: Table of the dies.
*/
struct pasr_map {
int nr_dies;
struct pasr_die die[PASR_MAX_DIE_NR];
};
#define for_each_pasr_section(i, j, map, s) \
for (i = 0; i < map.nr_dies; i++) \
for (s = &map.die[i].section[0], j = 0; \
j < map.die[i].nr_sections; \
j++, s = &map.die[i].section[j])
/**
* pasr_register_mask_function()
*
* @die_addr: Physical base address of the die.
* @function: Callback function for applying the DDR PASR mask.
* @cookie: Private data called with the callback function.
*
* This function is to be called by the platform specific PASR driver in
* charge of application of the PASR masks.
*/
int pasr_register_mask_function(phys_addr_t die_addr,
void *function, void *cookie);
/**
* pasr_put()
*
* @paddr: Physical address of the freed memory chunk.
* @size: Size of the freed memory chunk.
*
* This function is to be placed in the allocators when memory chunks are
* inserted in the free memory pool.
* This function has only to be called for unused memory, otherwise retention
* cannot be guaranteed.
*/
void pasr_put(phys_addr_t paddr, u64 size);
/**
* pasr_get()
*
* @paddr: Physical address of the allocated memory chunk.
* @size: Size of the allocated memory chunk.
*
* This function is to be placed in the allocators when memory chunks are
* removed from the free memory pool.
* If pasr_put() is used by the allocator, using this function is mandatory to
* guarantee retention.
*/
void pasr_get(phys_addr_t paddr, u64 size);
static inline void pasr_kput(struct page *page, int order)
{
if (order == MAX_ORDER - 1)
pasr_put(page_to_phys(page), PAGE_SIZE << (MAX_ORDER - 1));
}
static inline void pasr_kget(struct page *page, int order)
{
if (order == MAX_ORDER - 1)
pasr_get(page_to_phys(page), PAGE_SIZE << (MAX_ORDER - 1));
}
int __init early_pasr_setup(void);
int __init late_pasr_setup(void);
int __init pasr_init_core(struct pasr_map *);
#else
static inline int pasr_register_mask_function(phys_addr_t die_addr,
void *function, void *cookie)
{
return 0;
}
#define pasr_kput(page, order) do {} while (0)
#define pasr_kget(page, order) do {} while (0)
#define pasr_put(paddr, size) do {} while (0)
#define pasr_get(paddr, size) do {} while (0)
#endif /* CONFIG_PASR */
#endif /* _LINUX_PASR_H */