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
nexedi
linux
Commits
9af2ebbd
Commit
9af2ebbd
authored
Sep 23, 2010
by
Tony Lindgren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'hwmod_2.6.37' of
git://git.pwsan.com/linux-2.6
into omap-for-linus
parents
493c32a0
74ff3a68
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
829 additions
and
110 deletions
+829
-110
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/Makefile
+2
-2
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.c
+472
-90
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prcm.c
+27
-2
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm.h
+17
-1
arch/arm/mach-omap2/prm2xxx_3xxx.c
arch/arm/mach-omap2/prm2xxx_3xxx.c
+110
-0
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm44xx.c
+116
-0
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
+41
-14
arch/arm/plat-omap/include/plat/prcm.h
arch/arm/plat-omap/include/plat/prcm.h
+2
-0
arch/arm/plat-omap/omap_device.c
arch/arm/plat-omap/omap_device.c
+42
-1
No files found.
arch/arm/mach-omap2/Makefile
View file @
9af2ebbd
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
# Common support
# Common support
obj-y
:=
id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o
obj-y
:=
id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o
omap-2-3-common
=
irq.o sdrc.o
omap-2-3-common
=
irq.o sdrc.o
prm2xxx_3xxx.o
hwmod-common
=
omap_hwmod.o
\
hwmod-common
=
omap_hwmod.o
\
omap_hwmod_common_data.o
omap_hwmod_common_data.o
prcm-common
=
prcm.o powerdomain.o
prcm-common
=
prcm.o powerdomain.o
...
@@ -15,7 +15,7 @@ clock-common = clock.o clock_common_data.o \
...
@@ -15,7 +15,7 @@ clock-common = clock.o clock_common_data.o \
obj-$(CONFIG_ARCH_OMAP2)
+=
$
(
omap-2-3-common
)
$
(
prcm-common
)
$
(
hwmod-common
)
obj-$(CONFIG_ARCH_OMAP2)
+=
$
(
omap-2-3-common
)
$
(
prcm-common
)
$
(
hwmod-common
)
obj-$(CONFIG_ARCH_OMAP3)
+=
$
(
omap-2-3-common
)
$
(
prcm-common
)
$
(
hwmod-common
)
obj-$(CONFIG_ARCH_OMAP3)
+=
$
(
omap-2-3-common
)
$
(
prcm-common
)
$
(
hwmod-common
)
obj-$(CONFIG_ARCH_OMAP4)
+=
$
(
prcm-common
)
$
(
hwmod-common
)
obj-$(CONFIG_ARCH_OMAP4)
+=
$
(
prcm-common
)
prm44xx.o
$
(
hwmod-common
)
obj-$(CONFIG_OMAP_MCBSP)
+=
mcbsp.o
obj-$(CONFIG_OMAP_MCBSP)
+=
mcbsp.o
...
...
arch/arm/mach-omap2/omap_hwmod.c
View file @
9af2ebbd
...
@@ -13,10 +13,102 @@
...
@@ -13,10 +13,102 @@
* it under the terms of the GNU General Public License version 2 as
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
* published by the Free Software Foundation.
*
*
* This code manages "OMAP modules" (on-chip devices) and their
* Introduction
* integration with Linux device driver and bus code.
* ------------
*
* One way to view an OMAP SoC is as a collection of largely unrelated
* References:
* IP blocks connected by interconnects. The IP blocks include
* devices such as ARM processors, audio serial interfaces, UARTs,
* etc. Some of these devices, like the DSP, are created by TI;
* others, like the SGX, largely originate from external vendors. In
* TI's documentation, on-chip devices are referred to as "OMAP
* modules." Some of these IP blocks are identical across several
* OMAP versions. Others are revised frequently.
*
* These OMAP modules are tied together by various interconnects.
* Most of the address and data flow between modules is via OCP-based
* interconnects such as the L3 and L4 buses; but there are other
* interconnects that distribute the hardware clock tree, handle idle
* and reset signaling, supply power, and connect the modules to
* various pads or balls on the OMAP package.
*
* OMAP hwmod provides a consistent way to describe the on-chip
* hardware blocks and their integration into the rest of the chip.
* This description can be automatically generated from the TI
* hardware database. OMAP hwmod provides a standard, consistent API
* to reset, enable, idle, and disable these hardware blocks. And
* hwmod provides a way for other core code, such as the Linux device
* code or the OMAP power management and address space mapping code,
* to query the hardware database.
*
* Using hwmod
* -----------
* Drivers won't call hwmod functions directly. That is done by the
* omap_device code, and in rare occasions, by custom integration code
* in arch/arm/ *omap*. The omap_device code includes functions to
* build a struct platform_device using omap_hwmod data, and that is
* currently how hwmod data is communicated to drivers and to the
* Linux driver model. Most drivers will call omap_hwmod functions only
* indirectly, via pm_runtime*() functions.
*
* From a layering perspective, here is where the OMAP hwmod code
* fits into the kernel software stack:
*
* +-------------------------------+
* | Device driver code |
* | (e.g., drivers/) |
* +-------------------------------+
* | Linux driver model |
* | (platform_device / |
* | platform_driver data/code) |
* +-------------------------------+
* | OMAP core-driver integration |
* |(arch/arm/mach-omap2/devices.c)|
* +-------------------------------+
* | omap_device code |
* | (../plat-omap/omap_device.c) |
* +-------------------------------+
* ----> | omap_hwmod code/data | <-----
* | (../mach-omap2/omap_hwmod*) |
* +-------------------------------+
* | OMAP clock/PRCM/register fns |
* | (__raw_{read,write}l, clk*) |
* +-------------------------------+
*
* Device drivers should not contain any OMAP-specific code or data in
* them. They should only contain code to operate the IP block that
* the driver is responsible for. This is because these IP blocks can
* also appear in other SoCs, either from TI (such as DaVinci) or from
* other manufacturers; and drivers should be reusable across other
* platforms.
*
* The OMAP hwmod code also will attempt to reset and idle all on-chip
* devices upon boot. The goal here is for the kernel to be
* completely self-reliant and independent from bootloaders. This is
* to ensure a repeatable configuration, both to ensure consistent
* runtime behavior, and to make it easier for others to reproduce
* bugs.
*
* OMAP module activity states
* ---------------------------
* The hwmod code considers modules to be in one of several activity
* states. IP blocks start out in an UNKNOWN state, then once they
* are registered via the hwmod code, proceed to the REGISTERED state.
* Once their clock names are resolved to clock pointers, the module
* enters the CLKS_INITED state; and finally, once the module has been
* reset and the integration registers programmed, the INITIALIZED state
* is entered. The hwmod code will then place the module into either
* the IDLE state to save power, or in the case of a critical system
* module, the ENABLED state.
*
* OMAP core integration code can then call omap_hwmod*() functions
* directly to move the module between the IDLE, ENABLED, and DISABLED
* states, as needed. This is done during both the PM idle loop, and
* in the OMAP core integration code's implementation of the PM runtime
* functions.
*
* References
* ----------
* This is a partial list.
* - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
* - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
* - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
* - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
* - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
* - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
...
@@ -50,11 +142,13 @@
...
@@ -50,11 +142,13 @@
#include <plat/powerdomain.h>
#include <plat/powerdomain.h>
#include <plat/clock.h>
#include <plat/clock.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_hwmod.h>
#include <plat/prcm.h>
#include "cm.h"
#include "cm.h"
#include "prm.h"
/* Maximum microseconds to wait for OMAP module to reset */
/* Maximum microseconds to wait for OMAP module to
soft
reset */
#define MAX_MODULE_
RESET_WAIT
10000
#define MAX_MODULE_
SOFTRESET_WAIT
10000
/* Name of the OMAP hwmod for the MPU */
/* Name of the OMAP hwmod for the MPU */
#define MPU_INITIATOR_NAME "mpu"
#define MPU_INITIATOR_NAME "mpu"
...
@@ -544,6 +638,36 @@ static int _disable_clocks(struct omap_hwmod *oh)
...
@@ -544,6 +638,36 @@ static int _disable_clocks(struct omap_hwmod *oh)
return
0
;
return
0
;
}
}
static
void
_enable_optional_clocks
(
struct
omap_hwmod
*
oh
)
{
struct
omap_hwmod_opt_clk
*
oc
;
int
i
;
pr_debug
(
"omap_hwmod: %s: enabling optional clocks
\n
"
,
oh
->
name
);
for
(
i
=
oh
->
opt_clks_cnt
,
oc
=
oh
->
opt_clks
;
i
>
0
;
i
--
,
oc
++
)
if
(
oc
->
_clk
)
{
pr_debug
(
"omap_hwmod: enable %s:%s
\n
"
,
oc
->
role
,
oc
->
_clk
->
name
);
clk_enable
(
oc
->
_clk
);
}
}
static
void
_disable_optional_clocks
(
struct
omap_hwmod
*
oh
)
{
struct
omap_hwmod_opt_clk
*
oc
;
int
i
;
pr_debug
(
"omap_hwmod: %s: disabling optional clocks
\n
"
,
oh
->
name
);
for
(
i
=
oh
->
opt_clks_cnt
,
oc
=
oh
->
opt_clks
;
i
>
0
;
i
--
,
oc
++
)
if
(
oc
->
_clk
)
{
pr_debug
(
"omap_hwmod: disable %s:%s
\n
"
,
oc
->
role
,
oc
->
_clk
->
name
);
clk_disable
(
oc
->
_clk
);
}
}
/**
/**
* _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
* _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
...
@@ -622,7 +746,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
...
@@ -622,7 +746,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
}
}
/**
/**
* _
sysc_enable
- try to bring a module out of idle via OCP_SYSCONFIG
* _
enable_sysc
- try to bring a module out of idle via OCP_SYSCONFIG
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* If module is marked as SWSUP_SIDLE, force the module out of slave
* If module is marked as SWSUP_SIDLE, force the module out of slave
...
@@ -630,7 +754,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
...
@@ -630,7 +754,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
* as SWSUP_MSUSPEND, force the module out of master standby;
* as SWSUP_MSUSPEND, force the module out of master standby;
* otherwise, configure it for smart-standby. No return value.
* otherwise, configure it for smart-standby. No return value.
*/
*/
static
void
_
sysc_enable
(
struct
omap_hwmod
*
oh
)
static
void
_
enable_sysc
(
struct
omap_hwmod
*
oh
)
{
{
u8
idlemode
,
sf
;
u8
idlemode
,
sf
;
u32
v
;
u32
v
;
...
@@ -659,8 +783,6 @@ static void _sysc_enable(struct omap_hwmod *oh)
...
@@ -659,8 +783,6 @@ static void _sysc_enable(struct omap_hwmod *oh)
_set_module_autoidle
(
oh
,
idlemode
,
&
v
);
_set_module_autoidle
(
oh
,
idlemode
,
&
v
);
}
}
/* XXX OCP ENAWAKEUP bit? */
/*
/*
* XXX The clock framework should handle this, by
* XXX The clock framework should handle this, by
* calling into this code. But this must wait until the
* calling into this code. But this must wait until the
...
@@ -671,10 +793,14 @@ static void _sysc_enable(struct omap_hwmod *oh)
...
@@ -671,10 +793,14 @@ static void _sysc_enable(struct omap_hwmod *oh)
_set_clockactivity
(
oh
,
oh
->
class
->
sysc
->
clockact
,
&
v
);
_set_clockactivity
(
oh
,
oh
->
class
->
sysc
->
clockact
,
&
v
);
_write_sysconfig
(
v
,
oh
);
_write_sysconfig
(
v
,
oh
);
/* If slave is in SMARTIDLE, also enable wakeup */
if
((
sf
&
SYSC_HAS_SIDLEMODE
)
&&
!
(
oh
->
flags
&
HWMOD_SWSUP_SIDLE
))
_enable_wakeup
(
oh
);
}
}
/**
/**
* _
sysc_idle
- try to put a module into idle via OCP_SYSCONFIG
* _
idle_sysc
- try to put a module into idle via OCP_SYSCONFIG
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* If module is marked as SWSUP_SIDLE, force the module into slave
* If module is marked as SWSUP_SIDLE, force the module into slave
...
@@ -682,7 +808,7 @@ static void _sysc_enable(struct omap_hwmod *oh)
...
@@ -682,7 +808,7 @@ static void _sysc_enable(struct omap_hwmod *oh)
* as SWSUP_MSUSPEND, force the module into master standby; otherwise,
* as SWSUP_MSUSPEND, force the module into master standby; otherwise,
* configure it for smart-standby. No return value.
* configure it for smart-standby. No return value.
*/
*/
static
void
_
sysc_idle
(
struct
omap_hwmod
*
oh
)
static
void
_
idle_sysc
(
struct
omap_hwmod
*
oh
)
{
{
u8
idlemode
,
sf
;
u8
idlemode
,
sf
;
u32
v
;
u32
v
;
...
@@ -709,13 +835,13 @@ static void _sysc_idle(struct omap_hwmod *oh)
...
@@ -709,13 +835,13 @@ static void _sysc_idle(struct omap_hwmod *oh)
}
}
/**
/**
* _s
ysc_shutdown
- force a module into idle via OCP_SYSCONFIG
* _s
hutdown_sysc
- force a module into idle via OCP_SYSCONFIG
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* Force the module into slave idle and master suspend. No return
* Force the module into slave idle and master suspend. No return
* value.
* value.
*/
*/
static
void
_s
ysc_shutdown
(
struct
omap_hwmod
*
oh
)
static
void
_s
hutdown_sysc
(
struct
omap_hwmod
*
oh
)
{
{
u32
v
;
u32
v
;
u8
sf
;
u8
sf
;
...
@@ -767,10 +893,10 @@ static struct omap_hwmod *_lookup(const char *name)
...
@@ -767,10 +893,10 @@ static struct omap_hwmod *_lookup(const char *name)
* @data: not used; pass NULL
* @data: not used; pass NULL
*
*
* Called by omap_hwmod_late_init() (after omap2_clk_init()).
* Called by omap_hwmod_late_init() (after omap2_clk_init()).
* Resolves all clock names embedded in the hwmod.
Must be called
* Resolves all clock names embedded in the hwmod.
Returns -EINVAL if
*
with omap_hwmod_mutex held. Returns -EINVAL if the omap_hwmod
*
the omap_hwmod has not yet been registered or if the clocks have
*
has not yet been registered or if the clocks have already bee
n
*
already been initialized, 0 on success, or a non-zero error o
n
*
initialized, 0 on success, or a non-zero error on
failure.
* failure.
*/
*/
static
int
_init_clocks
(
struct
omap_hwmod
*
oh
,
void
*
data
)
static
int
_init_clocks
(
struct
omap_hwmod
*
oh
,
void
*
data
)
{
{
...
@@ -833,57 +959,203 @@ static int _wait_target_ready(struct omap_hwmod *oh)
...
@@ -833,57 +959,203 @@ static int _wait_target_ready(struct omap_hwmod *oh)
return
ret
;
return
ret
;
}
}
/**
* _lookup_hardreset - return the register bit shift for this hwmod/reset line
* @oh: struct omap_hwmod *
* @name: name of the reset line in the context of this hwmod
*
* Return the bit position of the reset line that match the
* input name. Return -ENOENT if not found.
*/
static
u8
_lookup_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
)
{
int
i
;
for
(
i
=
0
;
i
<
oh
->
rst_lines_cnt
;
i
++
)
{
const
char
*
rst_line
=
oh
->
rst_lines
[
i
].
name
;
if
(
!
strcmp
(
rst_line
,
name
))
{
u8
shift
=
oh
->
rst_lines
[
i
].
rst_shift
;
pr_debug
(
"omap_hwmod: %s: _lookup_hardreset: %s: %d
\n
"
,
oh
->
name
,
rst_line
,
shift
);
return
shift
;
}
}
return
-
ENOENT
;
}
/**
* _assert_hardreset - assert the HW reset line of submodules
* contained in the hwmod module.
* @oh: struct omap_hwmod *
* @name: name of the reset line to lookup and assert
*
* Some IP like dsp, ipu or iva contain processor that require
* an HW reset line to be assert / deassert in order to enable fully
* the IP.
*/
static
int
_assert_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
)
{
u8
shift
;
if
(
!
oh
)
return
-
EINVAL
;
shift
=
_lookup_hardreset
(
oh
,
name
);
if
(
IS_ERR_VALUE
(
shift
))
return
shift
;
if
(
cpu_is_omap24xx
()
||
cpu_is_omap34xx
())
return
omap2_prm_assert_hardreset
(
oh
->
prcm
.
omap2
.
module_offs
,
shift
);
else
if
(
cpu_is_omap44xx
())
return
omap4_prm_assert_hardreset
(
oh
->
prcm
.
omap4
.
rstctrl_reg
,
shift
);
else
return
-
EINVAL
;
}
/**
* _deassert_hardreset - deassert the HW reset line of submodules contained
* in the hwmod module.
* @oh: struct omap_hwmod *
* @name: name of the reset line to look up and deassert
*
* Some IP like dsp, ipu or iva contain processor that require
* an HW reset line to be assert / deassert in order to enable fully
* the IP.
*/
static
int
_deassert_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
)
{
u8
shift
;
int
r
;
if
(
!
oh
)
return
-
EINVAL
;
shift
=
_lookup_hardreset
(
oh
,
name
);
if
(
IS_ERR_VALUE
(
shift
))
return
shift
;
if
(
cpu_is_omap24xx
()
||
cpu_is_omap34xx
())
r
=
omap2_prm_deassert_hardreset
(
oh
->
prcm
.
omap2
.
module_offs
,
shift
);
else
if
(
cpu_is_omap44xx
())
r
=
omap4_prm_deassert_hardreset
(
oh
->
prcm
.
omap4
.
rstctrl_reg
,
shift
);
else
return
-
EINVAL
;
if
(
r
==
-
EBUSY
)
pr_warning
(
"omap_hwmod: %s: failed to hardreset
\n
"
,
oh
->
name
);
return
r
;
}
/**
* _read_hardreset - read the HW reset line state of submodules
* contained in the hwmod module
* @oh: struct omap_hwmod *
* @name: name of the reset line to look up and read
*
* Return the state of the reset line.
*/
static
int
_read_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
)
{
u8
shift
;
if
(
!
oh
)
return
-
EINVAL
;
shift
=
_lookup_hardreset
(
oh
,
name
);
if
(
IS_ERR_VALUE
(
shift
))
return
shift
;
if
(
cpu_is_omap24xx
()
||
cpu_is_omap34xx
())
{
return
omap2_prm_is_hardreset_asserted
(
oh
->
prcm
.
omap2
.
module_offs
,
shift
);
}
else
if
(
cpu_is_omap44xx
())
{
return
omap4_prm_is_hardreset_asserted
(
oh
->
prcm
.
omap4
.
rstctrl_reg
,
shift
);
}
else
{
return
-
EINVAL
;
}
}
/**
/**
* _reset - reset an omap_hwmod
* _reset - reset an omap_hwmod
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
* Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
* enabled for this to work. Must be called with omap_hwmod_mutex
* enabled for this to work. Returns -EINVAL if the hwmod cannot be
* held. Returns -EINVAL if the hwmod cannot be reset this way or if
* reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
* the hwmod is in the wrong state, -ETIMEDOUT if the module did not
* the module did not reset in time, or 0 upon success.
* reset in time, or 0 upon success.
*
* In OMAP3 a specific SYSSTATUS register is used to get the reset status.
* Starting in OMAP4, some IPs does not have SYSSTATUS register and instead
* use the SYSCONFIG softreset bit to provide the status.
*
* Note that some IP like McBSP does have a reset control but no reset status.
*/
*/
static
int
_reset
(
struct
omap_hwmod
*
oh
)
static
int
_reset
(
struct
omap_hwmod
*
oh
)
{
{
u32
r
,
v
;
u32
v
;
int
c
=
0
;
int
c
=
0
;
int
ret
=
0
;
if
(
!
oh
->
class
->
sysc
||
if
(
!
oh
->
class
->
sysc
||
!
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSC_HAS_SOFTRESET
)
||
!
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSC_HAS_SOFTRESET
))
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSS_MISSING
))
return
-
EINVAL
;
return
-
EINVAL
;
/* clocks must be on for this operation */
/* clocks must be on for this operation */
if
(
oh
->
_state
!=
_HWMOD_STATE_ENABLED
)
{
if
(
oh
->
_state
!=
_HWMOD_STATE_ENABLED
)
{
WARN
(
1
,
"omap_hwmod: %s: reset can only be entered from "
pr_warning
(
"omap_hwmod: %s: reset can only be entered from "
"enabled state
\n
"
,
oh
->
name
);
"enabled state
\n
"
,
oh
->
name
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* For some modules, all optionnal clocks need to be enabled as well */
if
(
oh
->
flags
&
HWMOD_CONTROL_OPT_CLKS_IN_RESET
)
_enable_optional_clocks
(
oh
);
pr_debug
(
"omap_hwmod: %s: resetting
\n
"
,
oh
->
name
);
pr_debug
(
"omap_hwmod: %s: resetting
\n
"
,
oh
->
name
);
v
=
oh
->
_sysc_cache
;
v
=
oh
->
_sysc_cache
;
r
=
_set_softreset
(
oh
,
&
v
);
r
et
=
_set_softreset
(
oh
,
&
v
);
if
(
r
)
if
(
r
et
)
return
r
;
goto
dis_opt_clks
;
_write_sysconfig
(
v
,
oh
);
_write_sysconfig
(
v
,
oh
);
omap_test_timeout
((
omap_hwmod_readl
(
oh
,
oh
->
class
->
sysc
->
syss_offs
)
&
if
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSS_HAS_RESET_STATUS
)
SYSS_RESETDONE_MASK
),
omap_test_timeout
((
omap_hwmod_readl
(
oh
,
MAX_MODULE_RESET_WAIT
,
c
);
oh
->
class
->
sysc
->
syss_offs
)
&
SYSS_RESETDONE_MASK
),
if
(
c
==
MAX_MODULE_RESET_WAIT
)
MAX_MODULE_SOFTRESET_WAIT
,
c
);
WARN
(
1
,
"omap_hwmod: %s: failed to reset in %d usec
\n
"
,
else
if
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSC_HAS_RESET_STATUS
)
oh
->
name
,
MAX_MODULE_RESET_WAIT
);
omap_test_timeout
(
!
(
omap_hwmod_readl
(
oh
,
oh
->
class
->
sysc
->
sysc_offs
)
&
SYSC_TYPE2_SOFTRESET_MASK
),
MAX_MODULE_SOFTRESET_WAIT
,
c
);
if
(
c
==
MAX_MODULE_SOFTRESET_WAIT
)
pr_warning
(
"omap_hwmod: %s: softreset failed (waited %d usec)
\n
"
,
oh
->
name
,
MAX_MODULE_SOFTRESET_WAIT
);
else
else
pr_debug
(
"omap_hwmod: %s: reset in %d usec
\n
"
,
oh
->
name
,
c
);
pr_debug
(
"omap_hwmod: %s:
soft
reset in %d usec
\n
"
,
oh
->
name
,
c
);
/*
/*
* XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
* XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
* _wait_target_ready() or _reset()
* _wait_target_ready() or _reset()
*/
*/
return
(
c
==
MAX_MODULE_RESET_WAIT
)
?
-
ETIMEDOUT
:
0
;
ret
=
(
c
==
MAX_MODULE_SOFTRESET_WAIT
)
?
-
ETIMEDOUT
:
0
;
dis_opt_clks:
if
(
oh
->
flags
&
HWMOD_CONTROL_OPT_CLKS_IN_RESET
)
_disable_optional_clocks
(
oh
);
return
ret
;
}
}
/**
/**
...
@@ -891,9 +1163,11 @@ static int _reset(struct omap_hwmod *oh)
...
@@ -891,9 +1163,11 @@ static int _reset(struct omap_hwmod *oh)
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* Enables an omap_hwmod @oh such that the MPU can access the hwmod's
* Enables an omap_hwmod @oh such that the MPU can access the hwmod's
* register target. Must be called with omap_hwmod_mutex held.
* register target. (This function has a full name --
* Returns -EINVAL if the hwmod is in the wrong state or passes along
* _omap_hwmod_enable() rather than simply _enable() -- because it is
* the return value of _wait_target_ready().
* currently required by the pm34xx.c idle loop.) Returns -EINVAL if
* the hwmod is in the wrong state or passes along the return value of
* _wait_target_ready().
*/
*/
int
_omap_hwmod_enable
(
struct
omap_hwmod
*
oh
)
int
_omap_hwmod_enable
(
struct
omap_hwmod
*
oh
)
{
{
...
@@ -909,6 +1183,15 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
...
@@ -909,6 +1183,15 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
pr_debug
(
"omap_hwmod: %s: enabling
\n
"
,
oh
->
name
);
pr_debug
(
"omap_hwmod: %s: enabling
\n
"
,
oh
->
name
);
/*
* If an IP contains only one HW reset line, then de-assert it in order
* to allow to enable the clocks. Otherwise the PRCM will return
* Intransition status, and the init will failed.
*/
if
((
oh
->
_state
==
_HWMOD_STATE_INITIALIZED
||
oh
->
_state
==
_HWMOD_STATE_DISABLED
)
&&
oh
->
rst_lines_cnt
==
1
)
_deassert_hardreset
(
oh
,
oh
->
rst_lines
[
0
].
name
);
/* XXX mux balls */
/* XXX mux balls */
_add_initiator_dep
(
oh
,
mpu_oh
);
_add_initiator_dep
(
oh
,
mpu_oh
);
...
@@ -922,7 +1205,7 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
...
@@ -922,7 +1205,7 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
if
(
oh
->
class
->
sysc
)
{
if
(
oh
->
class
->
sysc
)
{
if
(
!
(
oh
->
_int_flags
&
_HWMOD_SYSCONFIG_LOADED
))
if
(
!
(
oh
->
_int_flags
&
_HWMOD_SYSCONFIG_LOADED
))
_update_sysc_cache
(
oh
);
_update_sysc_cache
(
oh
);
_
sysc_enable
(
oh
);
_
enable_sysc
(
oh
);
}
}
}
else
{
}
else
{
pr_debug
(
"omap_hwmod: %s: _wait_target_ready: %d
\n
"
,
pr_debug
(
"omap_hwmod: %s: _wait_target_ready: %d
\n
"
,
...
@@ -933,12 +1216,14 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
...
@@ -933,12 +1216,14 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
}
}
/**
/**
* _idle - idle an omap_hwmod
* _
omap_hwmod_
idle - idle an omap_hwmod
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* Idles an omap_hwmod @oh. This should be called once the hwmod has
* Idles an omap_hwmod @oh. This should be called once the hwmod has
* no further work. Returns -EINVAL if the hwmod is in the wrong
* no further work. (This function has a full name --
* state or returns 0.
* _omap_hwmod_idle() rather than simply _idle() -- because it is
* currently required by the pm34xx.c idle loop.) Returns -EINVAL if
* the hwmod is in the wrong state or returns 0.
*/
*/
int
_omap_hwmod_idle
(
struct
omap_hwmod
*
oh
)
int
_omap_hwmod_idle
(
struct
omap_hwmod
*
oh
)
{
{
...
@@ -951,7 +1236,7 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
...
@@ -951,7 +1236,7 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
pr_debug
(
"omap_hwmod: %s: idling
\n
"
,
oh
->
name
);
pr_debug
(
"omap_hwmod: %s: idling
\n
"
,
oh
->
name
);
if
(
oh
->
class
->
sysc
)
if
(
oh
->
class
->
sysc
)
_
sysc_idle
(
oh
);
_
idle_sysc
(
oh
);
_del_initiator_dep
(
oh
,
mpu_oh
);
_del_initiator_dep
(
oh
,
mpu_oh
);
_disable_clocks
(
oh
);
_disable_clocks
(
oh
);
...
@@ -981,10 +1266,21 @@ static int _shutdown(struct omap_hwmod *oh)
...
@@ -981,10 +1266,21 @@ static int _shutdown(struct omap_hwmod *oh)
pr_debug
(
"omap_hwmod: %s: disabling
\n
"
,
oh
->
name
);
pr_debug
(
"omap_hwmod: %s: disabling
\n
"
,
oh
->
name
);
if
(
oh
->
class
->
sysc
)
if
(
oh
->
class
->
sysc
)
_sysc_shutdown
(
oh
);
_shutdown_sysc
(
oh
);
_del_initiator_dep
(
oh
,
mpu_oh
);
/* XXX what about the other system initiators here? DMA, tesla, d2d */
/*
_disable_clocks
(
oh
);
* If an IP contains only one HW reset line, then assert it
* before disabling the clocks and shutting down the IP.
*/
if
(
oh
->
rst_lines_cnt
==
1
)
_assert_hardreset
(
oh
,
oh
->
rst_lines
[
0
].
name
);
/* clocks and deps are already disabled in idle */
if
(
oh
->
_state
==
_HWMOD_STATE_ENABLED
)
{
_del_initiator_dep
(
oh
,
mpu_oh
);
/* XXX what about the other system initiators here? dma, dsp */
_disable_clocks
(
oh
);
}
/* XXX Should this code also force-disable the optional clocks? */
/* XXX Should this code also force-disable the optional clocks? */
/* XXX mux any associated balls to safe mode */
/* XXX mux any associated balls to safe mode */
...
@@ -1000,11 +1296,10 @@ static int _shutdown(struct omap_hwmod *oh)
...
@@ -1000,11 +1296,10 @@ static int _shutdown(struct omap_hwmod *oh)
* @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
* @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
*
*
* Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
* Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
* OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex held.
* OCP_SYSCONFIG register. @skip_setup_idle is intended to be used on
* @skip_setup_idle is intended to be used on a system that will not
* a system that will not call omap_hwmod_enable() to enable devices
* call omap_hwmod_enable() to enable devices (e.g., a system without
* (e.g., a system without PM runtime). Returns -EINVAL if the hwmod
* PM runtime). Returns -EINVAL if the hwmod is in the wrong state or
* is in the wrong state or returns 0.
* returns 0.
*/
*/
static
int
_setup
(
struct
omap_hwmod
*
oh
,
void
*
data
)
static
int
_setup
(
struct
omap_hwmod
*
oh
,
void
*
data
)
{
{
...
@@ -1034,8 +1329,19 @@ static int _setup(struct omap_hwmod *oh, void *data)
...
@@ -1034,8 +1329,19 @@ static int _setup(struct omap_hwmod *oh, void *data)
}
}
}
}
mutex_init
(
&
oh
->
_mutex
);
oh
->
_state
=
_HWMOD_STATE_INITIALIZED
;
oh
->
_state
=
_HWMOD_STATE_INITIALIZED
;
/*
* In the case of hwmod with hardreset that should not be
* de-assert at boot time, we have to keep the module
* initialized, because we cannot enable it properly with the
* reset asserted. Exit without warning because that behavior is
* expected.
*/
if
((
oh
->
flags
&
HWMOD_INIT_NO_RESET
)
&&
oh
->
rst_lines_cnt
==
1
)
return
0
;
r
=
_omap_hwmod_enable
(
oh
);
r
=
_omap_hwmod_enable
(
oh
);
if
(
r
)
{
if
(
r
)
{
pr_warning
(
"omap_hwmod: %s: cannot be enabled (%d)
\n
"
,
pr_warning
(
"omap_hwmod: %s: cannot be enabled (%d)
\n
"
,
...
@@ -1044,16 +1350,16 @@ static int _setup(struct omap_hwmod *oh, void *data)
...
@@ -1044,16 +1350,16 @@ static int _setup(struct omap_hwmod *oh, void *data)
}
}
if
(
!
(
oh
->
flags
&
HWMOD_INIT_NO_RESET
))
{
if
(
!
(
oh
->
flags
&
HWMOD_INIT_NO_RESET
))
{
_reset
(
oh
);
/*
/*
* XXX Do the OCP_SYSCONFIG bits need to be
* OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
* reprogrammed after a reset? If not, then this can
* The _omap_hwmod_enable() function should be split to
* be removed. If they do, then probably the
* avoid the rewrite of the OCP_SYSCONFIG register.
* _omap_hwmod_enable() function should be split to avoid the
* rewrite of the OCP_SYSCONFIG register.
*/
*/
if
(
oh
->
class
->
sysc
)
{
if
(
oh
->
class
->
sysc
)
{
_update_sysc_cache
(
oh
);
_update_sysc_cache
(
oh
);
_
sysc_enable
(
oh
);
_
enable_sysc
(
oh
);
}
}
}
}
...
@@ -1309,7 +1615,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh)
...
@@ -1309,7 +1615,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh)
* omap_hwmod_enable - enable an omap_hwmod
* omap_hwmod_enable - enable an omap_hwmod
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* Enable an omap_hw
om
d @oh. Intended to be called by omap_device_enable().
* Enable an omap_hw
mo
d @oh. Intended to be called by omap_device_enable().
* Returns -EINVAL on error or passes along the return value from _enable().
* Returns -EINVAL on error or passes along the return value from _enable().
*/
*/
int
omap_hwmod_enable
(
struct
omap_hwmod
*
oh
)
int
omap_hwmod_enable
(
struct
omap_hwmod
*
oh
)
...
@@ -1319,9 +1625,9 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
...
@@ -1319,9 +1625,9 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
if
(
!
oh
)
if
(
!
oh
)
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
r
=
_omap_hwmod_enable
(
oh
);
r
=
_omap_hwmod_enable
(
oh
);
mutex_unlock
(
&
o
map_hwmod
_mutex
);
mutex_unlock
(
&
o
h
->
_mutex
);
return
r
;
return
r
;
}
}
...
@@ -1331,7 +1637,7 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
...
@@ -1331,7 +1637,7 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
* omap_hwmod_idle - idle an omap_hwmod
* omap_hwmod_idle - idle an omap_hwmod
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* Idle an omap_hw
om
d @oh. Intended to be called by omap_device_idle().
* Idle an omap_hw
mo
d @oh. Intended to be called by omap_device_idle().
* Returns -EINVAL on error or passes along the return value from _idle().
* Returns -EINVAL on error or passes along the return value from _idle().
*/
*/
int
omap_hwmod_idle
(
struct
omap_hwmod
*
oh
)
int
omap_hwmod_idle
(
struct
omap_hwmod
*
oh
)
...
@@ -1339,9 +1645,9 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
...
@@ -1339,9 +1645,9 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
if
(
!
oh
)
if
(
!
oh
)
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
_omap_hwmod_idle
(
oh
);
_omap_hwmod_idle
(
oh
);
mutex_unlock
(
&
o
map_hwmod
_mutex
);
mutex_unlock
(
&
o
h
->
_mutex
);
return
0
;
return
0
;
}
}
...
@@ -1350,7 +1656,7 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
...
@@ -1350,7 +1656,7 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
* omap_hwmod_shutdown - shutdown an omap_hwmod
* omap_hwmod_shutdown - shutdown an omap_hwmod
* @oh: struct omap_hwmod *
* @oh: struct omap_hwmod *
*
*
* Shutdown an omap_hw
om
d @oh. Intended to be called by
* Shutdown an omap_hw
mo
d @oh. Intended to be called by
* omap_device_shutdown(). Returns -EINVAL on error or passes along
* omap_device_shutdown(). Returns -EINVAL on error or passes along
* the return value from _shutdown().
* the return value from _shutdown().
*/
*/
...
@@ -1359,9 +1665,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
...
@@ -1359,9 +1665,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
if
(
!
oh
)
if
(
!
oh
)
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
_shutdown
(
oh
);
_shutdown
(
oh
);
mutex_unlock
(
&
o
map_hwmod
_mutex
);
mutex_unlock
(
&
o
h
->
_mutex
);
return
0
;
return
0
;
}
}
...
@@ -1374,9 +1680,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
...
@@ -1374,9 +1680,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
*/
*/
int
omap_hwmod_enable_clocks
(
struct
omap_hwmod
*
oh
)
int
omap_hwmod_enable_clocks
(
struct
omap_hwmod
*
oh
)
{
{
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
_enable_clocks
(
oh
);
_enable_clocks
(
oh
);
mutex_unlock
(
&
o
map_hwmod
_mutex
);
mutex_unlock
(
&
o
h
->
_mutex
);
return
0
;
return
0
;
}
}
...
@@ -1389,9 +1695,9 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
...
@@ -1389,9 +1695,9 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
*/
*/
int
omap_hwmod_disable_clocks
(
struct
omap_hwmod
*
oh
)
int
omap_hwmod_disable_clocks
(
struct
omap_hwmod
*
oh
)
{
{
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
_disable_clocks
(
oh
);
_disable_clocks
(
oh
);
mutex_unlock
(
&
o
map_hwmod
_mutex
);
mutex_unlock
(
&
o
h
->
_mutex
);
return
0
;
return
0
;
}
}
...
@@ -1430,20 +1736,18 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
...
@@ -1430,20 +1736,18 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
*
*
* Under some conditions, a driver may wish to reset the entire device.
* Under some conditions, a driver may wish to reset the entire device.
* Called from omap_device code. Returns -EINVAL on error or passes along
* Called from omap_device code. Returns -EINVAL on error or passes along
* the return value from _reset()
/_enable()
.
* the return value from _reset().
*/
*/
int
omap_hwmod_reset
(
struct
omap_hwmod
*
oh
)
int
omap_hwmod_reset
(
struct
omap_hwmod
*
oh
)
{
{
int
r
;
int
r
;
if
(
!
oh
||
!
(
oh
->
_state
&
_HWMOD_STATE_ENABLED
)
)
if
(
!
oh
)
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
r
=
_reset
(
oh
);
r
=
_reset
(
oh
);
if
(
!
r
)
mutex_unlock
(
&
oh
->
_mutex
);
r
=
_omap_hwmod_enable
(
oh
);
mutex_unlock
(
&
omap_hwmod_mutex
);
return
r
;
return
r
;
}
}
...
@@ -1468,7 +1772,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
...
@@ -1468,7 +1772,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
{
{
int
ret
,
i
;
int
ret
,
i
;
ret
=
oh
->
mpu_irqs_cnt
+
oh
->
sdma_
ch
s_cnt
;
ret
=
oh
->
mpu_irqs_cnt
+
oh
->
sdma_
req
s_cnt
;
for
(
i
=
0
;
i
<
oh
->
slaves_cnt
;
i
++
)
for
(
i
=
0
;
i
<
oh
->
slaves_cnt
;
i
++
)
ret
+=
oh
->
slaves
[
i
]
->
addr_cnt
;
ret
+=
oh
->
slaves
[
i
]
->
addr_cnt
;
...
@@ -1501,10 +1805,10 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
...
@@ -1501,10 +1805,10 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
r
++
;
r
++
;
}
}
for
(
i
=
0
;
i
<
oh
->
sdma_
ch
s_cnt
;
i
++
)
{
for
(
i
=
0
;
i
<
oh
->
sdma_
req
s_cnt
;
i
++
)
{
(
res
+
r
)
->
name
=
(
oh
->
sdma_
ch
s
+
i
)
->
name
;
(
res
+
r
)
->
name
=
(
oh
->
sdma_
req
s
+
i
)
->
name
;
(
res
+
r
)
->
start
=
(
oh
->
sdma_
chs
+
i
)
->
dma_ch
;
(
res
+
r
)
->
start
=
(
oh
->
sdma_
reqs
+
i
)
->
dma_req
;
(
res
+
r
)
->
end
=
(
oh
->
sdma_
chs
+
i
)
->
dma_ch
;
(
res
+
r
)
->
end
=
(
oh
->
sdma_
reqs
+
i
)
->
dma_req
;
(
res
+
r
)
->
flags
=
IORESOURCE_DMA
;
(
res
+
r
)
->
flags
=
IORESOURCE_DMA
;
r
++
;
r
++
;
}
}
...
@@ -1644,9 +1948,9 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
...
@@ -1644,9 +1948,9 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
!
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSC_HAS_ENAWAKEUP
))
!
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSC_HAS_ENAWAKEUP
))
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
_enable_wakeup
(
oh
);
_enable_wakeup
(
oh
);
mutex_unlock
(
&
o
map_hwmod
_mutex
);
mutex_unlock
(
&
o
h
->
_mutex
);
return
0
;
return
0
;
}
}
...
@@ -1669,13 +1973,91 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
...
@@ -1669,13 +1973,91 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
!
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSC_HAS_ENAWAKEUP
))
!
(
oh
->
class
->
sysc
->
sysc_flags
&
SYSC_HAS_ENAWAKEUP
))
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
o
map_hwmod
_mutex
);
mutex_lock
(
&
o
h
->
_mutex
);
_disable_wakeup
(
oh
);
_disable_wakeup
(
oh
);
mutex_unlock
(
&
o
map_hwmod
_mutex
);
mutex_unlock
(
&
o
h
->
_mutex
);
return
0
;
return
0
;
}
}
/**
* omap_hwmod_assert_hardreset - assert the HW reset line of submodules
* contained in the hwmod module.
* @oh: struct omap_hwmod *
* @name: name of the reset line to lookup and assert
*
* Some IP like dsp, ipu or iva contain processor that require
* an HW reset line to be assert / deassert in order to enable fully
* the IP. Returns -EINVAL if @oh is null or if the operation is not
* yet supported on this OMAP; otherwise, passes along the return value
* from _assert_hardreset().
*/
int
omap_hwmod_assert_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
)
{
int
ret
;
if
(
!
oh
)
return
-
EINVAL
;
mutex_lock
(
&
oh
->
_mutex
);
ret
=
_assert_hardreset
(
oh
,
name
);
mutex_unlock
(
&
oh
->
_mutex
);
return
ret
;
}
/**
* omap_hwmod_deassert_hardreset - deassert the HW reset line of submodules
* contained in the hwmod module.
* @oh: struct omap_hwmod *
* @name: name of the reset line to look up and deassert
*
* Some IP like dsp, ipu or iva contain processor that require
* an HW reset line to be assert / deassert in order to enable fully
* the IP. Returns -EINVAL if @oh is null or if the operation is not
* yet supported on this OMAP; otherwise, passes along the return value
* from _deassert_hardreset().
*/
int
omap_hwmod_deassert_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
)
{
int
ret
;
if
(
!
oh
)
return
-
EINVAL
;
mutex_lock
(
&
oh
->
_mutex
);
ret
=
_deassert_hardreset
(
oh
,
name
);
mutex_unlock
(
&
oh
->
_mutex
);
return
ret
;
}
/**
* omap_hwmod_read_hardreset - read the HW reset line state of submodules
* contained in the hwmod module
* @oh: struct omap_hwmod *
* @name: name of the reset line to look up and read
*
* Return the current state of the hwmod @oh's reset line named @name:
* returns -EINVAL upon parameter error or if this operation
* is unsupported on the current OMAP; otherwise, passes along the return
* value from _read_hardreset().
*/
int
omap_hwmod_read_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
)
{
int
ret
;
if
(
!
oh
)
return
-
EINVAL
;
mutex_lock
(
&
oh
->
_mutex
);
ret
=
_read_hardreset
(
oh
,
name
);
mutex_unlock
(
&
oh
->
_mutex
);
return
ret
;
}
/**
/**
* omap_hwmod_for_each_by_class - call @fn for each hwmod of class @classname
* omap_hwmod_for_each_by_class - call @fn for each hwmod of class @classname
* @classname: struct omap_hwmod_class name to search for
* @classname: struct omap_hwmod_class name to search for
...
...
arch/arm/mach-omap2/prcm.c
View file @
9af2ebbd
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#include "cm.h"
#include "cm.h"
#include "prm.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
#include "prm-regbits-24xx.h"
#include "prm-regbits-44xx.h"
static
void
__iomem
*
prm_base
;
static
void
__iomem
*
prm_base
;
static
void
__iomem
*
cm_base
;
static
void
__iomem
*
cm_base
;
...
@@ -161,8 +162,8 @@ void omap_prcm_arch_reset(char mode, const char *cmd)
...
@@ -161,8 +162,8 @@ void omap_prcm_arch_reset(char mode, const char *cmd)
prm_set_mod_reg_bits
(
OMAP_RST_DPLL3_MASK
,
prcm_offs
,
prm_set_mod_reg_bits
(
OMAP_RST_DPLL3_MASK
,
prcm_offs
,
OMAP2_RM_RSTCTRL
);
OMAP2_RM_RSTCTRL
);
if
(
cpu_is_omap44xx
())
if
(
cpu_is_omap44xx
())
prm_set_mod_reg_bits
(
OMAP
_RST_DPLL3_MASK
,
prcm_offs
,
prm_set_mod_reg_bits
(
OMAP
4430_RST_GLOBAL_WARM_SW_MASK
,
OMAP4_RM_RSTCTRL
);
prcm_offs
,
OMAP4_RM_RSTCTRL
);
}
}
static
inline
u32
__omap_prcm_read
(
void
__iomem
*
base
,
s16
module
,
u16
reg
)
static
inline
u32
__omap_prcm_read
(
void
__iomem
*
base
,
s16
module
,
u16
reg
)
...
@@ -215,6 +216,30 @@ u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
...
@@ -215,6 +216,30 @@ u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
return
v
;
return
v
;
}
}
/* Read a PRM register, AND it, and shift the result down to bit 0 */
u32
omap4_prm_read_bits_shift
(
void
__iomem
*
reg
,
u32
mask
)
{
u32
v
;
v
=
__raw_readl
(
reg
);
v
&=
mask
;
v
>>=
__ffs
(
mask
);
return
v
;
}
/* Read-modify-write a register in a PRM module. Caller must lock */
u32
omap4_prm_rmw_reg_bits
(
u32
mask
,
u32
bits
,
void
__iomem
*
reg
)
{
u32
v
;
v
=
__raw_readl
(
reg
);
v
&=
~
mask
;
v
|=
bits
;
__raw_writel
(
v
,
reg
);
return
v
;
}
/* Read a register in a CM module */
/* Read a register in a CM module */
u32
cm_read_mod_reg
(
s16
module
,
u16
idx
)
u32
cm_read_mod_reg
(
s16
module
,
u16
idx
)
{
{
...
...
arch/arm/mach-omap2/prm.h
View file @
9af2ebbd
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
* OMAP2/3 Power/Reset Management (PRM) register definitions
* OMAP2/3 Power/Reset Management (PRM) register definitions
*
*
* Copyright (C) 2007-2009 Texas Instruments, Inc.
* Copyright (C) 2007-2009 Texas Instruments, Inc.
* Copyright (C) 20
09
Nokia Corporation
* Copyright (C) 20
10
Nokia Corporation
*
*
* Written by Paul Walmsley
* Written by Paul Walmsley
*
*
...
@@ -246,6 +246,15 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
...
@@ -246,6 +246,15 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
return
prm_rmw_mod_reg_bits
(
bits
,
0x0
,
module
,
idx
);
return
prm_rmw_mod_reg_bits
(
bits
,
0x0
,
module
,
idx
);
}
}
/* These omap2_ PRM functions apply to both OMAP2 and 3 */
int
omap2_prm_is_hardreset_asserted
(
s16
prm_mod
,
u8
shift
);
int
omap2_prm_assert_hardreset
(
s16
prm_mod
,
u8
shift
);
int
omap2_prm_deassert_hardreset
(
s16
prm_mod
,
u8
shift
);
int
omap4_prm_is_hardreset_asserted
(
void
__iomem
*
rstctrl_reg
,
u8
shift
);
int
omap4_prm_assert_hardreset
(
void
__iomem
*
rstctrl_reg
,
u8
shift
);
int
omap4_prm_deassert_hardreset
(
void
__iomem
*
rstctrl_reg
,
u8
shift
);
#endif
#endif
/*
/*
...
@@ -398,4 +407,11 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
...
@@ -398,4 +407,11 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
#define OMAP_POWERSTATE_MASK (0x3 << 0)
#define OMAP_POWERSTATE_MASK (0x3 << 0)
/*
* MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
* submodule to exit hardreset
*/
#define MAX_MODULE_HARDRESET_WAIT 10000
#endif
#endif
arch/arm/mach-omap2/prm2xxx_3xxx.c
0 → 100644
View file @
9af2ebbd
/*
* OMAP2/3 PRM module functions
*
* Copyright (C) 2010 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
* Benoît Cousson
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <plat/common.h>
#include <plat/cpu.h>
#include <plat/prcm.h>
#include "prm.h"
#include "prm-regbits-24xx.h"
#include "prm-regbits-34xx.h"
/**
* omap2_prm_is_hardreset_asserted - read the HW reset line state of
* submodules contained in the hwmod module
* @prm_mod: PRM submodule base (e.g. CORE_MOD)
* @shift: register bit shift corresponding to the reset line to check
*
* Returns 1 if the (sub)module hardreset line is currently asserted,
* 0 if the (sub)module hardreset line is not currently asserted, or
* -EINVAL if called while running on a non-OMAP2/3 chip.
*/
int
omap2_prm_is_hardreset_asserted
(
s16
prm_mod
,
u8
shift
)
{
if
(
!
(
cpu_is_omap24xx
()
||
cpu_is_omap34xx
()))
return
-
EINVAL
;
return
prm_read_mod_bits_shift
(
prm_mod
,
OMAP2_RM_RSTCTRL
,
(
1
<<
shift
));
}
/**
* omap2_prm_assert_hardreset - assert the HW reset line of a submodule
* @prm_mod: PRM submodule base (e.g. CORE_MOD)
* @shift: register bit shift corresponding to the reset line to assert
*
* Some IPs like dsp or iva contain processors that require an HW
* reset line to be asserted / deasserted in order to fully enable the
* IP. These modules may have multiple hard-reset lines that reset
* different 'submodules' inside the IP block. This function will
* place the submodule into reset. Returns 0 upon success or -EINVAL
* upon an argument error.
*/
int
omap2_prm_assert_hardreset
(
s16
prm_mod
,
u8
shift
)
{
u32
mask
;
if
(
!
(
cpu_is_omap24xx
()
||
cpu_is_omap34xx
()))
return
-
EINVAL
;
mask
=
1
<<
shift
;
prm_rmw_mod_reg_bits
(
mask
,
mask
,
prm_mod
,
OMAP2_RM_RSTCTRL
);
return
0
;
}
/**
* omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
* @prm_mod: PRM submodule base (e.g. CORE_MOD)
* @shift: register bit shift corresponding to the reset line to deassert
*
* Some IPs like dsp or iva contain processors that require an HW
* reset line to be asserted / deasserted in order to fully enable the
* IP. These modules may have multiple hard-reset lines that reset
* different 'submodules' inside the IP block. This function will
* take the submodule out of reset and wait until the PRCM indicates
* that the reset has completed before returning. Returns 0 upon success or
* -EINVAL upon an argument error, -EEXIST if the submodule was already out
* of reset, or -EBUSY if the submodule did not exit reset promptly.
*/
int
omap2_prm_deassert_hardreset
(
s16
prm_mod
,
u8
shift
)
{
u32
mask
;
int
c
;
if
(
!
(
cpu_is_omap24xx
()
||
cpu_is_omap34xx
()))
return
-
EINVAL
;
mask
=
1
<<
shift
;
/* Check the current status to avoid de-asserting the line twice */
if
(
prm_read_mod_bits_shift
(
prm_mod
,
OMAP2_RM_RSTCTRL
,
mask
)
==
0
)
return
-
EEXIST
;
/* Clear the reset status by writing 1 to the status bit */
prm_rmw_mod_reg_bits
(
0xffffffff
,
mask
,
prm_mod
,
OMAP2_RM_RSTST
);
/* de-assert the reset control line */
prm_rmw_mod_reg_bits
(
mask
,
0
,
prm_mod
,
OMAP2_RM_RSTCTRL
);
/* wait the status to be set */
omap_test_timeout
(
prm_read_mod_bits_shift
(
prm_mod
,
OMAP2_RM_RSTST
,
mask
),
MAX_MODULE_HARDRESET_WAIT
,
c
);
return
(
c
==
MAX_MODULE_HARDRESET_WAIT
)
?
-
EBUSY
:
0
;
}
arch/arm/mach-omap2/prm44xx.c
0 → 100644
View file @
9af2ebbd
/*
* OMAP4 PRM module functions
*
* Copyright (C) 2010 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
* Benoît Cousson
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <plat/common.h>
#include <plat/cpu.h>
#include <plat/prcm.h>
#include "prm.h"
#include "prm-regbits-44xx.h"
/*
* Address offset (in bytes) between the reset control and the reset
* status registers: 4 bytes on OMAP4
*/
#define OMAP4_RST_CTRL_ST_OFFSET 4
/**
* omap4_prm_is_hardreset_asserted - read the HW reset line state of
* submodules contained in the hwmod module
* @rstctrl_reg: RM_RSTCTRL register address for this module
* @shift: register bit shift corresponding to the reset line to check
*
* Returns 1 if the (sub)module hardreset line is currently asserted,
* 0 if the (sub)module hardreset line is not currently asserted, or
* -EINVAL upon parameter error.
*/
int
omap4_prm_is_hardreset_asserted
(
void
__iomem
*
rstctrl_reg
,
u8
shift
)
{
if
(
!
cpu_is_omap44xx
()
||
!
rstctrl_reg
)
return
-
EINVAL
;
return
omap4_prm_read_bits_shift
(
rstctrl_reg
,
(
1
<<
shift
));
}
/**
* omap4_prm_assert_hardreset - assert the HW reset line of a submodule
* @rstctrl_reg: RM_RSTCTRL register address for this module
* @shift: register bit shift corresponding to the reset line to assert
*
* Some IPs like dsp, ipu or iva contain processors that require an HW
* reset line to be asserted / deasserted in order to fully enable the
* IP. These modules may have multiple hard-reset lines that reset
* different 'submodules' inside the IP block. This function will
* place the submodule into reset. Returns 0 upon success or -EINVAL
* upon an argument error.
*/
int
omap4_prm_assert_hardreset
(
void
__iomem
*
rstctrl_reg
,
u8
shift
)
{
u32
mask
;
if
(
!
cpu_is_omap44xx
()
||
!
rstctrl_reg
)
return
-
EINVAL
;
mask
=
1
<<
shift
;
omap4_prm_rmw_reg_bits
(
mask
,
mask
,
rstctrl_reg
);
return
0
;
}
/**
* omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
* @rstctrl_reg: RM_RSTCTRL register address for this module
* @shift: register bit shift corresponding to the reset line to deassert
*
* Some IPs like dsp, ipu or iva contain processors that require an HW
* reset line to be asserted / deasserted in order to fully enable the
* IP. These modules may have multiple hard-reset lines that reset
* different 'submodules' inside the IP block. This function will
* take the submodule out of reset and wait until the PRCM indicates
* that the reset has completed before returning. Returns 0 upon success or
* -EINVAL upon an argument error, -EEXIST if the submodule was already out
* of reset, or -EBUSY if the submodule did not exit reset promptly.
*/
int
omap4_prm_deassert_hardreset
(
void
__iomem
*
rstctrl_reg
,
u8
shift
)
{
u32
mask
;
void
__iomem
*
rstst_reg
;
int
c
;
if
(
!
cpu_is_omap44xx
()
||
!
rstctrl_reg
)
return
-
EINVAL
;
rstst_reg
=
rstctrl_reg
+
OMAP4_RST_CTRL_ST_OFFSET
;
mask
=
1
<<
shift
;
/* Check the current status to avoid de-asserting the line twice */
if
(
omap4_prm_read_bits_shift
(
rstctrl_reg
,
mask
)
==
0
)
return
-
EEXIST
;
/* Clear the reset status by writing 1 to the status bit */
omap4_prm_rmw_reg_bits
(
0xffffffff
,
mask
,
rstst_reg
);
/* de-assert the reset control line */
omap4_prm_rmw_reg_bits
(
mask
,
0
,
rstctrl_reg
);
/* wait the status to be set */
omap_test_timeout
(
omap4_prm_read_bits_shift
(
rstst_reg
,
mask
),
MAX_MODULE_HARDRESET_WAIT
,
c
);
return
(
c
==
MAX_MODULE_HARDRESET_WAIT
)
?
-
EBUSY
:
0
;
}
arch/arm/plat-omap/include/plat/omap_hwmod.h
View file @
9af2ebbd
...
@@ -14,19 +14,16 @@
...
@@ -14,19 +14,16 @@
*
*
* These headers and macros are used to define OMAP on-chip module
* These headers and macros are used to define OMAP on-chip module
* data and their integration with other OMAP modules and Linux.
* data and their integration with other OMAP modules and Linux.
*
* Copious documentation and references can also be found in the
* References:
* omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
* - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
* writing).
* - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
* - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
* - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
* - Open Core Protocol Specification 2.2
*
*
* To do:
* To do:
* - add interconnect error log structures
* - add interconnect error log structures
* - add pinmuxing
* - add pinmuxing
* - init_conn_id_bit (CONNID_BIT_VECTOR)
* - init_conn_id_bit (CONNID_BIT_VECTOR)
* - implement default hwmod SMS/SDRC flags?
* - implement default hwmod SMS/SDRC flags?
* - remove unused fields
*
*
*/
*/
#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
...
@@ -35,6 +32,7 @@
...
@@ -35,6 +32,7 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/list.h>
#include <linux/ioport.h>
#include <linux/ioport.h>
#include <linux/mutex.h>
#include <plat/cpu.h>
#include <plat/cpu.h>
struct
omap_device
;
struct
omap_device
;
...
@@ -96,7 +94,7 @@ struct omap_hwmod_irq_info {
...
@@ -96,7 +94,7 @@ struct omap_hwmod_irq_info {
/**
/**
* struct omap_hwmod_dma_info - DMA channels used by the hwmod
* struct omap_hwmod_dma_info - DMA channels used by the hwmod
* @name: name of the DMA channel (module local name)
* @name: name of the DMA channel (module local name)
* @dma_
ch: DMA channel
ID
* @dma_
req: DMA request
ID
*
*
* @name should be something short, e.g., "tx" or "rx". It is for use
* @name should be something short, e.g., "tx" or "rx". It is for use
* by platform_get_resource_byname(). It is defined locally to the
* by platform_get_resource_byname(). It is defined locally to the
...
@@ -104,7 +102,20 @@ struct omap_hwmod_irq_info {
...
@@ -104,7 +102,20 @@ struct omap_hwmod_irq_info {
*/
*/
struct
omap_hwmod_dma_info
{
struct
omap_hwmod_dma_info
{
const
char
*
name
;
const
char
*
name
;
u16
dma_ch
;
u16
dma_req
;
};
/**
* struct omap_hwmod_rst_info - IPs reset lines use by hwmod
* @name: name of the reset line (module local name)
* @rst_shift: Offset of the reset bit
*
* @name should be something short, e.g., "cpu0" or "rst". It is defined
* locally to the hwmod.
*/
struct
omap_hwmod_rst_info
{
const
char
*
name
;
u8
rst_shift
;
};
};
/**
/**
...
@@ -237,8 +248,9 @@ struct omap_hwmod_ocp_if {
...
@@ -237,8 +248,9 @@ struct omap_hwmod_ocp_if {
#define SYSC_HAS_CLOCKACTIVITY (1 << 4)
#define SYSC_HAS_CLOCKACTIVITY (1 << 4)
#define SYSC_HAS_SIDLEMODE (1 << 5)
#define SYSC_HAS_SIDLEMODE (1 << 5)
#define SYSC_HAS_MIDLEMODE (1 << 6)
#define SYSC_HAS_MIDLEMODE (1 << 6)
#define SYSS_
MISSING
(1 << 7)
#define SYSS_
HAS_RESET_STATUS
(1 << 7)
#define SYSC_NO_CACHE (1 << 8)
/* XXX SW flag, belongs elsewhere */
#define SYSC_NO_CACHE (1 << 8)
/* XXX SW flag, belongs elsewhere */
#define SYSC_HAS_RESET_STATUS (1 << 9)
/* omap_hwmod_sysconfig.clockact flags */
/* omap_hwmod_sysconfig.clockact flags */
#define CLOCKACT_TEST_BOTH 0x0
#define CLOCKACT_TEST_BOTH 0x0
...
@@ -327,10 +339,12 @@ struct omap_hwmod_omap2_prcm {
...
@@ -327,10 +339,12 @@ struct omap_hwmod_omap2_prcm {
/**
/**
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
* struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
* @clkctrl_reg: PRCM address of the clock control register
* @clkctrl_reg: PRCM address of the clock control register
* @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
* @submodule_wkdep_bit: bit shift of the WKDEP range
* @submodule_wkdep_bit: bit shift of the WKDEP range
*/
*/
struct
omap_hwmod_omap4_prcm
{
struct
omap_hwmod_omap4_prcm
{
void
__iomem
*
clkctrl_reg
;
void
__iomem
*
clkctrl_reg
;
void
__iomem
*
rstctrl_reg
;
u8
submodule_wkdep_bit
;
u8
submodule_wkdep_bit
;
};
};
...
@@ -352,6 +366,10 @@ struct omap_hwmod_omap4_prcm {
...
@@ -352,6 +366,10 @@ struct omap_hwmod_omap4_prcm {
* HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
* HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
* HWMOD_NO_IDLEST : this module does not have idle status - this is the case
* HWMOD_NO_IDLEST : this module does not have idle status - this is the case
* only for few initiator modules on OMAP2 & 3.
* only for few initiator modules on OMAP2 & 3.
* HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
* This is needed for devices like DSS that require optional clocks enabled
* in order to complete the reset. Optional clocks will be disabled
* again after the reset.
*/
*/
#define HWMOD_SWSUP_SIDLE (1 << 0)
#define HWMOD_SWSUP_SIDLE (1 << 0)
#define HWMOD_SWSUP_MSTANDBY (1 << 1)
#define HWMOD_SWSUP_MSTANDBY (1 << 1)
...
@@ -360,6 +378,7 @@ struct omap_hwmod_omap4_prcm {
...
@@ -360,6 +378,7 @@ struct omap_hwmod_omap4_prcm {
#define HWMOD_NO_OCP_AUTOIDLE (1 << 4)
#define HWMOD_NO_OCP_AUTOIDLE (1 << 4)
#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
#define HWMOD_NO_IDLEST (1 << 6)
#define HWMOD_NO_IDLEST (1 << 6)
#define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7)
/*
/*
* omap_hwmod._int_flags definitions
* omap_hwmod._int_flags definitions
...
@@ -410,7 +429,7 @@ struct omap_hwmod_class {
...
@@ -410,7 +429,7 @@ struct omap_hwmod_class {
* @class: struct omap_hwmod_class * to the class of this hwmod
* @class: struct omap_hwmod_class * to the class of this hwmod
* @od: struct omap_device currently associated with this hwmod (internal use)
* @od: struct omap_device currently associated with this hwmod (internal use)
* @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
* @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
* @sdma_
chs: ptr to an array of SDMA channel IDs (see also sdma_ch
s_cnt)
* @sdma_
reqs: ptr to an array of System DMA request IDs (see sdma_req
s_cnt)
* @prcm: PRCM data pertaining to this hwmod
* @prcm: PRCM data pertaining to this hwmod
* @main_clk: main clock: OMAP clock name
* @main_clk: main clock: OMAP clock name
* @_clk: pointer to the main struct clk (filled in at runtime)
* @_clk: pointer to the main struct clk (filled in at runtime)
...
@@ -424,7 +443,7 @@ struct omap_hwmod_class {
...
@@ -424,7 +443,7 @@ struct omap_hwmod_class {
* @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
* @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
* @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
* @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
* @mpu_irqs_cnt: number of @mpu_irqs
* @mpu_irqs_cnt: number of @mpu_irqs
* @sdma_
chs_cnt: number of @sdma_ch
s
* @sdma_
reqs_cnt: number of @sdma_req
s
* @opt_clks_cnt: number of @opt_clks
* @opt_clks_cnt: number of @opt_clks
* @master_cnt: number of @master entries
* @master_cnt: number of @master entries
* @slaves_cnt: number of @slave entries
* @slaves_cnt: number of @slave entries
...
@@ -433,6 +452,7 @@ struct omap_hwmod_class {
...
@@ -433,6 +452,7 @@ struct omap_hwmod_class {
* @_state: internal-use hwmod state
* @_state: internal-use hwmod state
* @flags: hwmod flags (documented below)
* @flags: hwmod flags (documented below)
* @omap_chip: OMAP chips this hwmod is present on
* @omap_chip: OMAP chips this hwmod is present on
* @_mutex: mutex serializing operations on this hwmod
* @node: list node for hwmod list (internal use)
* @node: list node for hwmod list (internal use)
*
*
* @main_clk refers to this module's "main clock," which for our
* @main_clk refers to this module's "main clock," which for our
...
@@ -448,7 +468,8 @@ struct omap_hwmod {
...
@@ -448,7 +468,8 @@ struct omap_hwmod {
struct
omap_hwmod_class
*
class
;
struct
omap_hwmod_class
*
class
;
struct
omap_device
*
od
;
struct
omap_device
*
od
;
struct
omap_hwmod_irq_info
*
mpu_irqs
;
struct
omap_hwmod_irq_info
*
mpu_irqs
;
struct
omap_hwmod_dma_info
*
sdma_chs
;
struct
omap_hwmod_dma_info
*
sdma_reqs
;
struct
omap_hwmod_rst_info
*
rst_lines
;
union
{
union
{
struct
omap_hwmod_omap2_prcm
omap2
;
struct
omap_hwmod_omap2_prcm
omap2
;
struct
omap_hwmod_omap4_prcm
omap4
;
struct
omap_hwmod_omap4_prcm
omap4
;
...
@@ -461,6 +482,7 @@ struct omap_hwmod {
...
@@ -461,6 +482,7 @@ struct omap_hwmod {
void
*
dev_attr
;
void
*
dev_attr
;
u32
_sysc_cache
;
u32
_sysc_cache
;
void
__iomem
*
_mpu_rt_va
;
void
__iomem
*
_mpu_rt_va
;
struct
mutex
_mutex
;
struct
list_head
node
;
struct
list_head
node
;
u16
flags
;
u16
flags
;
u8
_mpu_port_index
;
u8
_mpu_port_index
;
...
@@ -468,7 +490,8 @@ struct omap_hwmod {
...
@@ -468,7 +490,8 @@ struct omap_hwmod {
u8
msuspendmux_shift
;
u8
msuspendmux_shift
;
u8
response_lat
;
u8
response_lat
;
u8
mpu_irqs_cnt
;
u8
mpu_irqs_cnt
;
u8
sdma_chs_cnt
;
u8
sdma_reqs_cnt
;
u8
rst_lines_cnt
;
u8
opt_clks_cnt
;
u8
opt_clks_cnt
;
u8
masters_cnt
;
u8
masters_cnt
;
u8
slaves_cnt
;
u8
slaves_cnt
;
...
@@ -492,6 +515,10 @@ int omap_hwmod_idle(struct omap_hwmod *oh);
...
@@ -492,6 +515,10 @@ int omap_hwmod_idle(struct omap_hwmod *oh);
int
_omap_hwmod_idle
(
struct
omap_hwmod
*
oh
);
int
_omap_hwmod_idle
(
struct
omap_hwmod
*
oh
);
int
omap_hwmod_shutdown
(
struct
omap_hwmod
*
oh
);
int
omap_hwmod_shutdown
(
struct
omap_hwmod
*
oh
);
int
omap_hwmod_assert_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
);
int
omap_hwmod_deassert_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
);
int
omap_hwmod_read_hardreset
(
struct
omap_hwmod
*
oh
,
const
char
*
name
);
int
omap_hwmod_enable_clocks
(
struct
omap_hwmod
*
oh
);
int
omap_hwmod_enable_clocks
(
struct
omap_hwmod
*
oh
);
int
omap_hwmod_disable_clocks
(
struct
omap_hwmod
*
oh
);
int
omap_hwmod_disable_clocks
(
struct
omap_hwmod
*
oh
);
...
...
arch/arm/plat-omap/include/plat/prcm.h
View file @
9af2ebbd
...
@@ -38,6 +38,8 @@ u32 prm_read_mod_reg(s16 module, u16 idx);
...
@@ -38,6 +38,8 @@ u32 prm_read_mod_reg(s16 module, u16 idx);
void
prm_write_mod_reg
(
u32
val
,
s16
module
,
u16
idx
);
void
prm_write_mod_reg
(
u32
val
,
s16
module
,
u16
idx
);
u32
prm_rmw_mod_reg_bits
(
u32
mask
,
u32
bits
,
s16
module
,
s16
idx
);
u32
prm_rmw_mod_reg_bits
(
u32
mask
,
u32
bits
,
s16
module
,
s16
idx
);
u32
prm_read_mod_bits_shift
(
s16
domain
,
s16
idx
,
u32
mask
);
u32
prm_read_mod_bits_shift
(
s16
domain
,
s16
idx
,
u32
mask
);
u32
omap4_prm_read_bits_shift
(
void
__iomem
*
reg
,
u32
mask
);
u32
omap4_prm_rmw_reg_bits
(
u32
mask
,
u32
bits
,
void
__iomem
*
reg
);
u32
cm_read_mod_reg
(
s16
module
,
u16
idx
);
u32
cm_read_mod_reg
(
s16
module
,
u16
idx
);
void
cm_write_mod_reg
(
u32
val
,
s16
module
,
u16
idx
);
void
cm_write_mod_reg
(
u32
val
,
s16
module
,
u16
idx
);
u32
cm_rmw_mod_reg_bits
(
u32
mask
,
u32
bits
,
s16
module
,
s16
idx
);
u32
cm_rmw_mod_reg_bits
(
u32
mask
,
u32
bits
,
s16
module
,
s16
idx
);
...
...
arch/arm/plat-omap/omap_device.c
View file @
9af2ebbd
...
@@ -82,6 +82,7 @@
...
@@ -82,6 +82,7 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <plat/omap_device.h>
#include <plat/omap_device.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_hwmod.h>
...
@@ -243,6 +244,44 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
...
@@ -243,6 +244,44 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
return
container_of
(
pdev
,
struct
omap_device
,
pdev
);
return
container_of
(
pdev
,
struct
omap_device
,
pdev
);
}
}
/**
* _add_optional_clock_alias - Add clock alias for hwmod optional clocks
* @od: struct omap_device *od
*
* For every optional clock present per hwmod per omap_device, this function
* adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
* if an entry is already present in it with the form <dev-id=NULL, con-id=role>
*
* The function is called from inside omap_device_build_ss(), after
* omap_device_register.
*
* This allows drivers to get a pointer to its optional clocks based on its role
* by calling clk_get(<dev*>, <role>).
*
* No return value.
*/
static
void
_add_optional_clock_alias
(
struct
omap_device
*
od
,
struct
omap_hwmod
*
oh
)
{
int
i
;
for
(
i
=
0
;
i
<
oh
->
opt_clks_cnt
;
i
++
)
{
struct
omap_hwmod_opt_clk
*
oc
;
int
r
;
oc
=
&
oh
->
opt_clks
[
i
];
if
(
!
oc
->
_clk
)
continue
;
r
=
clk_add_alias
(
oc
->
role
,
dev_name
(
&
od
->
pdev
.
dev
),
(
char
*
)
oc
->
clk
,
&
od
->
pdev
.
dev
);
if
(
r
)
pr_err
(
"omap_device: %s: clk_add_alias for %s failed
\n
"
,
dev_name
(
&
od
->
pdev
.
dev
),
oc
->
role
);
}
}
/* Public functions for use by core code */
/* Public functions for use by core code */
...
@@ -421,8 +460,10 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
...
@@ -421,8 +460,10 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
else
else
ret
=
omap_device_register
(
od
);
ret
=
omap_device_register
(
od
);
for
(
i
=
0
;
i
<
oh_cnt
;
i
++
)
for
(
i
=
0
;
i
<
oh_cnt
;
i
++
)
{
hwmods
[
i
]
->
od
=
od
;
hwmods
[
i
]
->
od
=
od
;
_add_optional_clock_alias
(
od
,
hwmods
[
i
]);
}
if
(
ret
)
if
(
ret
)
goto
odbs_exit4
;
goto
odbs_exit4
;
...
...
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