Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
ad57c394
Commit
ad57c394
authored
May 20, 2010
by
Tony Lindgren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'v2.6.34-rc7.iommu' of
git://gitorious.org/~doyu/lk/mainline
into omap-for-linus
parents
0581b52e
4abb7617
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
244 additions
and
46 deletions
+244
-46
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/Makefile
+1
-4
arch/arm/mach-omap2/iommu2.c
arch/arm/mach-omap2/iommu2.c
+4
-2
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap-iommu.c
+157
-0
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Kconfig
+7
-2
arch/arm/plat-omap/include/plat/omap44xx.h
arch/arm/plat-omap/include/plat/omap44xx.h
+3
-0
arch/arm/plat-omap/iommu.c
arch/arm/plat-omap/iommu.c
+66
-35
arch/arm/plat-omap/iovmm.c
arch/arm/plat-omap/iovmm.c
+6
-3
No files found.
arch/arm/mach-omap2/Makefile
View file @
ad57c394
...
...
@@ -89,10 +89,7 @@ obj-$(CONFIG_OMAP3_EMU) += emu.o
obj-$(CONFIG_OMAP_MBOX_FWK)
+=
mailbox_mach.o
mailbox_mach-objs
:=
mailbox.o
iommu-y
+=
iommu2.o
iommu-$(CONFIG_ARCH_OMAP3)
+=
omap3-iommu.o
obj-$(CONFIG_OMAP_IOMMU)
+=
$
(
iommu-y
)
obj-$(CONFIG_OMAP_IOMMU)
:=
iommu2.o omap-iommu.o
i2c-omap-$(CONFIG_I2C_OMAP)
:=
i2c.o
obj-y
+=
$
(
i2c-omap-m
)
$
(
i2c-omap-y
)
...
...
arch/arm/mach-omap2/iommu2.c
View file @
ad57c394
...
...
@@ -147,6 +147,7 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
printk
(
"
\n
"
);
iommu_write_reg
(
obj
,
stat
,
MMU_IRQSTATUS
);
omap2_iommu_disable
(
obj
);
return
stat
;
}
...
...
@@ -184,7 +185,7 @@ static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
if
(
!
cr
)
return
ERR_PTR
(
-
ENOMEM
);
cr
->
cam
=
(
e
->
da
&
MMU_CAM_VATAG_MASK
)
|
e
->
prsvd
|
e
->
pgsz
;
cr
->
cam
=
(
e
->
da
&
MMU_CAM_VATAG_MASK
)
|
e
->
prsvd
|
e
->
pgsz
|
e
->
valid
;
cr
->
ram
=
e
->
pa
|
e
->
endian
|
e
->
elsz
|
e
->
mixed
;
return
cr
;
...
...
@@ -212,7 +213,8 @@ static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
char
*
p
=
buf
;
/* FIXME: Need more detail analysis of cam/ram */
p
+=
sprintf
(
p
,
"%08x %08x
\n
"
,
cr
->
cam
,
cr
->
ram
);
p
+=
sprintf
(
p
,
"%08x %08x %01x
\n
"
,
cr
->
cam
,
cr
->
ram
,
(
cr
->
cam
&
MMU_CAM_P
)
?
1
:
0
);
return
p
-
buf
;
}
...
...
arch/arm/mach-omap2/omap
3
-iommu.c
→
arch/arm/mach-omap2/omap-iommu.c
View file @
ad57c394
/*
* omap iommu: omap
3
device registration
* omap iommu: omap device registration
*
* Copyright (C) 2008-2009 Nokia Corporation
*
...
...
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <plat/iommu.h>
#include <plat/irqs.h>
struct
iommu_device
{
resource_size_t
base
;
...
...
@@ -20,8 +21,11 @@ struct iommu_device {
struct
iommu_platform_data
pdata
;
struct
resource
res
[
2
];
};
static
struct
iommu_device
*
devices
;
static
int
num_iommu_devices
;
static
struct
iommu_device
devices
[]
=
{
#ifdef CONFIG_ARCH_OMAP3
static
struct
iommu_device
omap3_devices
[]
=
{
{
.
base
=
0x480bd400
,
.
irq
=
24
,
...
...
@@ -43,11 +47,48 @@ static struct iommu_device devices[] = {
},
#endif
};
#define NR_IOMMU_DEVICES ARRAY_SIZE(devices)
#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices)
static
struct
platform_device
*
omap3_iommu_pdev
[
NR_OMAP3_IOMMU_DEVICES
];
#else
#define omap3_devices NULL
#define NR_OMAP3_IOMMU_DEVICES 0
#define omap3_iommu_pdev NULL
#endif
#ifdef CONFIG_ARCH_OMAP4
static
struct
iommu_device
omap4_devices
[]
=
{
{
.
base
=
OMAP4_MMU1_BASE
,
.
irq
=
INT_44XX_DUCATI_MMU_IRQ
,
.
pdata
=
{
.
name
=
"ducati"
,
.
nr_tlb_entries
=
32
,
.
clk_name
=
"ducati_ick"
,
},
},
#if defined(CONFIG_MPU_TESLA_IOMMU)
{
.
base
=
OMAP4_MMU2_BASE
,
.
irq
=
INT_44XX_DSP_MMU
,
.
pdata
=
{
.
name
=
"tesla"
,
.
nr_tlb_entries
=
32
,
.
clk_name
=
"tesla_ick"
,
},
},
#endif
};
#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
static
struct
platform_device
*
omap4_iommu_pdev
[
NR_OMAP4_IOMMU_DEVICES
];
#else
#define omap4_devices NULL
#define NR_OMAP4_IOMMU_DEVICES 0
#define omap4_iommu_pdev NULL
#endif
static
struct
platform_device
*
omap3_iommu_pdev
[
NR_IOMMU_DEVICES
]
;
static
struct
platform_device
*
*
omap_iommu_pdev
;
static
int
__init
omap
3
_iommu_init
(
void
)
static
int
__init
omap_iommu_init
(
void
)
{
int
i
,
err
;
struct
resource
res
[]
=
{
...
...
@@ -55,7 +96,18 @@ static int __init omap3_iommu_init(void)
{
.
flags
=
IORESOURCE_IRQ
},
};
for
(
i
=
0
;
i
<
NR_IOMMU_DEVICES
;
i
++
)
{
if
(
cpu_is_omap34xx
())
{
devices
=
omap3_devices
;
omap_iommu_pdev
=
omap3_iommu_pdev
;
num_iommu_devices
=
NR_OMAP3_IOMMU_DEVICES
;
}
else
if
(
cpu_is_omap44xx
())
{
devices
=
omap4_devices
;
omap_iommu_pdev
=
omap4_iommu_pdev
;
num_iommu_devices
=
NR_OMAP4_IOMMU_DEVICES
;
}
else
return
-
ENODEV
;
for
(
i
=
0
;
i
<
num_iommu_devices
;
i
++
)
{
struct
platform_device
*
pdev
;
const
struct
iommu_device
*
d
=
&
devices
[
i
];
...
...
@@ -80,26 +132,26 @@ static int __init omap3_iommu_init(void)
err
=
platform_device_add
(
pdev
);
if
(
err
)
goto
err_out
;
omap
3
_iommu_pdev
[
i
]
=
pdev
;
omap_iommu_pdev
[
i
]
=
pdev
;
}
return
0
;
err_out:
while
(
i
--
)
platform_device_put
(
omap
3
_iommu_pdev
[
i
]);
platform_device_put
(
omap_iommu_pdev
[
i
]);
return
err
;
}
module_init
(
omap
3
_iommu_init
);
module_init
(
omap_iommu_init
);
static
void
__exit
omap
3
_iommu_exit
(
void
)
static
void
__exit
omap_iommu_exit
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
NR_IOMMU_DEVICES
;
i
++
)
platform_device_unregister
(
omap
3
_iommu_pdev
[
i
]);
for
(
i
=
0
;
i
<
num_iommu_devices
;
i
++
)
platform_device_unregister
(
omap_iommu_pdev
[
i
]);
}
module_exit
(
omap
3
_iommu_exit
);
module_exit
(
omap_iommu_exit
);
MODULE_AUTHOR
(
"Hiroshi DOYU"
);
MODULE_DESCRIPTION
(
"omap iommu: omap
3
device registration"
);
MODULE_DESCRIPTION
(
"omap iommu: omap device registration"
);
MODULE_LICENSE
(
"GPL v2"
);
arch/arm/plat-omap/Kconfig
View file @
ad57c394
...
...
@@ -110,8 +110,13 @@ config OMAP_IOMMU
tristate
config OMAP_IOMMU_DEBUG
depends on OMAP_IOMMU
tristate
tristate "Export OMAP IOMMU internals in DebugFS"
depends on OMAP_IOMMU && DEBUG_FS
help
Select this to see extensive information about
the internal state of OMAP IOMMU in debugfs.
Say N unless you know you need this.
choice
prompt "System timer"
...
...
arch/arm/plat-omap/include/plat/omap44xx.h
View file @
ad57c394
...
...
@@ -48,5 +48,8 @@
#define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000)
#define OMAP44XX_HSUSB_OTG_BASE (L4_44XX_BASE + 0xAB000)
#define OMAP4_MMU1_BASE 0x55082000
#define OMAP4_MMU2_BASE 0x4A066000
#endif
/* __ASM_ARCH_OMAP44XX_H */
arch/arm/plat-omap/iommu.c
View file @
ad57c394
...
...
@@ -25,6 +25,11 @@
#include "iopgtable.h"
#define for_each_iotlb_cr(obj, n, __i, cr) \
for (__i = 0; \
(__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \
__i++)
/* accommodate the difference between omap1 and omap2/3 */
static
const
struct
iommu_functions
*
arch_iommu
;
...
...
@@ -172,15 +177,12 @@ static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
l
->
base
=
MMU_LOCK_BASE
(
val
);
l
->
vict
=
MMU_LOCK_VICT
(
val
);
BUG_ON
(
l
->
base
!=
0
);
/* Currently no preservation is used */
}
static
void
iotlb_lock_set
(
struct
iommu
*
obj
,
struct
iotlb_lock
*
l
)
{
u32
val
;
BUG_ON
(
l
->
base
!=
0
);
/* Currently no preservation is used */
val
=
(
l
->
base
<<
MMU_LOCK_BASE_SHIFT
);
val
|=
(
l
->
vict
<<
MMU_LOCK_VICT_SHIFT
);
...
...
@@ -214,6 +216,20 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
return
arch_iommu
->
dump_cr
(
obj
,
cr
,
buf
);
}
/* only used in iotlb iteration for-loop */
static
struct
cr_regs
__iotlb_read_cr
(
struct
iommu
*
obj
,
int
n
)
{
struct
cr_regs
cr
;
struct
iotlb_lock
l
;
iotlb_lock_get
(
obj
,
&
l
);
l
.
vict
=
n
;
iotlb_lock_set
(
obj
,
&
l
);
iotlb_read_cr
(
obj
,
&
cr
);
return
cr
;
}
/**
* load_iotlb_entry - Set an iommu tlb entry
* @obj: target iommu
...
...
@@ -221,7 +237,6 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
**/
int
load_iotlb_entry
(
struct
iommu
*
obj
,
struct
iotlb_entry
*
e
)
{
int
i
;
int
err
=
0
;
struct
iotlb_lock
l
;
struct
cr_regs
*
cr
;
...
...
@@ -231,16 +246,19 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
clk_enable
(
obj
->
clk
);
for
(
i
=
0
;
i
<
obj
->
nr_tlb_entries
;
i
++
)
{
iotlb_lock_get
(
obj
,
&
l
);
if
(
l
.
base
==
obj
->
nr_tlb_entries
)
{
dev_warn
(
obj
->
dev
,
"%s: preserve entries full
\n
"
,
__func__
);
err
=
-
EBUSY
;
goto
out
;
}
if
(
!
e
->
prsvd
)
{
int
i
;
struct
cr_regs
tmp
;
iotlb_lock_get
(
obj
,
&
l
);
l
.
vict
=
i
;
iotlb_lock_set
(
obj
,
&
l
);
iotlb_read_cr
(
obj
,
&
tmp
);
for_each_iotlb_cr
(
obj
,
obj
->
nr_tlb_entries
,
i
,
tmp
)
if
(
!
iotlb_cr_valid
(
&
tmp
))
break
;
}
if
(
i
==
obj
->
nr_tlb_entries
)
{
dev_dbg
(
obj
->
dev
,
"%s: full: no entry
\n
"
,
__func__
);
...
...
@@ -248,6 +266,12 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
goto
out
;
}
iotlb_lock_get
(
obj
,
&
l
);
}
else
{
l
.
vict
=
l
.
base
;
iotlb_lock_set
(
obj
,
&
l
);
}
cr
=
iotlb_alloc_cr
(
obj
,
e
);
if
(
IS_ERR
(
cr
))
{
clk_disable
(
obj
->
clk
);
...
...
@@ -257,9 +281,11 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
iotlb_load_cr
(
obj
,
cr
);
kfree
(
cr
);
if
(
e
->
prsvd
)
l
.
base
++
;
/* increment victim for next tlb load */
if
(
++
l
.
vict
==
obj
->
nr_tlb_entries
)
l
.
vict
=
0
;
l
.
vict
=
l
.
base
;
iotlb_lock_set
(
obj
,
&
l
);
out:
clk_disable
(
obj
->
clk
);
...
...
@@ -276,20 +302,15 @@ EXPORT_SYMBOL_GPL(load_iotlb_entry);
**/
void
flush_iotlb_page
(
struct
iommu
*
obj
,
u32
da
)
{
struct
iotlb_lock
l
;
int
i
;
struct
cr_regs
cr
;
clk_enable
(
obj
->
clk
);
for
(
i
=
0
;
i
<
obj
->
nr_tlb_entries
;
i
++
)
{
struct
cr_regs
cr
;
for_each_iotlb_cr
(
obj
,
obj
->
nr_tlb_entries
,
i
,
cr
)
{
u32
start
;
size_t
bytes
;
iotlb_lock_get
(
obj
,
&
l
);
l
.
vict
=
i
;
iotlb_lock_set
(
obj
,
&
l
);
iotlb_read_cr
(
obj
,
&
cr
);
if
(
!
iotlb_cr_valid
(
&
cr
))
continue
;
...
...
@@ -299,7 +320,6 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
if
((
start
<=
da
)
&&
(
da
<
start
+
bytes
))
{
dev_dbg
(
obj
->
dev
,
"%s: %08x<=%08x(%x)
\n
"
,
__func__
,
start
,
da
,
bytes
);
iotlb_load_cr
(
obj
,
&
cr
);
iommu_write_reg
(
obj
,
1
,
MMU_FLUSH_ENTRY
);
}
}
...
...
@@ -370,26 +390,19 @@ EXPORT_SYMBOL_GPL(iommu_dump_ctx);
static
int
__dump_tlb_entries
(
struct
iommu
*
obj
,
struct
cr_regs
*
crs
,
int
num
)
{
int
i
;
struct
iotlb_lock
saved
,
l
;
struct
iotlb_lock
saved
;
struct
cr_regs
tmp
;
struct
cr_regs
*
p
=
crs
;
clk_enable
(
obj
->
clk
);
iotlb_lock_get
(
obj
,
&
saved
);
memcpy
(
&
l
,
&
saved
,
sizeof
(
saved
));
for
(
i
=
0
;
i
<
num
;
i
++
)
{
struct
cr_regs
tmp
;
iotlb_lock_get
(
obj
,
&
l
);
l
.
vict
=
i
;
iotlb_lock_set
(
obj
,
&
l
);
iotlb_read_cr
(
obj
,
&
tmp
);
for_each_iotlb_cr
(
obj
,
num
,
i
,
tmp
)
{
if
(
!
iotlb_cr_valid
(
&
tmp
))
continue
;
*
p
++
=
tmp
;
}
iotlb_lock_set
(
obj
,
&
saved
);
clk_disable
(
obj
->
clk
);
...
...
@@ -503,6 +516,12 @@ static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
{
u32
*
iopgd
=
iopgd_offset
(
obj
,
da
);
if
((
da
|
pa
)
&
~
IOSECTION_MASK
)
{
dev_err
(
obj
->
dev
,
"%s: %08x:%08x should aligned on %08lx
\n
"
,
__func__
,
da
,
pa
,
IOSECTION_SIZE
);
return
-
EINVAL
;
}
*
iopgd
=
(
pa
&
IOSECTION_MASK
)
|
prot
|
IOPGD_SECTION
;
flush_iopgd_range
(
iopgd
,
iopgd
);
return
0
;
...
...
@@ -513,6 +532,12 @@ static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
u32
*
iopgd
=
iopgd_offset
(
obj
,
da
);
int
i
;
if
((
da
|
pa
)
&
~
IOSUPER_MASK
)
{
dev_err
(
obj
->
dev
,
"%s: %08x:%08x should aligned on %08lx
\n
"
,
__func__
,
da
,
pa
,
IOSUPER_SIZE
);
return
-
EINVAL
;
}
for
(
i
=
0
;
i
<
16
;
i
++
)
*
(
iopgd
+
i
)
=
(
pa
&
IOSUPER_MASK
)
|
prot
|
IOPGD_SUPER
;
flush_iopgd_range
(
iopgd
,
iopgd
+
15
);
...
...
@@ -542,6 +567,12 @@ static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
u32
*
iopte
=
iopte_alloc
(
obj
,
iopgd
,
da
);
int
i
;
if
((
da
|
pa
)
&
~
IOLARGE_MASK
)
{
dev_err
(
obj
->
dev
,
"%s: %08x:%08x should aligned on %08lx
\n
"
,
__func__
,
da
,
pa
,
IOLARGE_SIZE
);
return
-
EINVAL
;
}
if
(
IS_ERR
(
iopte
))
return
PTR_ERR
(
iopte
);
...
...
arch/arm/plat-omap/iovmm.c
View file @
ad57c394
...
...
@@ -287,16 +287,19 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
prev_end
=
0
;
list_for_each_entry
(
tmp
,
&
obj
->
mmap
,
list
)
{
if
((
prev_end
<=
start
)
&&
(
start
+
bytes
<
tmp
->
da_start
))
if
(
prev_end
>=
start
)
break
;
if
(
start
+
bytes
<
tmp
->
da_start
)
goto
found
;
if
(
flags
&
IOVMF_DA_ANON
)
start
=
roundup
(
tmp
->
da_end
,
alignement
);
start
=
roundup
(
tmp
->
da_end
+
1
,
alignement
);
prev_end
=
tmp
->
da_end
;
}
if
((
start
>
=
prev_end
)
&&
(
ULONG_MAX
-
start
>=
bytes
))
if
((
start
>
prev_end
)
&&
(
ULONG_MAX
-
start
>=
bytes
))
goto
found
;
dev_dbg
(
obj
->
dev
,
"%s: no space to fit %08x(%x) flags: %08x
\n
"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment