Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b97b8a99 authored by Bernd Schmidt's avatar Bernd Schmidt Committed by Bryan Wu
Browse files

[Blackfin] arch: Initial checkin of the memory protection support.



Enable it with CONFIG_MPU.

Signed-off-by: default avatarBernd Schmidt <bernd.schmidt@analog.com>
Signed-off-by: default avatarBryan Wu <bryan.wu@analog.com>
parent 2047e40d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -765,6 +765,15 @@ config L1_MAX_PIECE
	  Set the max memory pieces for the L1 SRAM allocation algorithm.
	  Min value is 16. Max value is 1024.


config MPU
	bool "Enable the memory protection unit (EXPERIMENTAL)"
	default n
	help
	  Use the processor's MPU to protect applications from accessing
	  memory they do not own.  This comes at a performance penalty
	  and is recommended only for debugging.

comment "Asynchonous Memory Configuration"

menu "EBIU_AMGCTL Global Control"
+5 −1
Original line number Diff line number Diff line
@@ -82,7 +82,11 @@ core-y += arch/$(ARCH)/mach-$(MACHINE)/
core-y   += arch/$(ARCH)/mach-$(MACHINE)/boards/
endif

ifeq ($(CONFIG_MPU),y)
core-y	+= arch/$(ARCH)/kernel/cplb-mpu/
else
core-y	+= arch/$(ARCH)/kernel/cplb-nompu/
endif

libs-y   += arch/$(ARCH)/lib/

+8 −0
Original line number Diff line number Diff line
#
# arch/blackfin/kernel/cplb-nompu/Makefile
#

obj-y := cplbinit.o cacheinit.o cplbmgr.o

obj-$(CONFIG_CPLB_INFO) += cplbinfo.o
+62 −0
Original line number Diff line number Diff line
/*
 *               Copyright 2004-2007 Analog Devices Inc.
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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, see the file COPYING, or write
 * to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <linux/cpu.h>

#include <asm/cacheflush.h>
#include <asm/blackfin.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>

#if defined(CONFIG_BFIN_ICACHE)
void bfin_icache_init(void)
{
	unsigned long ctrl;
	int i;

	SSYNC();
	for (i = 0; i < MAX_CPLBS; i++) {
		bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr);
		bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data);
	}
	ctrl = bfin_read_IMEM_CONTROL();
	ctrl |= IMC | ENICPLB;
	bfin_write_IMEM_CONTROL(ctrl);
	SSYNC();
}
#endif

#if defined(CONFIG_BFIN_DCACHE)
void bfin_dcache_init(void)
{
	unsigned long ctrl;
	int i;

	SSYNC();
	for (i = 0; i < MAX_CPLBS; i++) {
		bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr);
		bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data);
	}

	ctrl = bfin_read_DMEM_CONTROL();
	ctrl |= DMEM_CNTR;
	bfin_write_DMEM_CONTROL(ctrl);
	SSYNC();
}
#endif
+144 −0
Original line number Diff line number Diff line
/*
 * File:         arch/blackfin/mach-common/cplbinfo.c
 * Based on:
 * Author:       Sonic Zhang <sonic.zhang@analog.com>
 *
 * Created:      Jan. 2005
 * Description:  Display CPLB status
 *
 * Modified:
 *               Copyright 2004-2006 Analog Devices Inc.
 *
 * Bugs:         Enter bugs at http://blackfin.uclinux.org/
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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, see the file COPYING, or write
 * to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>

#include <asm/current.h>
#include <asm/system.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>
#include <asm/blackfin.h>

#define CPLB_I 1
#define CPLB_D 2

#define SYNC_SYS    SSYNC()
#define SYNC_CORE   CSYNC()

#define CPLB_BIT_PAGESIZE 0x30000

static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };

static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
{
	int i;
	buf += sprintf(buf, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n");
	for (i = 0; i < MAX_CPLBS; i++) {
		unsigned long data = tbl[i].data;
		unsigned long addr = tbl[i].addr;
		if (!(data & CPLB_VALID))
			continue;

		buf +=
		    sprintf(buf,
			    "%d\t0x%08lx\t%06lx\t%s\t%c\t%c\t%c\t%c\n",
			    i, addr, data,
			    page_size_string_table[(data & 0x30000) >> 16],
			    (data & CPLB_USER_RD) ? 'Y' : 'N',
			    (data & CPLB_USER_WR) ? 'Y' : 'N',
			    (data & CPLB_SUPV_WR) ? 'Y' : 'N',
			    i < switched ? 'N' : 'Y');
	}
	buf += sprintf(buf, "\n");

	return buf;
}

int cplbinfo_proc_output(char *buf)
{
	char *p;

	p = buf;

	p += sprintf(p, "------------------ CPLB Information ------------------\n\n");

	if (bfin_read_IMEM_CONTROL() & ENICPLB) {
		p += sprintf(p, "Instruction CPLB entry:\n");
		p = cplb_print_entry(p, icplb_tbl, first_switched_icplb);
	} else
		p += sprintf(p, "Instruction CPLB is disabled.\n\n");

	if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) {
		p += sprintf(p, "Data CPLB entry:\n");
		p = cplb_print_entry(p, dcplb_tbl, first_switched_dcplb);
	} else
		p += sprintf(p, "Data CPLB is disabled.\n");

	p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n",
		     nr_icplb_miss, nr_icplb_supv_miss);
	p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n",
		     nr_dcplb_miss, nr_dcplb_prot);
	p += sprintf(p, "CPLB flushes: %d\n",
		     nr_cplb_flush);

	return p - buf;
}

static int cplbinfo_read_proc(char *page, char **start, off_t off,
			      int count, int *eof, void *data)
{
	int len;

	len = cplbinfo_proc_output(page);
	if (len <= off + count)
		*eof = 1;
	*start = page + off;
	len -= off;
	if (len > count)
		len = count;
	if (len < 0)
		len = 0;
	return len;
}

static int __init cplbinfo_init(void)
{
	struct proc_dir_entry *entry;

	entry = create_proc_entry("cplbinfo", 0, NULL);
	if (!entry)
		return -ENOMEM;

	entry->read_proc = cplbinfo_read_proc;
	entry->data = NULL;

	return 0;
}

static void __exit cplbinfo_exit(void)
{
	remove_proc_entry("cplbinfo", NULL);
}

module_init(cplbinfo_init);
module_exit(cplbinfo_exit);
Loading