mirror of https://gitee.com/openkylin/linux.git
Merge tag 'omap-for-v5.3/ti-sysc-dt-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into arm/dt
ti-sysc dts changes for v5.3 We can now drop the custom dts property "ti,hwmods" for drivers that have the ti-sysc interconnect target module configured in dts. Let's start with a minimal changes to omap4 uart and mmc. We use omap4 as the starting point as it has runtime PM implemented and all the omap variants after that are based on it with similar clkctrl clock for the modules. More devices will be updated later on as they get tested. Note that these changes are based on the related ti-sysc driver changes. * tag 'omap-for-v5.3/ti-sysc-dt-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (21 commits) ARM: dts: Drop legacy custom hwmods property for omap4 mmc ARM: dts: Drop legacy custom hwmods property for omap4 uart bus: ti-sysc: Detect uarts also on omap34xx bus: ti-sysc: Do rstctrl reset handling in two phases bus: ti-sysc: Add support for disabling module without legacy mode bus: ti-sysc: Set ENAWAKEUP if available bus: ti-sysc: Handle swsup idle mode quirks bus: ti-sysc: Handle clockactivity for enable and disable bus: ti-sysc: Enable interconnect target module autoidle bit on enable bus: ti-sysc: Allow QUIRK_LEGACY_IDLE even if legacy_mode is not set bus: ti-sysc: Make OCP reset work for sysstatus and sysconfig reset bits bus: ti-sysc: Support 16-bit writes too bus: ti-sysc: Add support for missing clockdomain handling ARM: dts: dra71x: Disable usb4_tm target module ARM: dts: dra71x: Disable rtc target module ARM: dts: dra76x: Disable usb4_tm target module ARM: dts: dra76x: Disable rtc target module ARM: dts: dra76x: Update MMC2_HS200_MANUAL1 iodelay values ARM: dts: am57xx-idk: Remove support for voltage switching for SD card bus: ti-sysc: Handle devices with no control registers ... Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
b3dbb6e3ef
|
@ -1759,11 +1759,10 @@ target-module@b0000 { /* 0x481b0000, ap 58 50.0 */
|
|||
target-module@cc000 { /* 0x481cc000, ap 60 46.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "d_can0";
|
||||
reg = <0xcc000 0x4>;
|
||||
reg-names = "rev";
|
||||
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
|
||||
clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN0_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN0_CLKCTRL 0>,
|
||||
<&dcan0_fck>;
|
||||
clock-names = "fck", "osc";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0xcc000 0x2000>;
|
||||
|
@ -1782,11 +1781,10 @@ dcan0: can@0 {
|
|||
target-module@d0000 { /* 0x481d0000, ap 62 42.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "d_can1";
|
||||
reg = <0xd0000 0x4>;
|
||||
reg-names = "rev";
|
||||
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
|
||||
clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN1_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN1_CLKCTRL 0>,
|
||||
<&dcan1_fck>;
|
||||
clock-names = "fck", "osc";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0xd0000 0x2000>;
|
||||
|
|
|
@ -1575,8 +1575,6 @@ timer8: timer@0 {
|
|||
target-module@cc000 { /* 0x481cc000, ap 50 46.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "d_can0";
|
||||
reg = <0xcc000 0x4>;
|
||||
reg-names = "rev";
|
||||
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
|
||||
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
|
@ -1596,8 +1594,6 @@ dcan0: can@0 {
|
|||
target-module@d0000 { /* 0x481d0000, ap 52 3a.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "d_can1";
|
||||
reg = <0xd0000 0x4>;
|
||||
reg-names = "rev";
|
||||
/* Domains (P, C): per_pwrdm, l4ls_clkdm */
|
||||
clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
|
|
|
@ -420,6 +420,7 @@ &mmc1 {
|
|||
vqmmc-supply = <&ldo1_reg>;
|
||||
bus-width = <4>;
|
||||
cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */
|
||||
no-1-8-v;
|
||||
};
|
||||
|
||||
&mmc2 {
|
||||
|
|
|
@ -3543,7 +3543,7 @@ timer16: timer@0 {
|
|||
};
|
||||
};
|
||||
|
||||
target-module@38000 { /* 0x48838000, ap 29 12.0 */
|
||||
rtctarget: target-module@38000 { /* 0x48838000, ap 29 12.0 */
|
||||
compatible = "ti,sysc-omap4-simple", "ti,sysc";
|
||||
ti,hwmods = "rtcss";
|
||||
reg = <0x38074 0x4>,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "dra72-evm-common.dtsi"
|
||||
#include "dra71x.dtsi"
|
||||
#include "dra7-mmc-iodelay.dtsi"
|
||||
#include "dra72x-mmc-iodelay.dtsi"
|
||||
#include <dt-bindings/net/ti-dp83867.h>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* 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 "dra72-evm-common.dtsi"
|
||||
|
||||
&rtctarget {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&usb4_tm {
|
||||
status = "disabled";
|
||||
};
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
* Datamanual Revisions:
|
||||
*
|
||||
* DRA76x Silicon Revision 1.0: SPRS993A, Revised July 2017
|
||||
* DRA76x Silicon Revision 1.0: SPRS993E, Revised December 2018
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -169,25 +169,25 @@ mmc1_iodelay_sdr104_conf: mmc1_iodelay_sdr104_conf {
|
|||
/* Corresponds to MMC2_HS200_MANUAL1 in datamanual */
|
||||
mmc2_iodelay_hs200_conf: mmc2_iodelay_hs200_conf {
|
||||
pinctrl-pin-array = <
|
||||
0x190 A_DELAY_PS(384) G_DELAY_PS(0) /* CFG_GPMC_A19_OEN */
|
||||
0x194 A_DELAY_PS(0) G_DELAY_PS(174) /* CFG_GPMC_A19_OUT */
|
||||
0x1a8 A_DELAY_PS(410) G_DELAY_PS(0) /* CFG_GPMC_A20_OEN */
|
||||
0x1ac A_DELAY_PS(85) G_DELAY_PS(0) /* CFG_GPMC_A20_OUT */
|
||||
0x1b4 A_DELAY_PS(468) G_DELAY_PS(0) /* CFG_GPMC_A21_OEN */
|
||||
0x1b8 A_DELAY_PS(139) G_DELAY_PS(0) /* CFG_GPMC_A21_OUT */
|
||||
0x1c0 A_DELAY_PS(676) G_DELAY_PS(0) /* CFG_GPMC_A22_OEN */
|
||||
0x1c4 A_DELAY_PS(69) G_DELAY_PS(0) /* CFG_GPMC_A22_OUT */
|
||||
0x1d0 A_DELAY_PS(1062) G_DELAY_PS(154) /* CFG_GPMC_A23_OUT */
|
||||
0x1d8 A_DELAY_PS(640) G_DELAY_PS(0) /* CFG_GPMC_A24_OEN */
|
||||
0x1dc A_DELAY_PS(0) G_DELAY_PS(0) /* CFG_GPMC_A24_OUT */
|
||||
0x1e4 A_DELAY_PS(356) G_DELAY_PS(0) /* CFG_GPMC_A25_OEN */
|
||||
0x1e8 A_DELAY_PS(0) G_DELAY_PS(0) /* CFG_GPMC_A25_OUT */
|
||||
0x1f0 A_DELAY_PS(579) G_DELAY_PS(0) /* CFG_GPMC_A26_OEN */
|
||||
0x1f4 A_DELAY_PS(0) G_DELAY_PS(0) /* CFG_GPMC_A26_OUT */
|
||||
0x1fc A_DELAY_PS(435) G_DELAY_PS(0) /* CFG_GPMC_A27_OEN */
|
||||
0x200 A_DELAY_PS(36) G_DELAY_PS(0) /* CFG_GPMC_A27_OUT */
|
||||
0x364 A_DELAY_PS(759) G_DELAY_PS(0) /* CFG_GPMC_CS1_OEN */
|
||||
0x368 A_DELAY_PS(72) G_DELAY_PS(0) /* CFG_GPMC_CS1_OUT */
|
||||
0x190 A_DELAY_PS(384) G_DELAY_PS(0) /* CFG_GPMC_A19_OEN */
|
||||
0x194 A_DELAY_PS(350) G_DELAY_PS(174) /* CFG_GPMC_A19_OUT */
|
||||
0x1a8 A_DELAY_PS(410) G_DELAY_PS(0) /* CFG_GPMC_A20_OEN */
|
||||
0x1ac A_DELAY_PS(335) G_DELAY_PS(0) /* CFG_GPMC_A20_OUT */
|
||||
0x1b4 A_DELAY_PS(468) G_DELAY_PS(0) /* CFG_GPMC_A21_OEN */
|
||||
0x1b8 A_DELAY_PS(339) G_DELAY_PS(0) /* CFG_GPMC_A21_OUT */
|
||||
0x1c0 A_DELAY_PS(676) G_DELAY_PS(0) /* CFG_GPMC_A22_OEN */
|
||||
0x1c4 A_DELAY_PS(219) G_DELAY_PS(0) /* CFG_GPMC_A22_OUT */
|
||||
0x1d0 A_DELAY_PS(1062) G_DELAY_PS(154) /* CFG_GPMC_A23_OUT */
|
||||
0x1d8 A_DELAY_PS(640) G_DELAY_PS(0) /* CFG_GPMC_A24_OEN */
|
||||
0x1dc A_DELAY_PS(150) G_DELAY_PS(0) /* CFG_GPMC_A24_OUT */
|
||||
0x1e4 A_DELAY_PS(356) G_DELAY_PS(0) /* CFG_GPMC_A25_OEN */
|
||||
0x1e8 A_DELAY_PS(150) G_DELAY_PS(0) /* CFG_GPMC_A25_OUT */
|
||||
0x1f0 A_DELAY_PS(579) G_DELAY_PS(0) /* CFG_GPMC_A26_OEN */
|
||||
0x1f4 A_DELAY_PS(200) G_DELAY_PS(0) /* CFG_GPMC_A26_OUT */
|
||||
0x1fc A_DELAY_PS(435) G_DELAY_PS(0) /* CFG_GPMC_A27_OEN */
|
||||
0x200 A_DELAY_PS(236) G_DELAY_PS(0) /* CFG_GPMC_A27_OUT */
|
||||
0x364 A_DELAY_PS(759) G_DELAY_PS(0) /* CFG_GPMC_CS1_OEN */
|
||||
0x368 A_DELAY_PS(372) G_DELAY_PS(0) /* CFG_GPMC_CS1_OUT */
|
||||
>;
|
||||
};
|
||||
|
||||
|
|
|
@ -81,3 +81,11 @@ mcan_clk: mcan_clk@3fc {
|
|||
reg = <0x3fc>;
|
||||
};
|
||||
};
|
||||
|
||||
&rtctarget {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&usb4_tm {
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -1371,7 +1371,6 @@ segment@0 { /* 0x48000000 */
|
|||
|
||||
target-module@20000 { /* 0x48020000, ap 3 06.0 */
|
||||
compatible = "ti,sysc-omap2", "ti,sysc";
|
||||
ti,hwmods = "uart3";
|
||||
reg = <0x20050 0x4>,
|
||||
<0x20054 0x4>,
|
||||
<0x20058 0x4>;
|
||||
|
@ -1728,7 +1727,6 @@ i2c3: i2c@0 {
|
|||
|
||||
target-module@6a000 { /* 0x4806a000, ap 26 18.0 */
|
||||
compatible = "ti,sysc-omap2", "ti,sysc";
|
||||
ti,hwmods = "uart1";
|
||||
reg = <0x6a050 0x4>,
|
||||
<0x6a054 0x4>,
|
||||
<0x6a058 0x4>;
|
||||
|
@ -1758,7 +1756,6 @@ uart1: serial@0 {
|
|||
|
||||
target-module@6c000 { /* 0x4806c000, ap 28 20.0 */
|
||||
compatible = "ti,sysc-omap2", "ti,sysc";
|
||||
ti,hwmods = "uart2";
|
||||
reg = <0x6c050 0x4>,
|
||||
<0x6c054 0x4>,
|
||||
<0x6c058 0x4>;
|
||||
|
@ -1788,7 +1785,6 @@ uart2: serial@0 {
|
|||
|
||||
target-module@6e000 { /* 0x4806e000, ap 30 1c.1 */
|
||||
compatible = "ti,sysc-omap2", "ti,sysc";
|
||||
ti,hwmods = "uart4";
|
||||
reg = <0x6e050 0x4>,
|
||||
<0x6e054 0x4>,
|
||||
<0x6e058 0x4>;
|
||||
|
@ -2107,7 +2103,6 @@ mcspi2: spi@0 {
|
|||
|
||||
target-module@9c000 { /* 0x4809c000, ap 53 36.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "mmc1";
|
||||
reg = <0x9c000 0x4>,
|
||||
<0x9c010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
|
@ -2175,7 +2170,6 @@ target-module@a8000 { /* 0x480a8000, ap 61 3e.0 */
|
|||
|
||||
target-module@ad000 { /* 0x480ad000, ap 63 50.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "mmc3";
|
||||
reg = <0xad000 0x4>,
|
||||
<0xad010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
|
@ -2241,7 +2235,6 @@ hdqw1w: 1w@0 {
|
|||
|
||||
target-module@b4000 { /* 0x480b4000, ap 67 46.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "mmc2";
|
||||
reg = <0xb4000 0x4>,
|
||||
<0xb4010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
|
@ -2336,7 +2329,6 @@ mcspi4: spi@0 {
|
|||
|
||||
target-module@d1000 { /* 0x480d1000, ap 73 44.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "mmc4";
|
||||
reg = <0xd1000 0x4>,
|
||||
<0xd1010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
|
@ -2369,7 +2361,6 @@ mmc4: mmc@0 {
|
|||
|
||||
target-module@d5000 { /* 0x480d5000, ap 75 4e.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "mmc5";
|
||||
reg = <0xd5000 0x4>,
|
||||
<0xd5010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
|
|
|
@ -3445,6 +3445,7 @@ static int omap_hwmod_check_module(struct device *dev,
|
|||
* @dev: struct device
|
||||
* @oh: module
|
||||
* @sysc_fields: sysc register bits
|
||||
* @clockdomain: clockdomain
|
||||
* @rev_offs: revision register offset
|
||||
* @sysc_offs: sysconfig register offset
|
||||
* @syss_offs: sysstatus register offset
|
||||
|
@ -3456,6 +3457,7 @@ static int omap_hwmod_check_module(struct device *dev,
|
|||
static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
|
||||
const struct ti_sysc_module_data *data,
|
||||
struct sysc_regbits *sysc_fields,
|
||||
struct clockdomain *clkdm,
|
||||
s32 rev_offs, s32 sysc_offs,
|
||||
s32 syss_offs, u32 sysc_flags,
|
||||
u32 idlemodes)
|
||||
|
@ -3463,8 +3465,6 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
|
|||
struct omap_hwmod_class_sysconfig *sysc;
|
||||
struct omap_hwmod_class *class = NULL;
|
||||
struct omap_hwmod_ocp_if *oi = NULL;
|
||||
struct clockdomain *clkdm = NULL;
|
||||
struct clk *clk = NULL;
|
||||
void __iomem *regs = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -3511,36 +3511,6 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
|
|||
oi->user = OCP_USER_MPU | OCP_USER_SDMA;
|
||||
}
|
||||
|
||||
if (!oh->_clk) {
|
||||
struct clk_hw_omap *hwclk;
|
||||
|
||||
clk = of_clk_get_by_name(dev->of_node, "fck");
|
||||
if (!IS_ERR(clk))
|
||||
clk_prepare(clk);
|
||||
else
|
||||
clk = NULL;
|
||||
|
||||
/*
|
||||
* Populate clockdomain based on dts clock. It is needed for
|
||||
* clkdm_deny_idle() and clkdm_allow_idle() until we have have
|
||||
* interconnect driver and reset driver capable of blocking
|
||||
* clockdomain idle during reset, enable and idle.
|
||||
*/
|
||||
if (clk) {
|
||||
hwclk = to_clk_hw_omap(__clk_get_hw(clk));
|
||||
if (hwclk && hwclk->clkdm_name)
|
||||
clkdm = clkdm_lookup(hwclk->clkdm_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that we assume interconnect driver manages the clocks
|
||||
* and do not need to populate oh->_clk for dynamically
|
||||
* allocated modules.
|
||||
*/
|
||||
clk_unprepare(clk);
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&oh->_lock, flags);
|
||||
if (regs)
|
||||
oh->_mpu_rt_va = regs;
|
||||
|
@ -3626,7 +3596,7 @@ int omap_hwmod_init_module(struct device *dev,
|
|||
u32 sysc_flags, idlemodes;
|
||||
int error;
|
||||
|
||||
if (!dev || !data)
|
||||
if (!dev || !data || !data->name || !cookie)
|
||||
return -EINVAL;
|
||||
|
||||
oh = _lookup(data->name);
|
||||
|
@ -3697,7 +3667,8 @@ int omap_hwmod_init_module(struct device *dev,
|
|||
return error;
|
||||
|
||||
return omap_hwmod_allocate_module(dev, oh, data, sysc_fields,
|
||||
rev_offs, sysc_offs, syss_offs,
|
||||
cookie->clkdm, rev_offs,
|
||||
sysc_offs, syss_offs,
|
||||
sysc_flags, idlemodes);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/platform_data/wkup_m3.h>
|
||||
#include <linux/platform_data/asoc-ti-mcbsp.h>
|
||||
|
||||
#include "clockdomain.h"
|
||||
#include "common.h"
|
||||
#include "common-board-devices.h"
|
||||
#include "control.h"
|
||||
|
@ -463,6 +464,62 @@ static void __init dra7x_evm_mmc_quirk(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static struct clockdomain *ti_sysc_find_one_clockdomain(struct clk *clk)
|
||||
{
|
||||
struct clockdomain *clkdm = NULL;
|
||||
struct clk_hw_omap *hwclk;
|
||||
|
||||
hwclk = to_clk_hw_omap(__clk_get_hw(clk));
|
||||
if (hwclk && hwclk->clkdm_name)
|
||||
clkdm = clkdm_lookup(hwclk->clkdm_name);
|
||||
|
||||
return clkdm;
|
||||
}
|
||||
|
||||
/**
|
||||
* ti_sysc_clkdm_init - find clockdomain based on clock
|
||||
* @fck: device functional clock
|
||||
* @ick: device interface clock
|
||||
* @dev: struct device
|
||||
*
|
||||
* Populate clockdomain based on clock. It is needed for
|
||||
* clkdm_deny_idle() and clkdm_allow_idle() for blocking clockdomain
|
||||
* clockdomain idle during reset, enable and idle.
|
||||
*
|
||||
* Note that we assume interconnect driver manages the clocks
|
||||
* and do not need to populate oh->_clk for dynamically
|
||||
* allocated modules.
|
||||
*/
|
||||
static int ti_sysc_clkdm_init(struct device *dev,
|
||||
struct clk *fck, struct clk *ick,
|
||||
struct ti_sysc_cookie *cookie)
|
||||
{
|
||||
if (fck)
|
||||
cookie->clkdm = ti_sysc_find_one_clockdomain(fck);
|
||||
if (cookie->clkdm)
|
||||
return 0;
|
||||
if (ick)
|
||||
cookie->clkdm = ti_sysc_find_one_clockdomain(ick);
|
||||
if (cookie->clkdm)
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void ti_sysc_clkdm_deny_idle(struct device *dev,
|
||||
const struct ti_sysc_cookie *cookie)
|
||||
{
|
||||
if (cookie->clkdm)
|
||||
clkdm_deny_idle(cookie->clkdm);
|
||||
}
|
||||
|
||||
static void ti_sysc_clkdm_allow_idle(struct device *dev,
|
||||
const struct ti_sysc_cookie *cookie)
|
||||
{
|
||||
if (cookie->clkdm)
|
||||
clkdm_allow_idle(cookie->clkdm);
|
||||
}
|
||||
|
||||
static int ti_sysc_enable_module(struct device *dev,
|
||||
const struct ti_sysc_cookie *cookie)
|
||||
{
|
||||
|
@ -494,6 +551,9 @@ static struct of_dev_auxdata omap_auxdata_lookup[];
|
|||
|
||||
static struct ti_sysc_platform_data ti_sysc_pdata = {
|
||||
.auxdata = omap_auxdata_lookup,
|
||||
.init_clockdomain = ti_sysc_clkdm_init,
|
||||
.clkdm_deny_idle = ti_sysc_clkdm_deny_idle,
|
||||
.clkdm_allow_idle = ti_sysc_clkdm_allow_idle,
|
||||
.init_module = omap_hwmod_init_module,
|
||||
.enable_module = ti_sysc_enable_module,
|
||||
.idle_module = ti_sysc_idle_module,
|
||||
|
|
|
@ -89,9 +89,10 @@ struct sysc {
|
|||
struct ti_sysc_cookie cookie;
|
||||
const char *name;
|
||||
u32 revision;
|
||||
bool enabled;
|
||||
bool needs_resume;
|
||||
bool child_needs_resume;
|
||||
unsigned int enabled:1;
|
||||
unsigned int needs_resume:1;
|
||||
unsigned int child_needs_resume:1;
|
||||
unsigned int disable_on_idle:1;
|
||||
struct delayed_work idle_work;
|
||||
};
|
||||
|
||||
|
@ -100,6 +101,20 @@ static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
|
|||
|
||||
static void sysc_write(struct sysc *ddata, int offset, u32 value)
|
||||
{
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
|
||||
writew_relaxed(value & 0xffff, ddata->module_va + offset);
|
||||
|
||||
/* Only i2c revision has LO and HI register with stride of 4 */
|
||||
if (ddata->offsets[SYSC_REVISION] >= 0 &&
|
||||
offset == ddata->offsets[SYSC_REVISION]) {
|
||||
u16 hi = value >> 16;
|
||||
|
||||
writew_relaxed(hi, ddata->module_va + offset + 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
writel_relaxed(value, ddata->module_va + offset);
|
||||
}
|
||||
|
||||
|
@ -109,7 +124,14 @@ static u32 sysc_read(struct sysc *ddata, int offset)
|
|||
u32 val;
|
||||
|
||||
val = readw_relaxed(ddata->module_va + offset);
|
||||
val |= (readw_relaxed(ddata->module_va + offset + 4) << 16);
|
||||
|
||||
/* Only i2c revision has LO and HI register with stride of 4 */
|
||||
if (ddata->offsets[SYSC_REVISION] >= 0 &&
|
||||
offset == ddata->offsets[SYSC_REVISION]) {
|
||||
u16 tmp = readw_relaxed(ddata->module_va + offset + 4);
|
||||
|
||||
val |= tmp << 16;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -132,6 +154,26 @@ static u32 sysc_read_revision(struct sysc *ddata)
|
|||
return sysc_read(ddata, offset);
|
||||
}
|
||||
|
||||
static u32 sysc_read_sysconfig(struct sysc *ddata)
|
||||
{
|
||||
int offset = ddata->offsets[SYSC_SYSCONFIG];
|
||||
|
||||
if (offset < 0)
|
||||
return 0;
|
||||
|
||||
return sysc_read(ddata, offset);
|
||||
}
|
||||
|
||||
static u32 sysc_read_sysstatus(struct sysc *ddata)
|
||||
{
|
||||
int offset = ddata->offsets[SYSC_SYSSTATUS];
|
||||
|
||||
if (offset < 0)
|
||||
return 0;
|
||||
|
||||
return sysc_read(ddata, offset);
|
||||
}
|
||||
|
||||
static int sysc_add_named_clock_from_child(struct sysc *ddata,
|
||||
const char *name,
|
||||
const char *optfck_name)
|
||||
|
@ -422,6 +464,30 @@ static void sysc_disable_opt_clocks(struct sysc *ddata)
|
|||
}
|
||||
}
|
||||
|
||||
static void sysc_clkdm_deny_idle(struct sysc *ddata)
|
||||
{
|
||||
struct ti_sysc_platform_data *pdata;
|
||||
|
||||
if (ddata->legacy_mode)
|
||||
return;
|
||||
|
||||
pdata = dev_get_platdata(ddata->dev);
|
||||
if (pdata && pdata->clkdm_deny_idle)
|
||||
pdata->clkdm_deny_idle(ddata->dev, &ddata->cookie);
|
||||
}
|
||||
|
||||
static void sysc_clkdm_allow_idle(struct sysc *ddata)
|
||||
{
|
||||
struct ti_sysc_platform_data *pdata;
|
||||
|
||||
if (ddata->legacy_mode)
|
||||
return;
|
||||
|
||||
pdata = dev_get_platdata(ddata->dev);
|
||||
if (pdata && pdata->clkdm_allow_idle)
|
||||
pdata->clkdm_allow_idle(ddata->dev, &ddata->cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysc_init_resets - init rstctrl reset line if configured
|
||||
* @ddata: device driver data
|
||||
|
@ -431,7 +497,7 @@ static void sysc_disable_opt_clocks(struct sysc *ddata)
|
|||
static int sysc_init_resets(struct sysc *ddata)
|
||||
{
|
||||
ddata->rsts =
|
||||
devm_reset_control_array_get_optional_exclusive(ddata->dev);
|
||||
devm_reset_control_get_optional(ddata->dev, "rstctrl");
|
||||
if (IS_ERR(ddata->rsts))
|
||||
return PTR_ERR(ddata->rsts);
|
||||
|
||||
|
@ -660,12 +726,6 @@ static int sysc_check_registers(struct sysc *ddata)
|
|||
nr_regs++;
|
||||
}
|
||||
|
||||
if (nr_regs < 1) {
|
||||
dev_err(ddata->dev, "missing registers\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (nr_matches > nr_regs) {
|
||||
dev_err(ddata->dev, "overlapping registers: (%i/%i)",
|
||||
nr_regs, nr_matches);
|
||||
|
@ -691,12 +751,18 @@ static int sysc_ioremap(struct sysc *ddata)
|
|||
{
|
||||
int size;
|
||||
|
||||
size = max3(ddata->offsets[SYSC_REVISION],
|
||||
ddata->offsets[SYSC_SYSCONFIG],
|
||||
ddata->offsets[SYSC_SYSSTATUS]);
|
||||
if (ddata->offsets[SYSC_REVISION] < 0 &&
|
||||
ddata->offsets[SYSC_SYSCONFIG] < 0 &&
|
||||
ddata->offsets[SYSC_SYSSTATUS] < 0) {
|
||||
size = ddata->module_size;
|
||||
} else {
|
||||
size = max3(ddata->offsets[SYSC_REVISION],
|
||||
ddata->offsets[SYSC_SYSCONFIG],
|
||||
ddata->offsets[SYSC_SYSSTATUS]);
|
||||
|
||||
if (size < 0 || (size + sizeof(u32)) > ddata->module_size)
|
||||
return -EINVAL;
|
||||
if ((size + sizeof(u32)) > ddata->module_size)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ddata->module_va = devm_ioremap(ddata->dev,
|
||||
ddata->module_pa,
|
||||
|
@ -794,7 +860,9 @@ static void sysc_show_registers(struct sysc *ddata)
|
|||
}
|
||||
|
||||
#define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1)
|
||||
#define SYSC_CLOCACT_ICK 2
|
||||
|
||||
/* Caller needs to manage sysc_clkdm_deny_idle() and sysc_clkdm_allow_idle() */
|
||||
static int sysc_enable_module(struct device *dev)
|
||||
{
|
||||
struct sysc *ddata;
|
||||
|
@ -805,23 +873,34 @@ static int sysc_enable_module(struct device *dev)
|
|||
if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* TODO: Need to prevent clockdomain autoidle?
|
||||
* See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c
|
||||
*/
|
||||
|
||||
regbits = ddata->cap->regbits;
|
||||
reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
|
||||
|
||||
/* Set CLOCKACTIVITY, we only use it for ick */
|
||||
if (regbits->clkact_shift >= 0 &&
|
||||
(ddata->cfg.quirks & SYSC_QUIRK_USE_CLOCKACT ||
|
||||
ddata->cfg.sysc_val & BIT(regbits->clkact_shift)))
|
||||
reg |= SYSC_CLOCACT_ICK << regbits->clkact_shift;
|
||||
|
||||
/* Set SIDLE mode */
|
||||
idlemodes = ddata->cfg.sidlemodes;
|
||||
if (!idlemodes || regbits->sidle_shift < 0)
|
||||
goto set_midle;
|
||||
|
||||
best_mode = fls(ddata->cfg.sidlemodes) - 1;
|
||||
if (best_mode > SYSC_IDLE_MASK) {
|
||||
dev_err(dev, "%s: invalid sidlemode\n", __func__);
|
||||
return -EINVAL;
|
||||
if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_SIDLE |
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT)) {
|
||||
best_mode = SYSC_IDLE_NO;
|
||||
} else {
|
||||
best_mode = fls(ddata->cfg.sidlemodes) - 1;
|
||||
if (best_mode > SYSC_IDLE_MASK) {
|
||||
dev_err(dev, "%s: invalid sidlemode\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set WAKEUP */
|
||||
if (regbits->enwkup_shift >= 0 &&
|
||||
ddata->cfg.sysc_val & BIT(regbits->enwkup_shift))
|
||||
reg |= BIT(regbits->enwkup_shift);
|
||||
}
|
||||
|
||||
reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
|
||||
|
@ -832,7 +911,7 @@ static int sysc_enable_module(struct device *dev)
|
|||
/* Set MIDLE mode */
|
||||
idlemodes = ddata->cfg.midlemodes;
|
||||
if (!idlemodes || regbits->midle_shift < 0)
|
||||
return 0;
|
||||
goto set_autoidle;
|
||||
|
||||
best_mode = fls(ddata->cfg.midlemodes) - 1;
|
||||
if (best_mode > SYSC_IDLE_MASK) {
|
||||
|
@ -844,6 +923,14 @@ static int sysc_enable_module(struct device *dev)
|
|||
reg |= best_mode << regbits->midle_shift;
|
||||
sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
|
||||
|
||||
set_autoidle:
|
||||
/* Autoidle bit must enabled separately if available */
|
||||
if (regbits->autoidle_shift >= 0 &&
|
||||
ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) {
|
||||
reg |= 1 << regbits->autoidle_shift;
|
||||
sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -861,6 +948,7 @@ static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Caller needs to manage sysc_clkdm_deny_idle() and sysc_clkdm_allow_idle() */
|
||||
static int sysc_disable_module(struct device *dev)
|
||||
{
|
||||
struct sysc *ddata;
|
||||
|
@ -872,11 +960,6 @@ static int sysc_disable_module(struct device *dev)
|
|||
if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* TODO: Need to prevent clockdomain autoidle?
|
||||
* See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c
|
||||
*/
|
||||
|
||||
regbits = ddata->cap->regbits;
|
||||
reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
|
||||
|
||||
|
@ -901,14 +984,21 @@ static int sysc_disable_module(struct device *dev)
|
|||
if (!idlemodes || regbits->sidle_shift < 0)
|
||||
return 0;
|
||||
|
||||
ret = sysc_best_idle_mode(idlemodes, &best_mode);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: invalid sidlemode\n", __func__);
|
||||
return ret;
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_SIDLE) {
|
||||
best_mode = SYSC_IDLE_FORCE;
|
||||
} else {
|
||||
ret = sysc_best_idle_mode(idlemodes, &best_mode);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: invalid sidlemode\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
|
||||
reg |= best_mode << regbits->sidle_shift;
|
||||
if (regbits->autoidle_shift >= 0 &&
|
||||
ddata->cfg.sysc_val & BIT(regbits->autoidle_shift))
|
||||
reg |= 1 << regbits->autoidle_shift;
|
||||
sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
|
||||
|
||||
return 0;
|
||||
|
@ -932,6 +1022,9 @@ static int __maybe_unused sysc_runtime_suspend_legacy(struct device *dev,
|
|||
dev_err(dev, "%s: could not idle: %i\n",
|
||||
__func__, error);
|
||||
|
||||
if (ddata->disable_on_idle)
|
||||
reset_control_assert(ddata->rsts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -941,6 +1034,9 @@ static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev,
|
|||
struct ti_sysc_platform_data *pdata;
|
||||
int error;
|
||||
|
||||
if (ddata->disable_on_idle)
|
||||
reset_control_deassert(ddata->rsts);
|
||||
|
||||
pdata = dev_get_platdata(ddata->dev);
|
||||
if (!pdata)
|
||||
return 0;
|
||||
|
@ -966,14 +1062,16 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
|
|||
if (!ddata->enabled)
|
||||
return 0;
|
||||
|
||||
sysc_clkdm_deny_idle(ddata);
|
||||
|
||||
if (ddata->legacy_mode) {
|
||||
error = sysc_runtime_suspend_legacy(dev, ddata);
|
||||
if (error)
|
||||
return error;
|
||||
goto err_allow_idle;
|
||||
} else {
|
||||
error = sysc_disable_module(dev);
|
||||
if (error)
|
||||
return error;
|
||||
goto err_allow_idle;
|
||||
}
|
||||
|
||||
sysc_disable_main_clocks(ddata);
|
||||
|
@ -983,6 +1081,12 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
|
|||
|
||||
ddata->enabled = false;
|
||||
|
||||
err_allow_idle:
|
||||
sysc_clkdm_allow_idle(ddata);
|
||||
|
||||
if (ddata->disable_on_idle)
|
||||
reset_control_assert(ddata->rsts);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -996,10 +1100,15 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
|
|||
if (ddata->enabled)
|
||||
return 0;
|
||||
|
||||
if (ddata->disable_on_idle)
|
||||
reset_control_deassert(ddata->rsts);
|
||||
|
||||
sysc_clkdm_deny_idle(ddata);
|
||||
|
||||
if (sysc_opt_clks_needed(ddata)) {
|
||||
error = sysc_enable_opt_clocks(ddata);
|
||||
if (error)
|
||||
return error;
|
||||
goto err_allow_idle;
|
||||
}
|
||||
|
||||
error = sysc_enable_main_clocks(ddata);
|
||||
|
@ -1018,6 +1127,8 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
|
|||
|
||||
ddata->enabled = true;
|
||||
|
||||
sysc_clkdm_allow_idle(ddata);
|
||||
|
||||
return 0;
|
||||
|
||||
err_main_clocks:
|
||||
|
@ -1025,6 +1136,8 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
|
|||
err_opt_clocks:
|
||||
if (sysc_opt_clks_needed(ddata))
|
||||
sysc_disable_opt_clocks(ddata);
|
||||
err_allow_idle:
|
||||
sysc_clkdm_allow_idle(ddata);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -1106,8 +1219,10 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
|
|||
0),
|
||||
SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
|
||||
0),
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||
/* Uarts on omap4 and later */
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
||||
|
@ -1128,7 +1243,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
|
|||
SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902,
|
||||
0xffff00f0, 0),
|
||||
SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0),
|
||||
SYSC_QUIRK("dcan", 0, 0, -1, -1, 0x00001401, 0xffffffff, 0),
|
||||
SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),
|
||||
SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
|
||||
SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
|
||||
|
@ -1246,6 +1360,33 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
|
|||
}
|
||||
}
|
||||
|
||||
static int sysc_clockdomain_init(struct sysc *ddata)
|
||||
{
|
||||
struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
|
||||
struct clk *fck = NULL, *ick = NULL;
|
||||
int error;
|
||||
|
||||
if (!pdata || !pdata->init_clockdomain)
|
||||
return 0;
|
||||
|
||||
switch (ddata->nr_clocks) {
|
||||
case 2:
|
||||
ick = ddata->clocks[SYSC_ICK];
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
fck = ddata->clocks[SYSC_FCK];
|
||||
break;
|
||||
case 0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = pdata->init_clockdomain(ddata->dev, fck, ick, &ddata->cookie);
|
||||
if (!error || error == -ENODEV)
|
||||
return 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that pdata->init_module() typically does a reset first. After
|
||||
* pdata->init_module() is done, PM runtime can be used for the interconnect
|
||||
|
@ -1256,7 +1397,7 @@ static int sysc_legacy_init(struct sysc *ddata)
|
|||
struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
|
||||
int error;
|
||||
|
||||
if (!ddata->legacy_mode || !pdata || !pdata->init_module)
|
||||
if (!pdata || !pdata->init_module)
|
||||
return 0;
|
||||
|
||||
error = pdata->init_module(ddata->dev, ddata->mdata, &ddata->cookie);
|
||||
|
@ -1281,7 +1422,7 @@ static int sysc_legacy_init(struct sysc *ddata)
|
|||
*/
|
||||
static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset)
|
||||
{
|
||||
int error;
|
||||
int error, val;
|
||||
|
||||
if (!ddata->rsts)
|
||||
return 0;
|
||||
|
@ -1292,37 +1433,59 @@ static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset)
|
|||
return error;
|
||||
}
|
||||
|
||||
return reset_control_deassert(ddata->rsts);
|
||||
error = reset_control_deassert(ddata->rsts);
|
||||
if (error == -EEXIST)
|
||||
return 0;
|
||||
|
||||
error = readx_poll_timeout(reset_control_status, ddata->rsts, val,
|
||||
val == 0, 100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the caller must ensure the interconnect target module is enabled
|
||||
* before calling reset. Otherwise reset will not complete.
|
||||
*/
|
||||
static int sysc_reset(struct sysc *ddata)
|
||||
{
|
||||
int offset = ddata->offsets[SYSC_SYSCONFIG];
|
||||
int val;
|
||||
int sysc_offset, syss_offset, sysc_val, rstval, quirks, error = 0;
|
||||
u32 sysc_mask, syss_done;
|
||||
|
||||
if (ddata->legacy_mode || offset < 0 ||
|
||||
sysc_offset = ddata->offsets[SYSC_SYSCONFIG];
|
||||
syss_offset = ddata->offsets[SYSC_SYSSTATUS];
|
||||
quirks = ddata->cfg.quirks;
|
||||
|
||||
if (ddata->legacy_mode || sysc_offset < 0 ||
|
||||
ddata->cap->regbits->srst_shift < 0 ||
|
||||
ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Currently only support reset status in sysstatus.
|
||||
* Warn and return error in all other cases
|
||||
*/
|
||||
if (!ddata->cfg.syss_mask) {
|
||||
dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
sysc_mask = BIT(ddata->cap->regbits->srst_shift);
|
||||
|
||||
val = sysc_read(ddata, offset);
|
||||
val |= (0x1 << ddata->cap->regbits->srst_shift);
|
||||
sysc_write(ddata, offset, val);
|
||||
if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED)
|
||||
syss_done = 0;
|
||||
else
|
||||
syss_done = ddata->cfg.syss_mask;
|
||||
|
||||
sysc_val = sysc_read_sysconfig(ddata);
|
||||
sysc_val |= sysc_mask;
|
||||
sysc_write(ddata, sysc_offset, sysc_val);
|
||||
|
||||
/* Poll on reset status */
|
||||
offset = ddata->offsets[SYSC_SYSSTATUS];
|
||||
if (syss_offset >= 0) {
|
||||
error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,
|
||||
(rstval & ddata->cfg.syss_mask) ==
|
||||
syss_done,
|
||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
|
||||
return readl_poll_timeout(ddata->module_va + offset, val,
|
||||
(val & ddata->cfg.syss_mask) == 0x0,
|
||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
} else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
|
||||
error = readx_poll_timeout(sysc_read_sysconfig, ddata, rstval,
|
||||
!(rstval & sysc_mask),
|
||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1335,12 +1498,8 @@ static int sysc_init_module(struct sysc *ddata)
|
|||
{
|
||||
int error = 0;
|
||||
bool manage_clocks = true;
|
||||
bool reset = true;
|
||||
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
|
||||
reset = false;
|
||||
|
||||
error = sysc_rstctrl_reset_deassert(ddata, reset);
|
||||
error = sysc_rstctrl_reset_deassert(ddata, false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -1348,7 +1507,13 @@ static int sysc_init_module(struct sysc *ddata)
|
|||
(SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT))
|
||||
manage_clocks = false;
|
||||
|
||||
error = sysc_clockdomain_init(ddata);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (manage_clocks) {
|
||||
sysc_clkdm_deny_idle(ddata);
|
||||
|
||||
error = sysc_enable_opt_clocks(ddata);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -1358,23 +1523,42 @@ static int sysc_init_module(struct sysc *ddata)
|
|||
goto err_opt_clocks;
|
||||
}
|
||||
|
||||
if (!(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)) {
|
||||
error = sysc_rstctrl_reset_deassert(ddata, true);
|
||||
if (error)
|
||||
goto err_main_clocks;
|
||||
}
|
||||
|
||||
ddata->revision = sysc_read_revision(ddata);
|
||||
sysc_init_revision_quirks(ddata);
|
||||
|
||||
error = sysc_legacy_init(ddata);
|
||||
if (error)
|
||||
goto err_main_clocks;
|
||||
if (ddata->legacy_mode) {
|
||||
error = sysc_legacy_init(ddata);
|
||||
if (error)
|
||||
goto err_main_clocks;
|
||||
}
|
||||
|
||||
if (!ddata->legacy_mode && manage_clocks) {
|
||||
error = sysc_enable_module(ddata->dev);
|
||||
if (error)
|
||||
goto err_main_clocks;
|
||||
}
|
||||
|
||||
error = sysc_reset(ddata);
|
||||
if (error)
|
||||
dev_err(ddata->dev, "Reset failed with %d\n", error);
|
||||
|
||||
if (!ddata->legacy_mode && manage_clocks)
|
||||
sysc_disable_module(ddata->dev);
|
||||
|
||||
err_main_clocks:
|
||||
if (manage_clocks)
|
||||
sysc_disable_main_clocks(ddata);
|
||||
err_opt_clocks:
|
||||
if (manage_clocks)
|
||||
if (manage_clocks) {
|
||||
sysc_disable_opt_clocks(ddata);
|
||||
sysc_clkdm_allow_idle(ddata);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -1664,9 +1848,6 @@ static struct dev_pm_domain sysc_child_pm_domain = {
|
|||
*/
|
||||
static void sysc_legacy_idle_quirk(struct sysc *ddata, struct device *child)
|
||||
{
|
||||
if (!ddata->legacy_mode)
|
||||
return;
|
||||
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
|
||||
dev_pm_domain_set(child, &sysc_child_pm_domain);
|
||||
}
|
||||
|
@ -2006,6 +2187,7 @@ static const struct sysc_capabilities sysc_dra7_mcan = {
|
|||
.type = TI_SYSC_DRA7_MCAN,
|
||||
.sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
|
||||
.regbits = &sysc_regbits_dra7_mcan,
|
||||
.mod_quirks = SYSS_QUIRK_RESETDONE_INVERTED,
|
||||
};
|
||||
|
||||
static int sysc_init_pdata(struct sysc *ddata)
|
||||
|
@ -2013,20 +2195,22 @@ static int sysc_init_pdata(struct sysc *ddata)
|
|||
struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
|
||||
struct ti_sysc_module_data *mdata;
|
||||
|
||||
if (!pdata || !ddata->legacy_mode)
|
||||
if (!pdata)
|
||||
return 0;
|
||||
|
||||
mdata = devm_kzalloc(ddata->dev, sizeof(*mdata), GFP_KERNEL);
|
||||
if (!mdata)
|
||||
return -ENOMEM;
|
||||
|
||||
mdata->name = ddata->legacy_mode;
|
||||
mdata->module_pa = ddata->module_pa;
|
||||
mdata->module_size = ddata->module_size;
|
||||
mdata->offsets = ddata->offsets;
|
||||
mdata->nr_offsets = SYSC_MAX_REGS;
|
||||
mdata->cap = ddata->cap;
|
||||
mdata->cfg = &ddata->cfg;
|
||||
if (ddata->legacy_mode) {
|
||||
mdata->name = ddata->legacy_mode;
|
||||
mdata->module_pa = ddata->module_pa;
|
||||
mdata->module_size = ddata->module_size;
|
||||
mdata->offsets = ddata->offsets;
|
||||
mdata->nr_offsets = SYSC_MAX_REGS;
|
||||
mdata->cap = ddata->cap;
|
||||
mdata->cfg = &ddata->cfg;
|
||||
}
|
||||
|
||||
ddata->mdata = mdata;
|
||||
|
||||
|
@ -2146,7 +2330,7 @@ static int sysc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (!of_get_available_child_count(ddata->dev->of_node))
|
||||
reset_control_assert(ddata->rsts);
|
||||
ddata->disable_on_idle = true;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ enum ti_sysc_module_type {
|
|||
|
||||
struct ti_sysc_cookie {
|
||||
void *data;
|
||||
void *clkdm;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -46,6 +47,7 @@ struct sysc_regbits {
|
|||
s8 emufree_shift;
|
||||
};
|
||||
|
||||
#define SYSS_QUIRK_RESETDONE_INVERTED BIT(14)
|
||||
#define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13)
|
||||
#define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12)
|
||||
#define SYSC_QUIRK_SWSUP_SIDLE BIT(11)
|
||||
|
@ -125,9 +127,16 @@ struct ti_sysc_module_data {
|
|||
};
|
||||
|
||||
struct device;
|
||||
struct clk;
|
||||
|
||||
struct ti_sysc_platform_data {
|
||||
struct of_dev_auxdata *auxdata;
|
||||
int (*init_clockdomain)(struct device *dev, struct clk *fck,
|
||||
struct clk *ick, struct ti_sysc_cookie *cookie);
|
||||
void (*clkdm_deny_idle)(struct device *dev,
|
||||
const struct ti_sysc_cookie *cookie);
|
||||
void (*clkdm_allow_idle)(struct device *dev,
|
||||
const struct ti_sysc_cookie *cookie);
|
||||
int (*init_module)(struct device *dev,
|
||||
const struct ti_sysc_module_data *data,
|
||||
struct ti_sysc_cookie *cookie);
|
||||
|
|
Loading…
Reference in New Issue