~ubuntu-branches/ubuntu/trusty/linux-armadaxp/trusty

« back to all changes in this revision

Viewing changes to drivers/staging/msm/memory.c

  • Committer: Package Import Robot
  • Author(s): Michael Casadevall, Bryan Wu, Dann Frazier, Michael Casadeall
  • Date: 2012-03-10 15:00:54 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120310150054-flugb39zon8vvgwe
Tags: 3.2.0-1600.1
[ Bryan Wu ]
* UBUNTU: import debian/debian.env and debian.armadaxp

[ Dann Frazier ]
* ARM: Armada XP: remove trailing '/' in dirnames in mvRules.mk

[ Michael Casadeall ]
* tools: add some tools for Marvell Armada XP processor
* kernel: timer tick hacking from Marvell
* kernel: Sheeva Errata: add delay on Sheeva when powering down
* net: add Marvell NFP netfilter
* net: socket and skb modifications made by Marvell
* miscdevice: add minor IDs for some Marvell Armada drivers
* fs: introduce memory pool for splice()
* video: EDID detection updates from Marvell Armada XP patchset
* video: backlight: add Marvell Dove LCD backlight driver
* video: display: add THS8200 display driver
* video: framebuffer: add Marvell Dove and Armada XP processor onchip LCD controller driver
* usbtest: add Interrupt transfer testing by Marvell Armada XP code
* usb: ehci: add support for Marvell EHCI controler
* tty/serial: 8250: add support for Marvell Armada XP processor and DeviceTree work
* rtc: add support for Marvell Armada XP onchip RTC controller
* net: pppoe: add Marvell ethernet NFP hook in PPPoE networking driver
* mtd: nand: add support for Marvell Armada XP Nand Flash Controller
* mtd: maps: add Marvell Armada XP specific map driver
* mmc: add support for Marvell Armada XP MMC/SD host controller
* i2c: add support for Marvell Armada XP onchip i2c bus controller
* hwmon: add Kconfig option for Armada XP onchip thermal sensor driver
* dmaengine: add Net DMA support for splice and update Marvell XOR DMA engine driver
* ata: add support for Marvell Armada XP SATA controller and update some quirks
* ARM: add Marvell Armada XP machine to mach-types
* ARM: oprofile: add support for Marvell PJ4B core
* ARM: mm: more ARMv6 switches for Marvell Armada XP
* ARM: remove static declaration to allow compilation
* ARM: alignment access fault trick
* ARM: mm: skip some fault fixing when run on NONE SMP ARMv6 mode during early abort event
* ARM: mm: add Marvell Sheeva CPU Architecture for PJ4B
* ARM: introduce optimized copy operation for Marvell Armada XP
* ARM: SAUCE: hardware breakpoint trick for Marvell Armada XP
* ARM: big endian and little endian tricks for Marvell Armada XP
* ARM: SAUCE: Add Marvell Armada XP build rules to arch/arm/kernel/Makefile
* ARM: vfp: add special handling for Marvell Armada XP
* ARM: add support for Marvell U-Boot
* ARM: add mv_controller_num for ARM PCI drivers
* ARM: add support for local PMUs, general SMP tweaks and cache flushing
* ARM: add Marvell device identifies in glue-proc.h
* ARM: add IPC driver support for Marvell platforms
* ARM: add DMA mapping for Marvell platforms
* ARM: add Sheeva errata and PJ4B code for booting
* ARM: update Kconfig and Makefile to include Marvell Armada XP platforms
* ARM: Armada XP: import LSP from Marvell for Armada XP 3.2 kernel enablement

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* arch/arm/mach-msm/memory.c
2
 
 *
3
 
 * Copyright (C) 2007 Google, Inc.
4
 
 * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
5
 
 *
6
 
 * This software is licensed under the terms of the GNU General Public
7
 
 * License version 2, as published by the Free Software Foundation, and
8
 
 * may be copied, distributed, and modified under those terms.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 */
16
 
 
17
 
#include <linux/mm.h>
18
 
#include <linux/mm_types.h>
19
 
#include <linux/bootmem.h>
20
 
#include <linux/module.h>
21
 
#include <asm/pgtable.h>
22
 
#include <asm/io.h>
23
 
#include <asm/mach/map.h>
24
 
#include "memory_ll.h"
25
 
#include <asm/cacheflush.h>
26
 
#if defined(CONFIG_MSM_NPA_REMOTE)
27
 
#include "npa_remote.h"
28
 
#include <linux/completion.h>
29
 
#include <linux/err.h>
30
 
#endif
31
 
 
32
 
int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
33
 
                            unsigned long pfn, unsigned long size, pgprot_t prot)
34
 
{
35
 
        unsigned long pfn_addr = pfn << PAGE_SHIFT;
36
 
/*
37
 
        if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) {
38
 
                prot = pgprot_device(prot);
39
 
                printk("remapping device %lx\n", prot);
40
 
        }
41
 
*/
42
 
        panic("Memory remap PFN stuff not done\n");
43
 
        return remap_pfn_range(vma, addr, pfn, size, prot);
44
 
}
45
 
 
46
 
void *zero_page_strongly_ordered;
47
 
 
48
 
static void map_zero_page_strongly_ordered(void)
49
 
{
50
 
        if (zero_page_strongly_ordered)
51
 
                return;
52
 
/*
53
 
        zero_page_strongly_ordered =
54
 
                ioremap_strongly_ordered(page_to_pfn(empty_zero_page)
55
 
                << PAGE_SHIFT, PAGE_SIZE);
56
 
*/
57
 
        panic("Strongly ordered memory functions not implemented\n");
58
 
}
59
 
 
60
 
void write_to_strongly_ordered_memory(void)
61
 
{
62
 
        map_zero_page_strongly_ordered();
63
 
        *(int *)zero_page_strongly_ordered = 0;
64
 
}
65
 
EXPORT_SYMBOL(write_to_strongly_ordered_memory);
66
 
 
67
 
void flush_axi_bus_buffer(void)
68
 
{
69
 
        __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
70
 
                                    : : "r" (0) : "memory");
71
 
        write_to_strongly_ordered_memory();
72
 
}
73
 
 
74
 
#define CACHE_LINE_SIZE 32
75
 
 
76
 
/* These cache related routines make the assumption that the associated
77
 
 * physical memory is contiguous. They will operate on all (L1
78
 
 * and L2 if present) caches.
79
 
 */
80
 
void clean_and_invalidate_caches(unsigned long vstart,
81
 
        unsigned long length, unsigned long pstart)
82
 
{
83
 
        unsigned long vaddr;
84
 
 
85
 
        for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
86
 
                asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr));
87
 
#ifdef CONFIG_OUTER_CACHE
88
 
        outer_flush_range(pstart, pstart + length);
89
 
#endif
90
 
        asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
91
 
        asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
92
 
 
93
 
        flush_axi_bus_buffer();
94
 
}
95
 
 
96
 
void clean_caches(unsigned long vstart,
97
 
        unsigned long length, unsigned long pstart)
98
 
{
99
 
        unsigned long vaddr;
100
 
 
101
 
        for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
102
 
                asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr));
103
 
#ifdef CONFIG_OUTER_CACHE
104
 
        outer_clean_range(pstart, pstart + length);
105
 
#endif
106
 
        asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
107
 
        asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
108
 
 
109
 
        flush_axi_bus_buffer();
110
 
}
111
 
 
112
 
void invalidate_caches(unsigned long vstart,
113
 
        unsigned long length, unsigned long pstart)
114
 
{
115
 
        unsigned long vaddr;
116
 
 
117
 
        for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
118
 
                asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr));
119
 
#ifdef CONFIG_OUTER_CACHE
120
 
        outer_inv_range(pstart, pstart + length);
121
 
#endif
122
 
        asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
123
 
        asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
124
 
 
125
 
        flush_axi_bus_buffer();
126
 
}
127
 
 
128
 
void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
129
 
{
130
 
        void *unused_addr = NULL;
131
 
        unsigned long addr, tmp_size, unused_size;
132
 
 
133
 
        /* Allocate maximum size needed, see where it ends up.
134
 
         * Then free it -- in this path there are no other allocators
135
 
         * so we can depend on getting the same address back
136
 
         * when we allocate a smaller piece that is aligned
137
 
         * at the end (if necessary) and the piece we really want,
138
 
         * then free the unused first piece.
139
 
         */
140
 
 
141
 
        tmp_size = size + alignment - PAGE_SIZE;
142
 
        addr = (unsigned long)alloc_bootmem(tmp_size);
143
 
        free_bootmem(__pa(addr), tmp_size);
144
 
 
145
 
        unused_size = alignment - (addr % alignment);
146
 
        if (unused_size)
147
 
                unused_addr = alloc_bootmem(unused_size);
148
 
 
149
 
        addr = (unsigned long)alloc_bootmem(size);
150
 
        if (unused_size)
151
 
                free_bootmem(__pa(unused_addr), unused_size);
152
 
 
153
 
        return (void *)addr;
154
 
}
155
 
 
156
 
#if defined(CONFIG_MSM_NPA_REMOTE)
157
 
struct npa_client *npa_memory_client;
158
 
#endif
159
 
 
160
 
static int change_memory_power_state(unsigned long start_pfn,
161
 
        unsigned long nr_pages, int state)
162
 
{
163
 
#if defined(CONFIG_MSM_NPA_REMOTE)
164
 
        static atomic_t node_created_flag = ATOMIC_INIT(1);
165
 
#else
166
 
        unsigned long start;
167
 
        unsigned long size;
168
 
        unsigned long virtual;
169
 
#endif
170
 
        int rc = 0;
171
 
 
172
 
#if defined(CONFIG_MSM_NPA_REMOTE)
173
 
        if (atomic_dec_and_test(&node_created_flag)) {
174
 
                /* Create NPA 'required' client. */
175
 
                npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME,
176
 
                        "memory node", NPA_CLIENT_REQUIRED);
177
 
                if (IS_ERR(npa_memory_client)) {
178
 
                        rc = PTR_ERR(npa_memory_client);
179
 
                        return rc;
180
 
                }
181
 
        }
182
 
 
183
 
        rc = npa_issue_required_request(npa_memory_client, state);
184
 
#else
185
 
        if (state == MEMORY_DEEP_POWERDOWN) {
186
 
                /* simulate turning off memory by writing bit pattern into it */
187
 
                start = start_pfn << PAGE_SHIFT;
188
 
                size = nr_pages << PAGE_SHIFT;
189
 
                virtual = __phys_to_virt(start);
190
 
                memset((void *)virtual, 0x27, size);
191
 
        }
192
 
#endif
193
 
        return rc;
194
 
}
195
 
 
196
 
int platform_physical_remove_pages(unsigned long start_pfn,
197
 
        unsigned long nr_pages)
198
 
{
199
 
        return change_memory_power_state(start_pfn, nr_pages,
200
 
                MEMORY_DEEP_POWERDOWN);
201
 
}
202
 
 
203
 
int platform_physical_add_pages(unsigned long start_pfn,
204
 
        unsigned long nr_pages)
205
 
{
206
 
        return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE);
207
 
}
208
 
 
209
 
int platform_physical_low_power_pages(unsigned long start_pfn,
210
 
        unsigned long nr_pages)
211
 
{
212
 
        return change_memory_power_state(start_pfn, nr_pages,
213
 
                MEMORY_SELF_REFRESH);
214
 
}