mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
Keystone SOC driver update for 4.19
- Add suspend/resume functionality to TI EMIF SRAM driver - Add wakeup M3 RTC self refresh support - Fix for the PM runtime ifdefs -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJbP9kjAAoJEHJsHOdBp5c/W+oQALeD0omSm7NKjF8iouQ2LwCt eoE4KOdZKL8yhZfkHfjHsJCGmYRlCVTHhz69pntAslJdDi/ny23zuf38PKnnz5Ht 39aCOPMbhLy0O3Vz8ZQ8vpGXlDwd9vNMc5Pgm41nrzcOMF/oNzs5s1LypiYogePA EwTRldIJeG3uwTwtqvFsj2HY9IeQHb72nQNr0sZqvURpC4ydU7ctwi69cFuVuY1Q O70QY9E4ZHm2NC+NNp7zt8gpwG97OGtn7d5m6ba+ExFln3vtn29/CtqYv4TSGBEd 99ZMe4+5+/Um5lPIm7tPuKv60GuV26uPGDfpEV3rbR8DgBC16z5IaIi7IxI+IHhO PZKCAfIiSU8/1d/uCcgjmosRdy3hrV2YC+PLi74frQzY/zijm2jVjY9yG8g6XUu/ 0cLipo1r0Kccw+UhsWLVTmKW2/RhRjvsmJdxgik4Ie5aHPoiS9gLSMMhtEnri3oe YzIisdQuaaZgsWzXo+CL1d7lOVFuFfoNwhOCHIs0GA7rDOJJ2qPC7zGTX+Fet+5j V+7oGoBFEC8ZSuOms9LKLKD8J7e/1SUb5X2iX73WSU0bFLEQAD33luciqPx9DvUo esZst+J3Ig9Co/AmeGhAKBgz3a1SAjqbsZJxdH496hMLQgUGT/KdvOX8ZG1jqPGl dE4CUXoTVwVZyVjT7tF3 =w8YK -----END PGP SIGNATURE----- Merge tag 'soc_drivers_for_4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone into next/drivers Keystone SOC driver update for 4.19 - Add suspend/resume functionality to TI EMIF SRAM driver - Add wakeup M3 RTC self refresh support - Fix for the PM runtime ifdefs * tag 'soc_drivers_for_4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone: soc: ti: wkup_m3_ipc: mark PM functions as __maybe_unused soc: ti: wkup_m3_ipc: Add wkup_m3_request_wake_src soc: ti: wkup_m3_ipc: Add rtc_only with ddr in self refresh mode support memory: ti-emif-sram: Add resume function to recopy sram code Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
872d6d96cd
3 changed files with 118 additions and 0 deletions
|
@ -249,6 +249,34 @@ static const struct of_device_id ti_emif_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, ti_emif_of_match);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ti_emif_resume(struct device *dev)
|
||||
{
|
||||
unsigned long tmp =
|
||||
__raw_readl((void *)emif_instance->ti_emif_sram_virt);
|
||||
|
||||
/*
|
||||
* Check to see if what we are copying is already present in the
|
||||
* first byte at the destination, only copy if it is not which
|
||||
* indicates we have lost context and sram no longer contains
|
||||
* the PM code
|
||||
*/
|
||||
if (tmp != ti_emif_sram)
|
||||
ti_emif_push_sram(dev, emif_instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ti_emif_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* The contents will be present in DDR hence no need to
|
||||
* explicitly save
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static int ti_emif_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
@ -308,12 +336,17 @@ static int ti_emif_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops ti_emif_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ti_emif_suspend, ti_emif_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver ti_emif_driver = {
|
||||
.probe = ti_emif_probe,
|
||||
.remove = ti_emif_remove,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = of_match_ptr(ti_emif_of_match),
|
||||
.pm = &ti_emif_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(ti_emif_driver);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#define M3_BASELINE_VERSION 0x191
|
||||
#define M3_STATUS_RESP_MASK (0xffff << 16)
|
||||
#define M3_FW_VERSION_MASK 0xffff
|
||||
#define M3_WAKE_SRC_MASK 0xff
|
||||
|
||||
#define M3_STATE_UNKNOWN 0
|
||||
#define M3_STATE_RESET 1
|
||||
|
@ -55,6 +56,23 @@
|
|||
|
||||
static struct wkup_m3_ipc *m3_ipc_state;
|
||||
|
||||
static const struct wkup_m3_wakeup_src wakeups[] = {
|
||||
{.irq_nr = 35, .src = "USB0_PHY"},
|
||||
{.irq_nr = 36, .src = "USB1_PHY"},
|
||||
{.irq_nr = 40, .src = "I2C0"},
|
||||
{.irq_nr = 41, .src = "RTC Timer"},
|
||||
{.irq_nr = 42, .src = "RTC Alarm"},
|
||||
{.irq_nr = 43, .src = "Timer0"},
|
||||
{.irq_nr = 44, .src = "Timer1"},
|
||||
{.irq_nr = 45, .src = "UART"},
|
||||
{.irq_nr = 46, .src = "GPIO0"},
|
||||
{.irq_nr = 48, .src = "MPU_WAKE"},
|
||||
{.irq_nr = 49, .src = "WDT0"},
|
||||
{.irq_nr = 50, .src = "WDT1"},
|
||||
{.irq_nr = 51, .src = "ADC_TSC"},
|
||||
{.irq_nr = 0, .src = "Unknown"},
|
||||
};
|
||||
|
||||
static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
|
||||
{
|
||||
writel(AM33XX_M3_TXEV_ACK,
|
||||
|
@ -329,12 +347,45 @@ static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3
|
||||
* @m3_ipc: Pointer to wkup_m3_ipc context
|
||||
*/
|
||||
static const char *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
|
||||
{
|
||||
unsigned int wakeup_src_idx;
|
||||
int j, val;
|
||||
|
||||
val = wkup_m3_ctrl_ipc_read(m3_ipc, 6);
|
||||
|
||||
wakeup_src_idx = val & M3_WAKE_SRC_MASK;
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(wakeups) - 1; j++) {
|
||||
if (wakeups[j].irq_nr == wakeup_src_idx)
|
||||
return wakeups[j].src;
|
||||
}
|
||||
return wakeups[j].src;
|
||||
}
|
||||
|
||||
/**
|
||||
* wkup_m3_set_rtc_only - Set the rtc_only flag
|
||||
* @wkup_m3_wakeup: struct wkup_m3_wakeup_src * gets assigned the
|
||||
* wakeup src value
|
||||
*/
|
||||
static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
|
||||
{
|
||||
if (m3_ipc_state)
|
||||
m3_ipc_state->is_rtc_only = true;
|
||||
}
|
||||
|
||||
static struct wkup_m3_ipc_ops ipc_ops = {
|
||||
.set_mem_type = wkup_m3_set_mem_type,
|
||||
.set_resume_address = wkup_m3_set_resume_address,
|
||||
.prepare_low_power = wkup_m3_prepare_low_power,
|
||||
.finish_low_power = wkup_m3_finish_low_power,
|
||||
.request_pm_status = wkup_m3_request_pm_status,
|
||||
.request_wake_src = wkup_m3_request_wake_src,
|
||||
.set_rtc_only = wkup_m3_set_rtc_only,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -484,6 +535,30 @@ static int wkup_m3_ipc_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused wkup_m3_ipc_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* Nothing needs to be done on suspend even with rtc_only flag set
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused wkup_m3_ipc_resume(struct device *dev)
|
||||
{
|
||||
if (m3_ipc_state->is_rtc_only) {
|
||||
rproc_shutdown(m3_ipc_state->rproc);
|
||||
rproc_boot(m3_ipc_state->rproc);
|
||||
}
|
||||
|
||||
m3_ipc_state->is_rtc_only = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops wkup_m3_ipc_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(wkup_m3_ipc_suspend, wkup_m3_ipc_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id wkup_m3_ipc_of_match[] = {
|
||||
{ .compatible = "ti,am3352-wkup-m3-ipc", },
|
||||
{ .compatible = "ti,am4372-wkup-m3-ipc", },
|
||||
|
@ -497,6 +572,7 @@ static struct platform_driver wkup_m3_ipc_driver = {
|
|||
.driver = {
|
||||
.name = "wkup_m3_ipc",
|
||||
.of_match_table = wkup_m3_ipc_of_match,
|
||||
.pm = &wkup_m3_ipc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -40,6 +40,12 @@ struct wkup_m3_ipc {
|
|||
struct mbox_chan *mbox;
|
||||
|
||||
struct wkup_m3_ipc_ops *ops;
|
||||
int is_rtc_only;
|
||||
};
|
||||
|
||||
struct wkup_m3_wakeup_src {
|
||||
int irq_nr;
|
||||
char src[10];
|
||||
};
|
||||
|
||||
struct wkup_m3_ipc_ops {
|
||||
|
@ -48,8 +54,11 @@ struct wkup_m3_ipc_ops {
|
|||
int (*prepare_low_power)(struct wkup_m3_ipc *m3_ipc, int state);
|
||||
int (*finish_low_power)(struct wkup_m3_ipc *m3_ipc);
|
||||
int (*request_pm_status)(struct wkup_m3_ipc *m3_ipc);
|
||||
const char *(*request_wake_src)(struct wkup_m3_ipc *m3_ipc);
|
||||
void (*set_rtc_only)(struct wkup_m3_ipc *m3_ipc);
|
||||
};
|
||||
|
||||
struct wkup_m3_ipc *wkup_m3_ipc_get(void);
|
||||
void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc);
|
||||
void wkup_m3_set_rtc_only_mode(void);
|
||||
#endif /* _LINUX_WKUP_M3_IPC_H */
|
||||
|
|
Loading…
Reference in a new issue