aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2015-08-18 16:10:05 -0400
committerOlof Johansson <olof@lixom.net>2015-08-18 16:10:05 -0400
commit207b504a63b849519cc285c3ddb37411d67beead (patch)
tree9628c94cc7d9af0bab209c373b8f0c5bb904801f
parentf9511a4fc47940c7b08ae51567bd9bddb54b8461 (diff)
parent8a0fa1843638c5078e6606114ed8bdf9ea56fab1 (diff)
Merge tag 'imx-soc-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into next/soc
The i.MX SoC changes for 4.3: - Add i.MX6 Ultralite SoC support, which is the newest addition to i.MX6 family. It integrates a single Cortex-A7 core and a power management module that reduces the complexity of external power supply and simplifies power sequencing. - Change SNVS RTC driver to use syscon interface for register access, and add SNVS power key driver support. - Add a second clock for mxc rtc driver, and support device tree probe for the driver. - Add FEC MAC reference clock and phy fixup initialization for i.MX6UL platform. * tag 'imx-soc-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: rtc: snvs: select option REGMAP_MMIO ARM: imx6ul: add fec MAC refrence clock and phy fixup init ARM: imx6ul: add fec bits to GPR syscon definition rtc: mxc: add support of device tree dt-binding: document the binding for mxc rtc rtc: mxc: use a second rtc clock input: snvs_pwrkey: use "wakeup-source" as deivce tree property name Document: devicetree: input: imx: i.mx snvs power device tree bindings input: keyboard: imx: add snvs power key driver Document: dt: fsl: snvs: change support syscon rtc: snvs: use syscon to access register ARM: imx: add low-level debug support for i.mx6ul ARM: imx: add i.mx6ul msl support Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl-sec4.txt91
-rw-r--r--Documentation/devicetree/bindings/input/snvs-pwrkey.txt1
-rw-r--r--Documentation/devicetree/bindings/rtc/rtc-mxc.txt26
-rw-r--r--arch/arm/Kconfig.debug9
-rw-r--r--arch/arm/include/debug/imx-uart.h13
-rw-r--r--arch/arm/mach-imx/Kconfig8
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/cpu.c3
-rw-r--r--arch/arm/mach-imx/mach-imx6ul.c86
-rw-r--r--arch/arm/mach-imx/mxc.h6
-rw-r--r--drivers/input/keyboard/Kconfig11
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/snvs_pwrkey.c227
-rw-r--r--drivers/rtc/Kconfig1
-rw-r--r--drivers/rtc/rtc-mxc.c60
-rw-r--r--drivers/rtc/rtc-snvs.c132
-rw-r--r--include/linux/mfd/syscon/imx6q-iomuxc-gpr.h8
17 files changed, 592 insertions, 92 deletions
diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
index e4022776ac6e..f16bbd6644b8 100644
--- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
+++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
@@ -288,12 +288,13 @@ Secure Non-Volatile Storage (SNVS) Node
288 Node defines address range and the associated 288 Node defines address range and the associated
289 interrupt for the SNVS function. This function 289 interrupt for the SNVS function. This function
290 monitors security state information & reports 290 monitors security state information & reports
291 security violations. 291 security violations. This also included rtc,
292 system power off and ON/OFF key.
292 293
293 - compatible 294 - compatible
294 Usage: required 295 Usage: required
295 Value type: <string> 296 Value type: <string>
296 Definition: Must include "fsl,sec-v4.0-mon". 297 Definition: Must include "fsl,sec-v4.0-mon" and "syscon".
297 298
298 - reg 299 - reg
299 Usage: required 300 Usage: required
@@ -324,7 +325,7 @@ Secure Non-Volatile Storage (SNVS) Node
324 the child address, parent address, & length. 325 the child address, parent address, & length.
325 326
326 - interrupts 327 - interrupts
327 Usage: required 328 Usage: optional
328 Value type: <prop_encoded-array> 329 Value type: <prop_encoded-array>
329 Definition: Specifies the interrupts generated by this 330 Definition: Specifies the interrupts generated by this
330 device. The value of the interrupts property 331 device. The value of the interrupts property
@@ -341,7 +342,7 @@ Secure Non-Volatile Storage (SNVS) Node
341 342
342EXAMPLE 343EXAMPLE
343 sec_mon@314000 { 344 sec_mon@314000 {
344 compatible = "fsl,sec-v4.0-mon"; 345 compatible = "fsl,sec-v4.0-mon", "syscon";
345 reg = <0x314000 0x1000>; 346 reg = <0x314000 0x1000>;
346 ranges = <0 0x314000 0x1000>; 347 ranges = <0 0x314000 0x1000>;
347 interrupt-parent = <&mpic>; 348 interrupt-parent = <&mpic>;
@@ -358,16 +359,72 @@ Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC Node
358 Value type: <string> 359 Value type: <string>
359 Definition: Must include "fsl,sec-v4.0-mon-rtc-lp". 360 Definition: Must include "fsl,sec-v4.0-mon-rtc-lp".
360 361
361 - reg 362 - interrupts
362 Usage: required 363 Usage: required
363 Value type: <prop-encoded-array> 364 Value type: <prop_encoded-array>
364 Definition: A standard property. Specifies the physical 365 Definition: Specifies the interrupts generated by this
365 address and length of the SNVS LP configuration registers. 366 device. The value of the interrupts property
367 consists of one interrupt specifier. The format
368 of the specifier is defined by the binding document
369 describing the node's interrupt parent.
370
371 - regmap
372 Usage: required
373 Value type: <phandle>
374 Definition: this is phandle to the register map node.
375
376 - offset
377 Usage: option
378 value type: <u32>
379 Definition: LP register offset. default it is 0x34.
366 380
367EXAMPLE 381EXAMPLE
368 sec_mon_rtc_lp@314000 { 382 sec_mon_rtc_lp@1 {
369 compatible = "fsl,sec-v4.0-mon-rtc-lp"; 383 compatible = "fsl,sec-v4.0-mon-rtc-lp";
370 reg = <0x34 0x58>; 384 interrupts = <93 2>;
385 regmap = <&snvs>;
386 offset = <0x34>;
387 };
388
389=====================================================================
390System ON/OFF key driver
391
392 The snvs-pwrkey is designed to enable POWER key function which controlled
393 by SNVS ONOFF, the driver can report the status of POWER key and wakeup
394 system if pressed after system suspend.
395
396 - compatible:
397 Usage: required
398 Value type: <string>
399 Definition: Mush include "fsl,sec-v4.0-pwrkey".
400
401 - interrupts:
402 Usage: required
403 Value type: <prop_encoded-array>
404 Definition: The SNVS ON/OFF interrupt number to the CPU(s).
405
406 - linux,keycode:
407 Usage: option
408 Value type: <int>
409 Definition: Keycode to emit, KEY_POWER by default.
410
411 - wakeup-source:
412 Usage: option
413 Value type: <boo>
414 Definition: Button can wake-up the system.
415
416 - regmap:
417 Usage: required:
418 Value type: <phandle>
419 Definition: this is phandle to the register map node.
420
421EXAMPLE:
422 snvs-pwrkey@0x020cc000 {
423 compatible = "fsl,sec-v4.0-pwrkey";
424 regmap = <&snvs>;
425 interrupts = <0 4 0x4>
426 linux,keycode = <116>; /* KEY_POWER */
427 wakeup;
371 }; 428 };
372 429
373===================================================================== 430=====================================================================
@@ -443,12 +500,20 @@ FULL EXAMPLE
443 compatible = "fsl,sec-v4.0-mon"; 500 compatible = "fsl,sec-v4.0-mon";
444 reg = <0x314000 0x1000>; 501 reg = <0x314000 0x1000>;
445 ranges = <0 0x314000 0x1000>; 502 ranges = <0 0x314000 0x1000>;
446 interrupt-parent = <&mpic>;
447 interrupts = <93 2>;
448 503
449 sec_mon_rtc_lp@34 { 504 sec_mon_rtc_lp@34 {
450 compatible = "fsl,sec-v4.0-mon-rtc-lp"; 505 compatible = "fsl,sec-v4.0-mon-rtc-lp";
451 reg = <0x34 0x58>; 506 regmap = <&sec_mon>;
507 offset = <0x34>;
508 interrupts = <93 2>;
509 };
510
511 snvs-pwrkey@0x020cc000 {
512 compatible = "fsl,sec-v4.0-pwrkey";
513 regmap = <&sec_mon>;
514 interrupts = <0 4 0x4>;
515 linux,keycode = <116>; /* KEY_POWER */
516 wakeup;
452 }; 517 };
453 }; 518 };
454 519
diff --git a/Documentation/devicetree/bindings/input/snvs-pwrkey.txt b/Documentation/devicetree/bindings/input/snvs-pwrkey.txt
new file mode 100644
index 000000000000..70c14250323b
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/snvs-pwrkey.txt
@@ -0,0 +1 @@
See Documentation/devicetree/bindings/crypto/fsl-sec4.txt
diff --git a/Documentation/devicetree/bindings/rtc/rtc-mxc.txt b/Documentation/devicetree/bindings/rtc/rtc-mxc.txt
new file mode 100644
index 000000000000..5bcd31d995b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-mxc.txt
@@ -0,0 +1,26 @@
1* Real Time Clock of the i.MX SoCs
2
3RTC controller for the i.MX SoCs
4
5Required properties:
6- compatible: Should be "fsl,imx1-rtc" or "fsl,imx21-rtc".
7- reg: physical base address of the controller and length of memory mapped
8 region.
9- interrupts: IRQ line for the RTC.
10- clocks: should contain two entries:
11 * one for the input reference
12 * one for the the SoC RTC
13- clock-names: should contain:
14 * "ref" for the input reference clock
15 * "ipg" for the SoC RTC clock
16
17Example:
18
19rtc@10007000 {
20 compatible = "fsl,imx21-rtc";
21 reg = <0x10007000 0x1000>;
22 interrupts = <22>;
23 clocks = <&clks IMX27_CLK_CKIL>,
24 <&clks IMX27_CLK_RTC_IPG_GATE>;
25 clock-names = "ref", "ipg";
26};
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 946c8c0fa1fb..0cfd7f947f6b 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -417,6 +417,13 @@ choice
417 Say Y here if you want kernel low-level debugging support 417 Say Y here if you want kernel low-level debugging support
418 on i.MX6SX. 418 on i.MX6SX.
419 419
420 config DEBUG_IMX6UL_UART
421 bool "i.MX6UL Debug UART"
422 depends on SOC_IMX6UL
423 help
424 Say Y here if you want kernel low-level debugging support
425 on i.MX6UL.
426
420 config DEBUG_IMX7D_UART 427 config DEBUG_IMX7D_UART
421 bool "i.MX7D Debug UART" 428 bool "i.MX7D Debug UART"
422 depends on SOC_IMX7D 429 depends on SOC_IMX7D
@@ -1275,6 +1282,7 @@ config DEBUG_IMX_UART_PORT
1275 DEBUG_IMX6Q_UART || \ 1282 DEBUG_IMX6Q_UART || \
1276 DEBUG_IMX6SL_UART || \ 1283 DEBUG_IMX6SL_UART || \
1277 DEBUG_IMX6SX_UART || \ 1284 DEBUG_IMX6SX_UART || \
1285 DEBUG_IMX6UL_UART || \
1278 DEBUG_IMX7D_UART 1286 DEBUG_IMX7D_UART
1279 default 1 1287 default 1
1280 depends on ARCH_MXC 1288 depends on ARCH_MXC
@@ -1326,6 +1334,7 @@ config DEBUG_LL_INCLUDE
1326 DEBUG_IMX6Q_UART || \ 1334 DEBUG_IMX6Q_UART || \
1327 DEBUG_IMX6SL_UART || \ 1335 DEBUG_IMX6SL_UART || \
1328 DEBUG_IMX6SX_UART || \ 1336 DEBUG_IMX6SX_UART || \
1337 DEBUG_IMX6UL_UART || \
1329 DEBUG_IMX7D_UART 1338 DEBUG_IMX7D_UART
1330 default "debug/ks8695.S" if DEBUG_KS8695_UART 1339 default "debug/ks8695.S" if DEBUG_KS8695_UART
1331 default "debug/msm.S" if DEBUG_QCOM_UARTDM 1340 default "debug/msm.S" if DEBUG_QCOM_UARTDM
diff --git a/arch/arm/include/debug/imx-uart.h b/arch/arm/include/debug/imx-uart.h
index 66f736f74684..bce58e975ad1 100644
--- a/arch/arm/include/debug/imx-uart.h
+++ b/arch/arm/include/debug/imx-uart.h
@@ -90,6 +90,17 @@
90#define IMX6SX_UART_BASE_ADDR(n) IMX6SX_UART##n##_BASE_ADDR 90#define IMX6SX_UART_BASE_ADDR(n) IMX6SX_UART##n##_BASE_ADDR
91#define IMX6SX_UART_BASE(n) IMX6SX_UART_BASE_ADDR(n) 91#define IMX6SX_UART_BASE(n) IMX6SX_UART_BASE_ADDR(n)
92 92
93#define IMX6UL_UART1_BASE_ADDR 0x02020000
94#define IMX6UL_UART2_BASE_ADDR 0x021e8000
95#define IMX6UL_UART3_BASE_ADDR 0x021ec000
96#define IMX6UL_UART4_BASE_ADDR 0x021f0000
97#define IMX6UL_UART5_BASE_ADDR 0x021f4000
98#define IMX6UL_UART6_BASE_ADDR 0x021fc000
99#define IMX6UL_UART7_BASE_ADDR 0x02018000
100#define IMX6UL_UART8_BASE_ADDR 0x02024000
101#define IMX6UL_UART_BASE_ADDR(n) IMX6UL_UART##n##_BASE_ADDR
102#define IMX6UL_UART_BASE(n) IMX6UL_UART_BASE_ADDR(n)
103
93#define IMX7D_UART1_BASE_ADDR 0x30860000 104#define IMX7D_UART1_BASE_ADDR 0x30860000
94#define IMX7D_UART2_BASE_ADDR 0x30890000 105#define IMX7D_UART2_BASE_ADDR 0x30890000
95#define IMX7D_UART3_BASE_ADDR 0x30880000 106#define IMX7D_UART3_BASE_ADDR 0x30880000
@@ -124,6 +135,8 @@
124#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SL) 135#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SL)
125#elif defined(CONFIG_DEBUG_IMX6SX_UART) 136#elif defined(CONFIG_DEBUG_IMX6SX_UART)
126#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SX) 137#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SX)
138#elif defined(CONFIG_DEBUG_IMX6UL_UART)
139#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6UL)
127#elif defined(CONFIG_DEBUG_IMX7D_UART) 140#elif defined(CONFIG_DEBUG_IMX7D_UART)
128#define UART_PADDR IMX_DEBUG_UART_BASE(IMX7D) 141#define UART_PADDR IMX_DEBUG_UART_BASE(IMX7D)
129 142
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 573536f1bb73..8ceda2844c4f 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -548,6 +548,14 @@ config SOC_IMX6SX
548 help 548 help
549 This enables support for Freescale i.MX6 SoloX processor. 549 This enables support for Freescale i.MX6 SoloX processor.
550 550
551config SOC_IMX6UL
552 bool "i.MX6 UltraLite support"
553 select PINCTRL_IMX6UL
554 select SOC_IMX6
555
556 help
557 This enables support for Freescale i.MX6 UltraLite processor.
558
551config SOC_IMX7D 559config SOC_IMX7D
552 bool "i.MX7 Dual support" 560 bool "i.MX7 Dual support"
553 select PINCTRL_IMX7D 561 select PINCTRL_IMX7D
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 37c502ac9595..fb689d813b09 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -83,6 +83,7 @@ endif
83obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o 83obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o
84obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o 84obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
85obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o 85obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
86obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
86obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o 87obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o
87 88
88ifeq ($(CONFIG_SUSPEND),y) 89ifeq ($(CONFIG_SUSPEND),y)
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index a7fa92a7b1d7..5b0f752d5507 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -130,6 +130,9 @@ struct device * __init imx_soc_device_init(void)
130 case MXC_CPU_IMX6Q: 130 case MXC_CPU_IMX6Q:
131 soc_id = "i.MX6Q"; 131 soc_id = "i.MX6Q";
132 break; 132 break;
133 case MXC_CPU_IMX6UL:
134 soc_id = "i.MX6UL";
135 break;
133 case MXC_CPU_IMX7D: 136 case MXC_CPU_IMX7D:
134 soc_id = "i.MX7D"; 137 soc_id = "i.MX7D";
135 break; 138 break;
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
new file mode 100644
index 000000000000..db74da5b46af
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -0,0 +1,86 @@
1/*
2 * Copyright (C) 2015 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/irqchip.h>
9#include <linux/mfd/syscon.h>
10#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
11#include <linux/micrel_phy.h>
12#include <linux/of_platform.h>
13#include <linux/phy.h>
14#include <linux/regmap.h>
15#include <asm/mach/arch.h>
16#include <asm/mach/map.h>
17
18#include "common.h"
19
20static void __init imx6ul_enet_clk_init(void)
21{
22 struct regmap *gpr;
23
24 gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
25 if (!IS_ERR(gpr))
26 regmap_update_bits(gpr, IOMUXC_GPR1, IMX6UL_GPR1_ENET_CLK_DIR,
27 IMX6UL_GPR1_ENET_CLK_OUTPUT);
28 else
29 pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
30
31}
32
33static int ksz8081_phy_fixup(struct phy_device *dev)
34{
35 if (dev && dev->interface == PHY_INTERFACE_MODE_MII) {
36 phy_write(dev, 0x1f, 0x8110);
37 phy_write(dev, 0x16, 0x201);
38 } else if (dev && dev->interface == PHY_INTERFACE_MODE_RMII) {
39 phy_write(dev, 0x1f, 0x8190);
40 phy_write(dev, 0x16, 0x202);
41 }
42
43 return 0;
44}
45
46static void __init imx6ul_enet_phy_init(void)
47{
48 phy_register_fixup_for_uid(PHY_ID_KSZ8081, 0xffffffff, ksz8081_phy_fixup);
49}
50
51static inline void imx6ul_enet_init(void)
52{
53 imx6ul_enet_clk_init();
54 imx6ul_enet_phy_init();
55}
56
57static void __init imx6ul_init_machine(void)
58{
59 struct device *parent;
60
61 parent = imx_soc_device_init();
62 if (parent == NULL)
63 pr_warn("failed to initialize soc device\n");
64
65 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
66 imx6ul_enet_init();
67 imx_anatop_init();
68}
69
70static void __init imx6ul_init_irq(void)
71{
72 imx_init_revision_from_anatop();
73 imx_src_init();
74 irqchip_init();
75}
76
77static const char *imx6ul_dt_compat[] __initconst = {
78 "fsl,imx6ul",
79 NULL,
80};
81
82DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
83 .init_irq = imx6ul_init_irq,
84 .init_machine = imx6ul_init_machine,
85 .dt_compat = imx6ul_dt_compat,
86MACHINE_END
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index c4436d4fd6fd..a5b1af6d7441 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -38,6 +38,7 @@
38#define MXC_CPU_IMX6DL 0x61 38#define MXC_CPU_IMX6DL 0x61
39#define MXC_CPU_IMX6SX 0x62 39#define MXC_CPU_IMX6SX 0x62
40#define MXC_CPU_IMX6Q 0x63 40#define MXC_CPU_IMX6Q 0x63
41#define MXC_CPU_IMX6UL 0x64
41#define MXC_CPU_IMX7D 0x72 42#define MXC_CPU_IMX7D 0x72
42 43
43#define IMX_DDR_TYPE_LPDDR2 1 44#define IMX_DDR_TYPE_LPDDR2 1
@@ -165,6 +166,11 @@ static inline bool cpu_is_imx6sx(void)
165 return __mxc_cpu_type == MXC_CPU_IMX6SX; 166 return __mxc_cpu_type == MXC_CPU_IMX6SX;
166} 167}
167 168
169static inline bool cpu_is_imx6ul(void)
170{
171 return __mxc_cpu_type == MXC_CPU_IMX6UL;
172}
173
168static inline bool cpu_is_imx6q(void) 174static inline bool cpu_is_imx6q(void)
169{ 175{
170 return __mxc_cpu_type == MXC_CPU_IMX6Q; 176 return __mxc_cpu_type == MXC_CPU_IMX6Q;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4cd94fd6cbad..82a8fb50afac 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -401,6 +401,17 @@ config KEYBOARD_MPR121
401 To compile this driver as a module, choose M here: the 401 To compile this driver as a module, choose M here: the
402 module will be called mpr121_touchkey. 402 module will be called mpr121_touchkey.
403 403
404config KEYBOARD_SNVS_PWRKEY
405 tristate "IMX SNVS Power Key Driver"
406 depends on SOC_IMX6SX
407 depends on OF
408 help
409 This is the snvs powerkey driver for the Freescale i.MX application
410 processors that are newer than i.MX6 SX.
411
412 To compile this driver as a module, choose M here; the
413 module will be called snvs_pwrkey.
414
404config KEYBOARD_IMX 415config KEYBOARD_IMX
405 tristate "IMX keypad support" 416 tristate "IMX keypad support"
406 depends on ARCH_MXC 417 depends on ARCH_MXC
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index df28d5553c05..1d416ddf84e4 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o
51obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o 51obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o
52obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o 52obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o
53obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o 53obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
54obj-$(CONFIG_KEYBOARD_SNVS_PWRKEY) += snvs_pwrkey.o
54obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o 55obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o
55obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o 56obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
56obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o 57obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
new file mode 100644
index 000000000000..78fd24ca3813
--- /dev/null
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -0,0 +1,227 @@
1/*
2 * Driver for the IMX SNVS ON/OFF Power Key
3 * Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/device.h>
14#include <linux/err.h>
15#include <linux/init.h>
16#include <linux/input.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/jiffies.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/platform_device.h>
25#include <linux/mfd/syscon.h>
26#include <linux/regmap.h>
27
28#define SNVS_LPSR_REG 0x4C /* LP Status Register */
29#define SNVS_LPCR_REG 0x38 /* LP Control Register */
30#define SNVS_HPSR_REG 0x14
31#define SNVS_HPSR_BTN BIT(6)
32#define SNVS_LPSR_SPO BIT(18)
33#define SNVS_LPCR_DEP_EN BIT(5)
34
35#define DEBOUNCE_TIME 30
36#define REPEAT_INTERVAL 60
37
38struct pwrkey_drv_data {
39 struct regmap *snvs;
40 int irq;
41 int keycode;
42 int keystate; /* 1:pressed */
43 int wakeup;
44 struct timer_list check_timer;
45 struct input_dev *input;
46};
47
48static void imx_imx_snvs_check_for_events(unsigned long data)
49{
50 struct pwrkey_drv_data *pdata = (struct pwrkey_drv_data *) data;
51 struct input_dev *input = pdata->input;
52 u32 state;
53
54 regmap_read(pdata->snvs, SNVS_HPSR_REG, &state);
55 state = state & SNVS_HPSR_BTN ? 1 : 0;
56
57 /* only report new event if status changed */
58 if (state ^ pdata->keystate) {
59 pdata->keystate = state;
60 input_event(input, EV_KEY, pdata->keycode, state);
61 input_sync(input);
62 pm_relax(pdata->input->dev.parent);
63 }
64
65 /* repeat check if pressed long */
66 if (state) {
67 mod_timer(&pdata->check_timer,
68 jiffies + msecs_to_jiffies(REPEAT_INTERVAL));
69 }
70}
71
72static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
73{
74 struct platform_device *pdev = dev_id;
75 struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
76 u32 lp_status;
77
78 pm_wakeup_event(pdata->input->dev.parent, 0);
79
80 regmap_read(pdata->snvs, SNVS_LPSR_REG, &lp_status);
81 if (lp_status & SNVS_LPSR_SPO)
82 mod_timer(&pdata->check_timer, jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
83
84 /* clear SPO status */
85 regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
86
87 return IRQ_HANDLED;
88}
89
90static void imx_snvs_pwrkey_act(void *pdata)
91{
92 struct pwrkey_drv_data *pd = pdata;
93
94 del_timer_sync(&pd->check_timer);
95}
96
97static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
98{
99 struct pwrkey_drv_data *pdata = NULL;
100 struct input_dev *input = NULL;
101 struct device_node *np;
102 int error;
103
104 /* Get SNVS register Page */
105 np = pdev->dev.of_node;
106 if (!np)
107 return -ENODEV;
108
109 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
110 if (!pdata)
111 return -ENOMEM;
112
113 pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");;
114
115 if (!pdata->snvs) {
116 dev_err(&pdev->dev, "Can't get snvs syscon\n");
117 return -ENODEV;
118 }
119
120 if (of_property_read_u32(np, "linux,keycode", &pdata->keycode)) {
121 pdata->keycode = KEY_POWER;
122 dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
123 }
124
125 pdata->wakeup = of_property_read_bool(np, "wakeup-source");
126
127 pdata->irq = platform_get_irq(pdev, 0);
128 if (pdata->irq < 0) {
129 dev_err(&pdev->dev, "no irq defined in platform data\n");
130 return -EINVAL;
131 }
132
133 regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_DEP_EN, SNVS_LPCR_DEP_EN);
134
135 /* clear the unexpected interrupt before driver ready */
136 regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
137
138 setup_timer(&pdata->check_timer,
139 imx_imx_snvs_check_for_events, (unsigned long) pdata);
140
141 input = devm_input_allocate_device(&pdev->dev);
142 if (!input) {
143 dev_err(&pdev->dev, "failed to allocate the input device\n");
144 return -ENOMEM;
145 }
146
147 input->name = pdev->name;
148 input->phys = "snvs-pwrkey/input0";
149 input->id.bustype = BUS_HOST;
150
151 input_set_capability(input, EV_KEY, pdata->keycode);
152
153 /* input customer action to cancel release timer */
154 error = devm_add_action(&pdev->dev, imx_snvs_pwrkey_act, pdata);
155 if (error) {
156 dev_err(&pdev->dev, "failed to register remove action\n");
157 return error;
158 }
159
160 error = devm_request_irq(&pdev->dev, pdata->irq,
161 imx_snvs_pwrkey_interrupt,
162 0, pdev->name, pdev);
163
164 if (error) {
165 dev_err(&pdev->dev, "interrupt not available.\n");
166 return error;
167 }
168
169 error = input_register_device(input);
170 if (error < 0) {
171 dev_err(&pdev->dev, "failed to register input device\n");
172 input_free_device(input);
173 return error;
174 }
175
176 pdata->input = input;
177 platform_set_drvdata(pdev, pdata);
178
179 device_init_wakeup(&pdev->dev, pdata->wakeup);
180
181 return 0;
182}
183
184static int imx_snvs_pwrkey_suspend(struct device *dev)
185{
186 struct platform_device *pdev = to_platform_device(dev);
187 struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
188
189 if (device_may_wakeup(&pdev->dev))
190 enable_irq_wake(pdata->irq);
191
192 return 0;
193}
194
195static int imx_snvs_pwrkey_resume(struct device *dev)
196{
197 struct platform_device *pdev = to_platform_device(dev);
198 struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
199
200 if (device_may_wakeup(&pdev->dev))
201 disable_irq_wake(pdata->irq);
202
203 return 0;
204}
205
206static const struct of_device_id imx_snvs_pwrkey_ids[] = {
207 { .compatible = "fsl,sec-v4.0-pwrkey" },
208 { /* sentinel */ }
209};
210MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids);
211
212static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops, imx_snvs_pwrkey_suspend,
213 imx_snvs_pwrkey_resume);
214
215static struct platform_driver imx_snvs_pwrkey_driver = {
216 .driver = {
217 .name = "snvs_pwrkey",
218 .pm = &imx_snvs_pwrkey_pm_ops,
219 .of_match_table = imx_snvs_pwrkey_ids,
220 },
221 .probe = imx_snvs_pwrkey_probe,
222};
223module_platform_driver(imx_snvs_pwrkey_driver);
224
225MODULE_AUTHOR("Freescale Semiconductor");
226MODULE_DESCRIPTION("i.MX snvs power key Driver");
227MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 83b4b89b9d5a..533bfa3b6039 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1523,6 +1523,7 @@ config RTC_DRV_MXC
1523 1523
1524config RTC_DRV_SNVS 1524config RTC_DRV_SNVS
1525 tristate "Freescale SNVS RTC support" 1525 tristate "Freescale SNVS RTC support"
1526 select REGMAP_MMIO
1526 depends on HAS_IOMEM 1527 depends on HAS_IOMEM
1527 depends on OF 1528 depends on OF
1528 help 1529 help
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 5fc292c2dfdf..7bd89d90048f 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -16,6 +16,8 @@
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/of.h>
20#include <linux/of_device.h>
19 21
20#define RTC_INPUT_CLK_32768HZ (0x00 << 5) 22#define RTC_INPUT_CLK_32768HZ (0x00 << 5)
21#define RTC_INPUT_CLK_32000HZ (0x01 << 5) 23#define RTC_INPUT_CLK_32000HZ (0x01 << 5)
@@ -79,7 +81,8 @@ struct rtc_plat_data {
79 struct rtc_device *rtc; 81 struct rtc_device *rtc;
80 void __iomem *ioaddr; 82 void __iomem *ioaddr;
81 int irq; 83 int irq;
82 struct clk *clk; 84 struct clk *clk_ref;
85 struct clk *clk_ipg;
83 struct rtc_time g_rtc_alarm; 86 struct rtc_time g_rtc_alarm;
84 enum imx_rtc_type devtype; 87 enum imx_rtc_type devtype;
85}; 88};
@@ -97,6 +100,15 @@ static const struct platform_device_id imx_rtc_devtype[] = {
97}; 100};
98MODULE_DEVICE_TABLE(platform, imx_rtc_devtype); 101MODULE_DEVICE_TABLE(platform, imx_rtc_devtype);
99 102
103#ifdef CONFIG_OF
104static const struct of_device_id imx_rtc_dt_ids[] = {
105 { .compatible = "fsl,imx1-rtc", .data = (const void *)IMX1_RTC },
106 { .compatible = "fsl,imx21-rtc", .data = (const void *)IMX21_RTC },
107 {}
108};
109MODULE_DEVICE_TABLE(of, imx_rtc_dt_ids);
110#endif
111
100static inline int is_imx1_rtc(struct rtc_plat_data *data) 112static inline int is_imx1_rtc(struct rtc_plat_data *data)
101{ 113{
102 return data->devtype == IMX1_RTC; 114 return data->devtype == IMX1_RTC;
@@ -361,29 +373,45 @@ static int mxc_rtc_probe(struct platform_device *pdev)
361 u32 reg; 373 u32 reg;
362 unsigned long rate; 374 unsigned long rate;
363 int ret; 375 int ret;
376 const struct of_device_id *of_id;
364 377
365 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 378 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
366 if (!pdata) 379 if (!pdata)
367 return -ENOMEM; 380 return -ENOMEM;
368 381
369 pdata->devtype = pdev->id_entry->driver_data; 382 of_id = of_match_device(imx_rtc_dt_ids, &pdev->dev);
383 if (of_id)
384 pdata->devtype = (enum imx_rtc_type)of_id->data;
385 else
386 pdata->devtype = pdev->id_entry->driver_data;
370 387
371 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 388 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
372 pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res); 389 pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
373 if (IS_ERR(pdata->ioaddr)) 390 if (IS_ERR(pdata->ioaddr))
374 return PTR_ERR(pdata->ioaddr); 391 return PTR_ERR(pdata->ioaddr);
375 392
376 pdata->clk = devm_clk_get(&pdev->dev, NULL); 393 pdata->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
377 if (IS_ERR(pdata->clk)) { 394 if (IS_ERR(pdata->clk_ipg)) {
378 dev_err(&pdev->dev, "unable to get clock!\n"); 395 dev_err(&pdev->dev, "unable to get ipg clock!\n");
379 return PTR_ERR(pdata->clk); 396 return PTR_ERR(pdata->clk_ipg);
380 } 397 }
381 398
382 ret = clk_prepare_enable(pdata->clk); 399 ret = clk_prepare_enable(pdata->clk_ipg);
383 if (ret) 400 if (ret)
384 return ret; 401 return ret;
385 402
386 rate = clk_get_rate(pdata->clk); 403 pdata->clk_ref = devm_clk_get(&pdev->dev, "ref");
404 if (IS_ERR(pdata->clk_ref)) {
405 dev_err(&pdev->dev, "unable to get ref clock!\n");
406 ret = PTR_ERR(pdata->clk_ref);
407 goto exit_put_clk_ipg;
408 }
409
410 ret = clk_prepare_enable(pdata->clk_ref);
411 if (ret)
412 goto exit_put_clk_ipg;
413
414 rate = clk_get_rate(pdata->clk_ref);
387 415
388 if (rate == 32768) 416 if (rate == 32768)
389 reg = RTC_INPUT_CLK_32768HZ; 417 reg = RTC_INPUT_CLK_32768HZ;
@@ -394,7 +422,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)
394 else { 422 else {
395 dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); 423 dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate);
396 ret = -EINVAL; 424 ret = -EINVAL;
397 goto exit_put_clk; 425 goto exit_put_clk_ref;
398 } 426 }
399 427
400 reg |= RTC_ENABLE_BIT; 428 reg |= RTC_ENABLE_BIT;
@@ -402,7 +430,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)
402 if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { 430 if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) {
403 dev_err(&pdev->dev, "hardware module can't be enabled!\n"); 431 dev_err(&pdev->dev, "hardware module can't be enabled!\n");
404 ret = -EIO; 432 ret = -EIO;
405 goto exit_put_clk; 433 goto exit_put_clk_ref;
406 } 434 }
407 435
408 platform_set_drvdata(pdev, pdata); 436 platform_set_drvdata(pdev, pdata);
@@ -424,15 +452,17 @@ static int mxc_rtc_probe(struct platform_device *pdev)
424 THIS_MODULE); 452 THIS_MODULE);
425 if (IS_ERR(rtc)) { 453 if (IS_ERR(rtc)) {
426 ret = PTR_ERR(rtc); 454 ret = PTR_ERR(rtc);
427 goto exit_put_clk; 455 goto exit_put_clk_ref;
428 } 456 }
429 457
430 pdata->rtc = rtc; 458 pdata->rtc = rtc;
431 459
432 return 0; 460 return 0;
433 461
434exit_put_clk: 462exit_put_clk_ref:
435 clk_disable_unprepare(pdata->clk); 463 clk_disable_unprepare(pdata->clk_ref);
464exit_put_clk_ipg:
465 clk_disable_unprepare(pdata->clk_ipg);
436 466
437 return ret; 467 return ret;
438} 468}
@@ -441,7 +471,8 @@ static int mxc_rtc_remove(struct platform_device *pdev)
441{ 471{
442 struct rtc_plat_data *pdata = platform_get_drvdata(pdev); 472 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
443 473
444 clk_disable_unprepare(pdata->clk); 474 clk_disable_unprepare(pdata->clk_ref);
475 clk_disable_unprepare(pdata->clk_ipg);
445 476
446 return 0; 477 return 0;
447} 478}
@@ -473,6 +504,7 @@ static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume);
473static struct platform_driver mxc_rtc_driver = { 504static struct platform_driver mxc_rtc_driver = {
474 .driver = { 505 .driver = {
475 .name = "mxc_rtc", 506 .name = "mxc_rtc",
507 .of_match_table = of_match_ptr(imx_rtc_dt_ids),
476 .pm = &mxc_rtc_pm_ops, 508 .pm = &mxc_rtc_pm_ops,
477 }, 509 },
478 .id_table = imx_rtc_devtype, 510 .id_table = imx_rtc_devtype,
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index d87a85cefb66..950c5d0b6dca 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -18,6 +18,10 @@
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/rtc.h> 19#include <linux/rtc.h>
20#include <linux/clk.h> 20#include <linux/clk.h>
21#include <linux/mfd/syscon.h>
22#include <linux/regmap.h>
23
24#define SNVS_LPREGISTER_OFFSET 0x34
21 25
22/* These register offsets are relative to LP (Low Power) range */ 26/* These register offsets are relative to LP (Low Power) range */
23#define SNVS_LPCR 0x04 27#define SNVS_LPCR 0x04
@@ -37,31 +41,36 @@
37 41
38struct snvs_rtc_data { 42struct snvs_rtc_data {
39 struct rtc_device *rtc; 43 struct rtc_device *rtc;
40 void __iomem *ioaddr; 44 struct regmap *regmap;
45 int offset;
41 int irq; 46 int irq;
42 spinlock_t lock;
43 struct clk *clk; 47 struct clk *clk;
44}; 48};
45 49
46static u32 rtc_read_lp_counter(void __iomem *ioaddr) 50static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
47{ 51{
48 u64 read1, read2; 52 u64 read1, read2;
53 u32 val;
49 54
50 do { 55 do {
51 read1 = readl(ioaddr + SNVS_LPSRTCMR); 56 regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
57 read1 = val;
52 read1 <<= 32; 58 read1 <<= 32;
53 read1 |= readl(ioaddr + SNVS_LPSRTCLR); 59 regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
60 read1 |= val;
54 61
55 read2 = readl(ioaddr + SNVS_LPSRTCMR); 62 regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
63 read2 = val;
56 read2 <<= 32; 64 read2 <<= 32;
57 read2 |= readl(ioaddr + SNVS_LPSRTCLR); 65 regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
66 read2 |= val;
58 } while (read1 != read2); 67 } while (read1 != read2);
59 68
60 /* Convert 47-bit counter to 32-bit raw second count */ 69 /* Convert 47-bit counter to 32-bit raw second count */
61 return (u32) (read1 >> CNTR_TO_SECS_SH); 70 return (u32) (read1 >> CNTR_TO_SECS_SH);
62} 71}
63 72
64static void rtc_write_sync_lp(void __iomem *ioaddr) 73static void rtc_write_sync_lp(struct snvs_rtc_data *data)
65{ 74{
66 u32 count1, count2, count3; 75 u32 count1, count2, count3;
67 int i; 76 int i;
@@ -69,15 +78,15 @@ static void rtc_write_sync_lp(void __iomem *ioaddr)
69 /* Wait for 3 CKIL cycles */ 78 /* Wait for 3 CKIL cycles */
70 for (i = 0; i < 3; i++) { 79 for (i = 0; i < 3; i++) {
71 do { 80 do {
72 count1 = readl(ioaddr + SNVS_LPSRTCLR); 81 regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
73 count2 = readl(ioaddr + SNVS_LPSRTCLR); 82 regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
74 } while (count1 != count2); 83 } while (count1 != count2);
75 84
76 /* Now wait until counter value changes */ 85 /* Now wait until counter value changes */
77 do { 86 do {
78 do { 87 do {
79 count2 = readl(ioaddr + SNVS_LPSRTCLR); 88 regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
80 count3 = readl(ioaddr + SNVS_LPSRTCLR); 89 regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
81 } while (count2 != count3); 90 } while (count2 != count3);
82 } while (count3 == count1); 91 } while (count3 == count1);
83 } 92 }
@@ -85,23 +94,14 @@ static void rtc_write_sync_lp(void __iomem *ioaddr)
85 94
86static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable) 95static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
87{ 96{
88 unsigned long flags;
89 int timeout = 1000; 97 int timeout = 1000;
90 u32 lpcr; 98 u32 lpcr;
91 99
92 spin_lock_irqsave(&data->lock, flags); 100 regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_SRTC_ENV,
93 101 enable ? SNVS_LPCR_SRTC_ENV : 0);
94 lpcr = readl(data->ioaddr + SNVS_LPCR);
95 if (enable)
96 lpcr |= SNVS_LPCR_SRTC_ENV;
97 else
98 lpcr &= ~SNVS_LPCR_SRTC_ENV;
99 writel(lpcr, data->ioaddr + SNVS_LPCR);
100
101 spin_unlock_irqrestore(&data->lock, flags);
102 102
103 while (--timeout) { 103 while (--timeout) {
104 lpcr = readl(data->ioaddr + SNVS_LPCR); 104 regmap_read(data->regmap, data->offset + SNVS_LPCR, &lpcr);
105 105
106 if (enable) { 106 if (enable) {
107 if (lpcr & SNVS_LPCR_SRTC_ENV) 107 if (lpcr & SNVS_LPCR_SRTC_ENV)
@@ -121,7 +121,7 @@ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
121static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm) 121static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
122{ 122{
123 struct snvs_rtc_data *data = dev_get_drvdata(dev); 123 struct snvs_rtc_data *data = dev_get_drvdata(dev);
124 unsigned long time = rtc_read_lp_counter(data->ioaddr); 124 unsigned long time = rtc_read_lp_counter(data);
125 125
126 rtc_time_to_tm(time, tm); 126 rtc_time_to_tm(time, tm);
127 127
@@ -139,8 +139,8 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
139 snvs_rtc_enable(data, false); 139 snvs_rtc_enable(data, false);
140 140
141 /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */ 141 /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
142 writel(time << CNTR_TO_SECS_SH, data->ioaddr + SNVS_LPSRTCLR); 142 regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
143 writel(time >> (32 - CNTR_TO_SECS_SH), data->ioaddr + SNVS_LPSRTCMR); 143 regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
144 144
145 /* Enable RTC again */ 145 /* Enable RTC again */
146 snvs_rtc_enable(data, true); 146 snvs_rtc_enable(data, true);
@@ -153,10 +153,10 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
153 struct snvs_rtc_data *data = dev_get_drvdata(dev); 153 struct snvs_rtc_data *data = dev_get_drvdata(dev);
154 u32 lptar, lpsr; 154 u32 lptar, lpsr;
155 155
156 lptar = readl(data->ioaddr + SNVS_LPTAR); 156 regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
157 rtc_time_to_tm(lptar, &alrm->time); 157 rtc_time_to_tm(lptar, &alrm->time);
158 158
159 lpsr = readl(data->ioaddr + SNVS_LPSR); 159 regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
160 alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0; 160 alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
161 161
162 return 0; 162 return 0;
@@ -165,21 +165,12 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
165static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) 165static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
166{ 166{
167 struct snvs_rtc_data *data = dev_get_drvdata(dev); 167 struct snvs_rtc_data *data = dev_get_drvdata(dev);
168 u32 lpcr;
169 unsigned long flags;
170
171 spin_lock_irqsave(&data->lock, flags);
172 168
173 lpcr = readl(data->ioaddr + SNVS_LPCR); 169 regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
174 if (enable) 170 (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
175 lpcr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN); 171 enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
176 else
177 lpcr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
178 writel(lpcr, data->ioaddr + SNVS_LPCR);
179 172
180 spin_unlock_irqrestore(&data->lock, flags); 173 rtc_write_sync_lp(data);
181
182 rtc_write_sync_lp(data->ioaddr);
183 174
184 return 0; 175 return 0;
185} 176}
@@ -189,24 +180,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
189 struct snvs_rtc_data *data = dev_get_drvdata(dev); 180 struct snvs_rtc_data *data = dev_get_drvdata(dev);
190 struct rtc_time *alrm_tm = &alrm->time; 181 struct rtc_time *alrm_tm = &alrm->time;
191 unsigned long time; 182 unsigned long time;
192 unsigned long flags;
193 u32 lpcr;
194 183
195 rtc_tm_to_time(alrm_tm, &time); 184 rtc_tm_to_time(alrm_tm, &time);
196 185
197 spin_lock_irqsave(&data->lock, flags); 186 regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
198 187 regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
199 /* Have to clear LPTA_EN before programming new alarm time in LPTAR */
200 lpcr = readl(data->ioaddr + SNVS_LPCR);
201 lpcr &= ~SNVS_LPCR_LPTA_EN;
202 writel(lpcr, data->ioaddr + SNVS_LPCR);
203
204 spin_unlock_irqrestore(&data->lock, flags);
205
206 writel(time, data->ioaddr + SNVS_LPTAR);
207 188
208 /* Clear alarm interrupt status bit */ 189 /* Clear alarm interrupt status bit */
209 writel(SNVS_LPSR_LPTA, data->ioaddr + SNVS_LPSR); 190 regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
210 191
211 return snvs_rtc_alarm_irq_enable(dev, alrm->enabled); 192 return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
212} 193}
@@ -226,7 +207,7 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
226 u32 lpsr; 207 u32 lpsr;
227 u32 events = 0; 208 u32 events = 0;
228 209
229 lpsr = readl(data->ioaddr + SNVS_LPSR); 210 regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
230 211
231 if (lpsr & SNVS_LPSR_LPTA) { 212 if (lpsr & SNVS_LPSR_LPTA) {
232 events |= (RTC_AF | RTC_IRQF); 213 events |= (RTC_AF | RTC_IRQF);
@@ -238,25 +219,48 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
238 } 219 }
239 220
240 /* clear interrupt status */ 221 /* clear interrupt status */
241 writel(lpsr, data->ioaddr + SNVS_LPSR); 222 regmap_write(data->regmap, data->offset + SNVS_LPSR, lpsr);
242 223
243 return events ? IRQ_HANDLED : IRQ_NONE; 224 return events ? IRQ_HANDLED : IRQ_NONE;
244} 225}
245 226
227static const struct regmap_config snvs_rtc_config = {
228 .reg_bits = 32,
229 .val_bits = 32,
230 .reg_stride = 4,
231};
232
246static int snvs_rtc_probe(struct platform_device *pdev) 233static int snvs_rtc_probe(struct platform_device *pdev)
247{ 234{
248 struct snvs_rtc_data *data; 235 struct snvs_rtc_data *data;
249 struct resource *res; 236 struct resource *res;
250 int ret; 237 int ret;
238 void __iomem *mmio;
251 239
252 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 240 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
253 if (!data) 241 if (!data)
254 return -ENOMEM; 242 return -ENOMEM;
255 243
256 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 244 data->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");
257 data->ioaddr = devm_ioremap_resource(&pdev->dev, res); 245
258 if (IS_ERR(data->ioaddr)) 246 if (IS_ERR(data->regmap)) {
259 return PTR_ERR(data->ioaddr); 247 dev_warn(&pdev->dev, "snvs rtc: you use old dts file, please update it\n");
248 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
249
250 mmio = devm_ioremap_resource(&pdev->dev, res);
251 if (IS_ERR(mmio))
252 return PTR_ERR(mmio);
253
254 data->regmap = devm_regmap_init_mmio(&pdev->dev, mmio, &snvs_rtc_config);
255 } else {
256 data->offset = SNVS_LPREGISTER_OFFSET;
257 of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
258 }
259
260 if (!data->regmap) {
261 dev_err(&pdev->dev, "Can't find snvs syscon\n");
262 return -ENODEV;
263 }
260 264
261 data->irq = platform_get_irq(pdev, 0); 265 data->irq = platform_get_irq(pdev, 0);
262 if (data->irq < 0) 266 if (data->irq < 0)
@@ -276,13 +280,11 @@ static int snvs_rtc_probe(struct platform_device *pdev)
276 280
277 platform_set_drvdata(pdev, data); 281 platform_set_drvdata(pdev, data);
278 282
279 spin_lock_init(&data->lock);
280
281 /* Initialize glitch detect */ 283 /* Initialize glitch detect */
282 writel(SNVS_LPPGDR_INIT, data->ioaddr + SNVS_LPPGDR); 284 regmap_write(data->regmap, data->offset + SNVS_LPPGDR, SNVS_LPPGDR_INIT);
283 285
284 /* Clear interrupt status */ 286 /* Clear interrupt status */
285 writel(0xffffffff, data->ioaddr + SNVS_LPSR); 287 regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
286 288
287 /* Enable RTC */ 289 /* Enable RTC */
288 snvs_rtc_enable(data, true); 290 snvs_rtc_enable(data, true);
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
index d16f4c82c568..558a485d03ab 100644
--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -435,4 +435,12 @@
435#define IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS (0x1 << 1) 435#define IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS (0x1 << 1)
436#define IMX6SX_GPR5_DISP_MUX_DCIC1_MASK (0x1 << 1) 436#define IMX6SX_GPR5_DISP_MUX_DCIC1_MASK (0x1 << 1)
437 437
438/* For imx6ul iomux gpr register field define */
439#define IMX6UL_GPR1_ENET1_CLK_DIR (0x1 << 17)
440#define IMX6UL_GPR1_ENET2_CLK_DIR (0x1 << 18)
441#define IMX6UL_GPR1_ENET1_CLK_OUTPUT (0x1 << 17)
442#define IMX6UL_GPR1_ENET2_CLK_OUTPUT (0x1 << 18)
443#define IMX6UL_GPR1_ENET_CLK_DIR (0x3 << 17)
444#define IMX6UL_GPR1_ENET_CLK_OUTPUT (0x3 << 17)
445
438#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */ 446#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */