Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: omap: Save and restore sysconfig

As we are using cpu_pm to save and restore context, we must also save and
restore the GPIO sysconfig register. This is needed because we are not
calling PM runtime functions at all with cpu_pm.

We need to save the sysconfig on idle as it's value can get reconfigured by
PM runtime and can be different from the init time value. Device specific
flags like "ti,no-idle-on-init" can affect the init value.

Fixes: b764a5863fd8 ("gpio: omap: Remove custom PM calls and use cpu_pm instead")
Cc: Aaro Koskinen <aaro.koskinen@iki.fi>
Cc: Adam Ford <aford173@gmail.com>
Cc: Andreas Kemnade <andreas@kemnade.info>
Cc: Grygorii Strashko <grygorii.strashko@ti.com>
Cc: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Acked-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

authored by

Tony Lindgren and committed by
Bartosz Golaszewski
ddd8d94c 23cf00dd

+12
+9
drivers/gpio/gpio-omap.c
··· 29 29 #define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF 30 30 31 31 struct gpio_regs { 32 + u32 sysconfig; 32 33 u32 irqenable1; 33 34 u32 irqenable2; 34 35 u32 wake_en; ··· 1070 1069 const struct omap_gpio_reg_offs *regs = p->regs; 1071 1070 void __iomem *base = p->base; 1072 1071 1072 + p->context.sysconfig = readl_relaxed(base + regs->sysconfig); 1073 1073 p->context.ctrl = readl_relaxed(base + regs->ctrl); 1074 1074 p->context.oe = readl_relaxed(base + regs->direction); 1075 1075 p->context.wake_en = readl_relaxed(base + regs->wkup_en); ··· 1090 1088 const struct omap_gpio_reg_offs *regs = bank->regs; 1091 1089 void __iomem *base = bank->base; 1092 1090 1091 + writel_relaxed(bank->context.sysconfig, base + regs->sysconfig); 1093 1092 writel_relaxed(bank->context.wake_en, base + regs->wkup_en); 1094 1093 writel_relaxed(bank->context.ctrl, base + regs->ctrl); 1095 1094 writel_relaxed(bank->context.leveldetect0, base + regs->leveldetect0); ··· 1117 1114 u32 mask, nowake; 1118 1115 1119 1116 bank->saved_datain = readl_relaxed(base + bank->regs->datain); 1117 + 1118 + /* Save syconfig, it's runtime value can be different from init value */ 1119 + if (bank->loses_context) 1120 + bank->context.sysconfig = readl_relaxed(base + bank->regs->sysconfig); 1120 1121 1121 1122 if (!bank->enabled_non_wakeup_gpios) 1122 1123 goto update_gpio_context_count; ··· 1286 1279 1287 1280 static const struct omap_gpio_reg_offs omap2_gpio_regs = { 1288 1281 .revision = OMAP24XX_GPIO_REVISION, 1282 + .sysconfig = OMAP24XX_GPIO_SYSCONFIG, 1289 1283 .direction = OMAP24XX_GPIO_OE, 1290 1284 .datain = OMAP24XX_GPIO_DATAIN, 1291 1285 .dataout = OMAP24XX_GPIO_DATAOUT, ··· 1310 1302 1311 1303 static const struct omap_gpio_reg_offs omap4_gpio_regs = { 1312 1304 .revision = OMAP4_GPIO_REVISION, 1305 + .sysconfig = OMAP4_GPIO_SYSCONFIG, 1313 1306 .direction = OMAP4_GPIO_OE, 1314 1307 .datain = OMAP4_GPIO_DATAIN, 1315 1308 .dataout = OMAP4_GPIO_DATAOUT,
+3
include/linux/platform_data/gpio-omap.h
··· 85 85 * omap2+ specific GPIO registers 86 86 */ 87 87 #define OMAP24XX_GPIO_REVISION 0x0000 88 + #define OMAP24XX_GPIO_SYSCONFIG 0x0010 88 89 #define OMAP24XX_GPIO_IRQSTATUS1 0x0018 89 90 #define OMAP24XX_GPIO_IRQSTATUS2 0x0028 90 91 #define OMAP24XX_GPIO_IRQENABLE2 0x002c ··· 109 108 #define OMAP24XX_GPIO_SETDATAOUT 0x0094 110 109 111 110 #define OMAP4_GPIO_REVISION 0x0000 111 + #define OMAP4_GPIO_SYSCONFIG 0x0010 112 112 #define OMAP4_GPIO_EOI 0x0020 113 113 #define OMAP4_GPIO_IRQSTATUSRAW0 0x0024 114 114 #define OMAP4_GPIO_IRQSTATUSRAW1 0x0028 ··· 150 148 #ifndef __ASSEMBLER__ 151 149 struct omap_gpio_reg_offs { 152 150 u16 revision; 151 + u16 sysconfig; 153 152 u16 direction; 154 153 u16 datain; 155 154 u16 dataout;