arm: omap2+: hwmod: Add refcounting for modulemode shared by multiple hwmods

Generally, IP blocks/modules within a clock domain each have their own
CM_x_CLKCTRL register, each having it's own MODULEMODE field to manage the
module.

DSS clockdoain, however, has multiple modules in it, but only one register
named CM_DSS_DSS_CLKCTRL, which contains one MODULEMODE register field.

Until now, we defined modulemode only for the top level DSS hwmod("dss_core")
and didn't define it for other DSS hwmods(like "dss_dispc", "dss_dsi1" and so
on). This made the omapdss driver work as the top level DSS platform device
and the rest had a parent-child relationship. This ensured that the parent
hwmod("dss_core") is enabled if any of the children hwmods are enabled while
using omapdss.

This method, however, doesn't work when each hwmod is enabled individually.
This happens early in boot in omap_hwmod_setup_all, where each hwmod is
enabled, and then reset and idled. All the 'children' DSS hwmods fail to enable
and reset, since they don't enable modulemode.

The way to make such modules work both during initialization and when used by
pm runtime API in the driver would be to add refcounting for enabling/disabling
the modulemode field.

We add a new flag bit for the flag in omap_hwmod_omap4_prcm, which tells
omap_hwmod that this hwmod uses a modulemode field shared by other hwmods.

We create a struct called 'modulemode_shared'. The hwmod data file should define
an instance of this struct. Each hwmod that uses this modulemode field should
hold a pointer to this instance.

omap_hwmod's soc enable_module and disable_module ops set the MODULEMODE
reigster bits only when the first module using it is enabled, or the last
module using it is disabled. We serialize accesses to the struct with a
spinlock.

Signed-off-by: Archit Taneja <archit@ti.com>
arm: omap5 hwmod data: Example: Make DSS hwmods share MODULEMODE fields

DSS hwmods share the MODULEMODE field. Add the new HWMOD_OMAP4_MODULEMODE_SHARED
flag, and create a modulemode_shared struct which the DSS hwmods refer to.

This will allow the hwmods to reset properly during boot, and not break things
when the DSS driver runs.

(Note: hdmi and rfbi hwmods still don't reset properly as they don't have their
mainclks as dss_dss_clk, this needs to be changed later).

Signed-off-by: Archit Taneja <archit@ti.com>
CLK: TI: clockdomain: add support for retrying init

Retry init is needed if clockdomains are registered before the corresponding
clocks are ready. In this case, the clockdomain info is added to a list
which will be processed once the clockdomains for next PRCM module are
processed.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
ARM: PRCM: split PRCM module init to their own driver files

Currently, clock providers coming from CM, PRM, and SCRM are all initialized in
prm_common.c.

Move the DT-match tables to their respective files, and create separate init
functions for each module.

Originally worked on by: Tero Kristo <t-kristo@ti.com>

Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Archit Taneja <archit@ti.com>
ARM: OMAP2+: Add CONTROL_MODULE_CORE as a clock provider for DRA7x

In DRA7x SoCs, the CONTROL_MODULE_CORE sub block in the control module has a
few register fields which perform gating or muxing of clocks.

These gate/muxes are generally SoC level clocks entering an IP, which didn't
manage to make it in the clock management related registers for the IP.

Other OMAP SOCs don't seem to have clock related register fields in the control
module.

We create a new table and function to init ctrl-core IPS as clock providers.
This, along with scrm clock providers, are initialized in of_control_init().
We add a compatible string for dra7-ctrl-core in the DT match table.

Signed-off-by: Archit Taneja <archit@ti.com>
ARM: dts: Add ctrl-core DT node for DRA7

Add DT node for the ctrl-core sub module of the DRA7 control module. We map the
CTRL_MODULE_CORE address region up to 0x4a002d60, this region contains register
fields which configure clocks. The remainder of the registers are related to
pad configurations or cross-bar configurations, and therefore aren't mapped.

Signed-off-by: Archit Taneja <archit@ti.com>
ARM: dts: Add dss_deshdcp clock node under dra7-ctrl-core

The DESHDCP clock is required only by the DES-HDCP block within HDMI in DSS.
However, if the clock isn't set before DSS clock domian is enabled, the clock
domain never comes out of idle state.

The DESHDCP clock is enabled/disabled at the DSS boundary by the bit
DSS_DESHDCP_CLKEN in CTRL_CORE_CONTROL_IO_2.

Add dss_deshdcp gate-clock node under dra7-ctrl-core. There are separate bit
fields for enabling and disabling the clock. We just map the enable bit since
this clock doesn't cause any impact if left enabled.

Signed-off-by: Archit Taneja <archit@ti.com>
CLK: TI: Enable dss_deshdcp clock in dra7xx_clk_init

The DESHDCP clock is required only by the DES-HDCP block within HDMI in DSS.
However, if the clock isn't set before DSS clock domian is enabled, the clock
domain never comes out of idle state.

This is because the DSS IP is designed in such a way that if DES-HDCP block
can't transition from idle state, the entire DSS clock domain also cannot
transition from idle to enabled. DES-HDCP block needs the DESHDCP clock
enabled to transition from idle successfully.

We enable the deshdcp clock in dra7xx_clk_init() which happens before omap
hwmods are setup. This clock is effectively a gate clock with the parent as
DSS_L3_GICLK. The parent is an automatically controlled clock by DSS clock
domain and hence doesn't have a clock node associated to it. Since
DSS_L3_GICLK is derived from the OCP clock, we set the dss_deshdcp_clk's
parent as l3_iclk_div.

Leaving this bit enabled doesn't prevent DSS or the system to suspend, and only
a very few flops get this clock all the time. So there is negligible impact.

Signed-off-by: Archit Taneja <archit@ti.com>
OMAPDSS: DPI: Use DPI driver data

DPI related data is currently a static global struct parameter. It is accessed
directly by functions in the driver.

This method won't work if we want the driver to support multiple DPI instances.
Create struct dpi_data, and pass it's pointer to functions which need to use it.

We still have a static instance defined for dpi_data, which is accessed by top
level DPI ops. This will be removed when the driver dynamically allocates
dpi_data for each DPI instance.

Signed-off-by: Archit Taneja <archit@ti.com>
OMAPDSS: DPI: Allocate driver data

Allocate driver data(dpi_data) for each DPI instance. It's allocated in
omap_dpi_probe() when DT isn't used, and in dpi_init_port() when DT is used.
The dpi_data struct instance is no longer global. In the case of DPI ops, it's
retrieved from dpi_get_data_from_dssdev(). 'dssdev' passed by the connected
encoder/panel driver is a pointer to the 'output' member in dpi_data, and thus
can be used to get the DPI instance's driver data. In the case of probe/ini_port
functions, it's set as DPI/DSS device's private data embedded in the
platform_device struct.

Having dpi_data as private data of the platform device will not work for
multiple DPI instances in the DT case. This is because there is no corresponding
platform_device for DPI or SDI, they exist only as ports under the parent DSS
platform_device in the DT case. The DPI port's private data('data' member in
device_node struct) will later be used to store dpi_data.

Signed-off-by: Archit Taneja <archit@ti.com>
OMAPDSS: DPI: Store dpi_data pointer in the DT port's data

DPI and SDI ports are backed by only one parent DSS device. We don't have a
corresponding platform_device for ports under DSS. In order to support multiple
instances of DPI, we need to pass the driver data pointer through the DPI port's
private data ('data' member in device_node struct).

dpi_init_output/dpi_uninit_output are untouched and only used for non-DT case,
these are called when the DPI platform device probed/removed. These funcs will
be removed when non-DT mode is removed.

dpi_init_output_port/dpi_uninit_output_port are created and used for the DT
path, called when DSS inits/uninits it's ports. These new functions retrieve
the dpi_data pointer from 'port->data', and not from the platform device's
data(pdev->dev) like in the non-DT path.

We add some code in dss_uninit_ports() to pass a pointer to the DPI port in
dpi_uninit_port().

Signed-off-by: Archit Taneja <archit@ti.com>
OMAPDSS: DSS: init dss ports cleanly

The init/uninit port functions are used to set up the DPI and SDI outputs under
the dss platform device. A 'reg' property is used to determine whether the node
is DPI or SDI for OMAP34xx DSS revision. For other DSS revisions, only DPI
output exists.

For multiple DPI output instances(introduced in DRA7xx DSS), we would use the
'reg' property in dts to specify the DPI output instance.

The current functions work fine if there is only one DPI output instance in
DSS. For multiple DPI instances, it would get complicated to figure out whether
'reg' is used to specify whether the output is SDI, or another DPI instance.

We create a list of port types supported for each DSS rev, with the index of the
port in the list matching the reg id. This allows us to have a more generic way
to init/uninit ports within DSS, and support multiple DPI ports.

Also, make the uninit_port functions iterative since we will have multiple DPI
ports to uninit in the future.

Signed-off-by: Archit Taneja <archit@ti.com>
OMAPDSS: DT: Get source endpoint by matching reg-id

In omapdss_of_find_source_for_first_ep, we retrieve a source endpoint's DT node,
and then see what omapdss output has the matching device_node pointer in
omap_dss_find_output_by_node.

For all DPI and SDI outputs, the device_node pointer is set as the parent's DSS
device_node pointer. If the source is one of these outputs, the above method
won't work.

To get the correct output for ports within DSS(and in other cases in the future,
where multiple ports might be under one device), we require additional
information which is exclusive to the output port.

We create a new field in omap_dss_device called 'port_num', this provides port
number of the output port corresponding to this device. When searching for the
source endpoint in DT, we extract the 'reg' property from the port corresponding
to the endpoint source. From the list of registered outputs, we pick out that
output which has both dev->of_node and port_num matching with the device_node
pointer and 'reg' of the source endpoint node from DT.

For encoder blocks(the ones which have both an input and output port), we need
to set the port_num as the 'reg' property for the output port as defined in the
DT bindings. We set port_num to 1 in the tfp410 and tpd12s015 encoder drivers.

Signed-off-by: Archit Taneja <archit@ti.com>
OMAPDSS: DPI: Add support for multiple instances

Register DPI outputs, and assign the port_num to them as specified by the
'reg' property in the DPI ports in DT.

To support multiple DPI instances, dpi_get_channel needs to take the DPI
instance's reg-id to get the corresponding channel. Make it take this
argument.We just pass 0 in the non-DT path, since we don't support multiple
instances in the non-DT case.

Signed-off-by: Archit Taneja <archit@ti.com>