summaryrefslogtreecommitdiff
path: root/include/linux/pasr.h
blob: 9a6ab1214a7bb1106e2cba63604f73bce261013a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * 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 */