* [PATCH 09/11] ARM: imx: correct i.mx6sll dram io low power mode
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
i.MX6SLL has different DRAM IO offset, and it has no
CAS/RAS/ODT/RESET pin now, correct the DRAM IO offset.
To better support all different i.MX6 SoCs and different
DRAM types, introduce a new column to store the low power
settings for DRAM IO, then suspend asm code no need to check
SoC or DRAM type, just get the DRAM IO's low power
settings from OCRAM pm_info and set to each DRAM IO.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
arch/arm/mach-imx/pm-imx6.c | 17 ++++++++++++++++-
arch/arm/mach-imx/suspend-imx6.S | 29 +++++++----------------------
2 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 2ed4316..5fb78a9 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -230,7 +230,7 @@ struct imx6_cpu_pm_info {
struct imx6_pm_base gpc_base;
struct imx6_pm_base l2_base;
u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */
- u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
+ u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][3]; /* To save offset,value and low power setting */
} __aligned(8);
void imx6_set_int_mem_clk_lpm(bool enable)
@@ -570,6 +570,21 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
pm_info->mmdc_io_val[i][1] =
readl_relaxed(pm_info->iomuxc_base.vbase +
mmdc_offset_array[i]);
+ pm_info->mmdc_io_val[i][2] = 0;
+
+ }
+
+ /* i.MX6SLL has no DRAM RESET pin */
+ if (cpu_is_imx6sll()) {
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 2][2] = 0x1000;
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 1][2] = 0x1000;
+ } else {
+ if (pm_info->ddr_type == IMX_DDR_TYPE_LPDDR2) {
+ /* for LPDDR2, CKE0/1 and RESET pin need special setting */
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 3][2] = 0x1000;
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 2][2] = 0x1000;
+ pm_info->mmdc_io_val[pm_info->mmdc_io_num - 1][2] = 0x80000;
+ }
}
imx6_suspend_in_ocram_fn = fncpy(
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
index 76ee2ce..c9a26f4 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -104,7 +104,7 @@
add r7, r7, r0
1:
ldr r8, [r7], #0x4
- ldr r9, [r7], #0x4
+ ldr r9, [r7], #0x8
str r9, [r11, r8]
subs r6, r6, #0x1
bne 1b
@@ -179,7 +179,6 @@ ENTRY(imx6_suspend)
ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
ldr r6, [r11, #0x0]
- /* use r11 to store the IO address */
ldr r11, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
/* store physical resume addr and pm_info address. */
str r9, [r11, #MX6Q_SRC_GPR1]
@@ -207,32 +206,18 @@ poll_dvfs_set:
ands r7, r7, #(1 << 25)
beq poll_dvfs_set
+ /* use r11 to store the IO address */
ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
- ldr r6, =0x0
- ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
add r8, r8, r0
- /* LPDDR2's last 3 IOs need special setting */
- cmp r3, #IMX_DDR_TYPE_LPDDR2
- subeq r7, r7, #0x3
set_mmdc_io_lpm:
- ldr r9, [r8], #0x8
- str r6, [r11, r9]
- subs r7, r7, #0x1
+ ldr r7, [r8], #0x8
+ ldr r9, [r8], #0x4
+ str r9, [r11, r7]
+ subs r6, r6, #0x1
bne set_mmdc_io_lpm
- cmp r3, #IMX_DDR_TYPE_LPDDR2
- bne set_mmdc_io_lpm_done
- ldr r6, =0x1000
- ldr r9, [r8], #0x8
- str r6, [r11, r9]
- ldr r9, [r8], #0x8
- str r6, [r11, r9]
- ldr r6, =0x80000
- ldr r9, [r8]
- str r6, [r11, r9]
-set_mmdc_io_lpm_done:
-
/*
* mask all GPC interrupts before
* enabling the RBC counters to
--
1.9.1
^ permalink raw reply related
* [PATCH 08/11] ARM: imx: Add suspend/resume support for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
Add suspend/resume support for imx6sll.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
arch/arm/mach-imx/pm-imx6.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 1515e49..2ed4316 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -145,6 +145,13 @@ struct imx6_pm_socdata {
0x494, 0x4b0, /* MODE_CTL, MODE, */
};
+static const u32 imx6sll_mmdc_io_offset[] __initconst = {
+ 0x294, 0x298, 0x29c, 0x2a0, /* DQM0 ~ DQM3 */
+ 0x544, 0x54c, 0x554, 0x558, /* GPR_B0DS ~ GPR_B3DS */
+ 0x530, 0x540, 0x2ac, 0x52c, /* MODE_CTL, MODE, SDCLK_0, GPR_ADDDS */
+ 0x2a4, 0x2a8, /* SDCKE0, SDCKE1*/
+};
+
static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
.mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src",
@@ -195,6 +202,15 @@ struct imx6_pm_socdata {
.mmdc_io_offset = imx6ul_mmdc_io_offset,
};
+static const struct imx6_pm_socdata imx6sll_pm_data __initconst = {
+ .mmdc_compat = "fsl,imx6sll-mmdc",
+ .src_compat = "fsl,imx6sll-src",
+ .iomuxc_compat = "fsl,imx6sll-iomuxc",
+ .gpc_compat = "fsl,imx6sll-gpc",
+ .pl310_compat = "arm,pl310-cache",
+ .mmdc_io_num = ARRAY_SIZE(imx6sll_mmdc_io_offset),
+ .mmdc_io_offset = imx6sll_mmdc_io_offset,
+};
/*
* This structure is for passing necessary data for low level ocram
* suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
@@ -293,9 +309,10 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
val |= 0x2 << BP_CLPCR_LPM;
val &= ~BM_CLPCR_VSTBY;
val &= ~BM_CLPCR_SBYOS;
- if (cpu_is_imx6sl())
+ if (cpu_is_imx6sl() || cpu_is_imx6sll())
val |= BM_CLPCR_BYPASS_PMIC_READY;
- if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
+ cpu_is_imx6sll())
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
else
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@@ -310,9 +327,10 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
val |= 0x3 << BP_CLPCR_STBY_COUNT;
val |= BM_CLPCR_VSTBY;
val |= BM_CLPCR_SBYOS;
- if (cpu_is_imx6sl() || cpu_is_imx6sx())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6sll())
val |= BM_CLPCR_BYPASS_PMIC_READY;
- if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
+ if (cpu_is_imx6sl() || cpu_is_imx6sx() ||
+ cpu_is_imx6ul() || cpu_is_imx6sll())
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
else
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@@ -373,6 +391,7 @@ static int imx6q_pm_enter(suspend_state_t state)
imx6sl_set_wait_clk(true);
/* Zzz ... */
cpu_do_idle();
+
if (cpu_is_imx6sl())
imx6sl_set_wait_clk(false);
imx_gpc_post_resume();
@@ -632,7 +651,10 @@ void __init imx6dl_pm_init(void)
void __init imx6sl_pm_init(void)
{
- imx6_pm_common_init(&imx6sl_pm_data);
+ if (cpu_is_imx6sl())
+ imx6_pm_common_init(&imx6sl_pm_data);
+ else
+ imx6_pm_common_init(&imx6sll_pm_data);
}
void __init imx6sx_pm_init(void)
--
1.9.1
^ permalink raw reply related
* [PATCH 07/11] ARM: debug: Add low level debug support for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: kernel, fabio.estevam, daniel.lezcano, tglx, p.zabel, linux-clk,
devicetree, linux-gpio, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
Add low level debug support for i.MX6SLL.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
arch/arm/Kconfig.debug | 9 +++++++++
arch/arm/include/debug/imx-uart.h | 10 ++++++++++
2 files changed, 19 insertions(+)
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 408540f..d52d48c 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -405,6 +405,13 @@ choice
Say Y here if you want kernel low-level debugging support
on i.MX6SL.
+ config DEBUG_IMX6SLL_UART
+ bool "i.MX6SLL Debug UART"
+ depends on SOC_IMX6SLL
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX6SLL.
+
config DEBUG_IMX6SX_UART
bool "i.MX6SX Debug UART"
depends on SOC_IMX6SX
@@ -1374,6 +1381,7 @@ config DEBUG_IMX_UART_PORT
DEBUG_IMX53_UART || \
DEBUG_IMX6Q_UART || \
DEBUG_IMX6SL_UART || \
+ DEBUG_IMX6SLL_UART || \
DEBUG_IMX6SX_UART || \
DEBUG_IMX6UL_UART || \
DEBUG_IMX7D_UART
@@ -1428,6 +1436,7 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX53_UART ||\
DEBUG_IMX6Q_UART || \
DEBUG_IMX6SL_UART || \
+ DEBUG_IMX6SLL_UART || \
DEBUG_IMX6SX_UART || \
DEBUG_IMX6UL_UART || \
DEBUG_IMX7D_UART
diff --git a/arch/arm/include/debug/imx-uart.h b/arch/arm/include/debug/imx-uart.h
index bce58e9..24e60ce 100644
--- a/arch/arm/include/debug/imx-uart.h
+++ b/arch/arm/include/debug/imx-uart.h
@@ -81,6 +81,14 @@
#define IMX6SL_UART_BASE_ADDR(n) IMX6SL_UART##n##_BASE_ADDR
#define IMX6SL_UART_BASE(n) IMX6SL_UART_BASE_ADDR(n)
+#define IMX6SLL_UART1_BASE_ADDR 0x02020000
+#define IMX6SLL_UART2_BASE_ADDR 0x02024000
+#define IMX6SLL_UART3_BASE_ADDR 0x02034000
+#define IMX6SLL_UART4_BASE_ADDR 0x02018000
+#define IMX6SLL_UART5_BASE_ADDR 0x021f4000
+#define IMX6SLL_UART_BASE_ADDR(n) IMX6SLL_UART##n##_BASE_ADDR
+#define IMX6SLL_UART_BASE(n) IMX6SLL_UART_BASE_ADDR(n)
+
#define IMX6SX_UART1_BASE_ADDR 0x02020000
#define IMX6SX_UART2_BASE_ADDR 0x021e8000
#define IMX6SX_UART3_BASE_ADDR 0x021ec000
@@ -133,6 +141,8 @@
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6Q)
#elif defined(CONFIG_DEBUG_IMX6SL_UART)
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SL)
+#elif defined(CONFIG_DEBUG_IMX6SLL_UART)
+#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SLL)
#elif defined(CONFIG_DEBUG_IMX6SX_UART)
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SX)
#elif defined(CONFIG_DEBUG_IMX6UL_UART)
--
1.9.1
^ permalink raw reply related
* [PATCH 06/11] ARM: dts: imx: Add imx6sll EVK board dts support
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
Add basic dts support for imx6sll EVK baoard.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
arch/arm/boot/dts/Makefile | 2 +
arch/arm/boot/dts/imx6sll-evk.dts | 652 ++++++++++++++++++++++++++++++++++++++
2 files changed, 654 insertions(+)
create mode 100644 arch/arm/boot/dts/imx6sll-evk.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 38c595d..24eb4bd 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -416,6 +416,8 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
dtb-$(CONFIG_SOC_IMX6SL) += \
imx6sl-evk.dtb \
imx6sl-warp.dtb
+dtb-$(CONFIG_SOC_IMX6SLL) += \
+ imx6sll-evk.dtb
dtb-$(CONFIG_SOC_IMX6SX) += \
imx6sx-nitrogen6sx.dtb \
imx6sx-sabreauto.dtb \
diff --git a/arch/arm/boot/dts/imx6sll-evk.dts b/arch/arm/boot/dts/imx6sll-evk.dts
new file mode 100644
index 0000000..2a624cb
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-evk.dts
@@ -0,0 +1,652 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sll.dtsi"
+
+/ {
+ model = "Freescale i.MX6SLL EVK Board";
+ compatible = "fsl,imx6sll-evk", "fsl,imx6sll";
+
+ memory {
+ reg = <0x80000000 0x80000000>;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ status = "okay";
+ };
+
+ battery: max8903@0 {
+ compatible = "fsl,max8903-charger";
+ pinctrl-names = "default";
+ dok_input = <&gpio4 13 1>;
+ uok_input = <&gpio4 13 1>;
+ chg_input = <&gpio4 15 1>;
+ flt_input = <&gpio4 14 1>;
+ fsl,dcm_always_high;
+ fsl,dc_valid;
+ fsl,adc_disable;
+ status = "okay";
+ };
+
+ pxp_v4l2_out {
+ compatible = "fsl,imx6sl-pxp-v4l2";
+ status = "okay";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_usb_otg1_vbus: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_aud3v: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "wm8962-supply-3v15";
+ regulator-min-microvolt = <3150000>;
+ regulator-max-microvolt = <3150000>;
+ regulator-boot-on;
+ };
+
+ reg_aud4v: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "wm8962-supply-4v2";
+ regulator-min-microvolt = <4325000>;
+ regulator-max-microvolt = <4325000>;
+ regulator-boot-on;
+ };
+
+ reg_lcd: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "lcd-pwr";
+ gpio = <&gpio4 8 0>;
+ enable-active-high;
+ };
+
+ reg_sd1_vmmc: sd1_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD1_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_sd3_vmmc: sd3_vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "SD3_WIFI";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ cpu-dai = <&ssi2>;
+ audio-codec = <&codec>;
+ audio-routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Ext Spk", "SPKOUTL",
+ "Ext Spk", "SPKOUTR",
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC";
+ mux-int-port = <2>;
+ mux-ext-port = <3>;
+ codec-master;
+ hp-det-gpios = <&gpio4 24 1>;
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux3>;
+ status = "okay";
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6SLL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <393216000>;
+};
+
+&cpu0 {
+ arm-supply = <&sw1a_reg>;
+ soc-supply = <&sw1c_reg>;
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ max17135: max17135@48 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_max17135>;
+ compatible = "maxim,max17135";
+ reg = <0x48>;
+ status = "okay";
+
+ vneg_pwrup = <1>;
+ gvee_pwrup = <2>;
+ vpos_pwrup = <10>;
+ gvdd_pwrup = <12>;
+ gvdd_pwrdn = <1>;
+ vpos_pwrdn = <2>;
+ gvee_pwrdn = <8>;
+ vneg_pwrdn = <10>;
+ gpio_pmic_pwrgood = <&gpio2 13 0>;
+ gpio_pmic_vcom_ctrl = <&gpio2 3 0>;
+ gpio_pmic_wakeup = <&gpio2 14 0>;
+ gpio_pmic_v3p3 = <&gpio2 7 0>;
+ gpio_pmic_intr = <&gpio2 12 0>;
+
+ regulators {
+ DISPLAY_reg: DISPLAY {
+ regulator-name = "DISPLAY";
+ };
+
+ GVDD_reg: GVDD {
+ /* 20v */
+ regulator-name = "GVDD";
+ };
+
+ GVEE_reg: GVEE {
+ /* -22v */
+ regulator-name = "GVEE";
+ };
+
+ HVINN_reg: HVINN {
+ /* -22v */
+ regulator-name = "HVINN";
+ };
+
+ HVINP_reg: HVINP {
+ /* 20v */
+ regulator-name = "HVINP";
+ };
+
+ VCOM_reg: VCOM {
+ regulator-name = "VCOM";
+ /* 2's-compliment, -4325000 */
+ regulator-min-microvolt = <0xffbe0178>;
+ /* 2's-compliment, -500000 */
+ regulator-max-microvolt = <0xfff85ee0>;
+ };
+
+ VNEG_reg: VNEG {
+ /* -15v */
+ regulator-name = "VNEG";
+ };
+
+ VPOS_reg: VPOS {
+ /* 15v */
+ regulator-name = "VPOS";
+ };
+
+ V3P3_reg: V3P3 {
+ regulator-name = "V3P3";
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ codec: wm8962@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clks IMX6SLL_CLK_EXTERN_AUDIO>;
+ DCVDD-supply = <&vgen3_reg>;
+ DBVDD-supply = <®_aud3v>;
+ AVDD-supply = <&vgen3_reg>;
+ CPVDD-supply = <&vgen3_reg>;
+ MICVDD-supply = <®_aud3v>;
+ PLLVDD-supply = <&vgen3_reg>;
+ SPKVDD1-supply = <®_aud4v>;
+ SPKVDD2-supply = <®_aud4v>;
+ amic-mono;
+ };
+};
+
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6SLL_PAD_KEY_ROW7__GPIO4_IO07 0x17059
+ MX6SLL_PAD_GPIO4_IO22__GPIO4_IO22 0x17059
+ MX6SLL_PAD_KEY_COL3__GPIO3_IO30 0x17059
+ /*
+ * Must set the LVE of pad SD2_RESET, otherwise current
+ * leakage through eMMC chip will pull high the VCCQ to
+ * 2.6v, which will impact SD1 and SD3 SD3.0 voltage switch.
+ */
+ MX6SLL_PAD_SD2_RESET__GPIO4_IO27 0x417059
+ MX6SLL_PAD_KEY_COL4__GPIO4_IO00 0x17059
+ MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059 /* SD3 CD */
+ MX6SLL_PAD_KEY_COL6__GPIO4_IO04 0x17059 /*SD3 RESET */
+ MX6SLL_PAD_KEY_COL5__GPIO4_IO02 0x17059
+ MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x17059 /* HP DETECT */
+ /* CHG_FLT, CHG_UOK/DOK, CHG_STATUS */
+ MX6SLL_PAD_ECSPI2_MISO__GPIO4_IO14 0x17000
+ MX6SLL_PAD_ECSPI2_MOSI__GPIO4_IO13 0x17000
+ MX6SLL_PAD_ECSPI2_SS0__GPIO4_IO15 0x17000
+ >;
+ };
+
+ pinctrl_audmux3: audmux3grp {
+ fsl,pins = <
+ MX6SLL_PAD_AUD_TXC__AUD3_TXC 0x4130b0
+ MX6SLL_PAD_AUD_TXFS__AUD3_TXFS 0x4130b0
+ MX6SLL_PAD_AUD_TXD__AUD3_TXD 0x4110b0
+ MX6SLL_PAD_AUD_RXD__AUD3_RXD 0x4130b0
+ MX6SLL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+ >;
+ };
+
+ pinctrl_csi1: csi1grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_GDRL__CSI_MCLK 0x1b088
+ MX6SLL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x1b088
+ MX6SLL_PAD_EPDC_GDSP__CSI_VSYNC 0x1b088
+ MX6SLL_PAD_EPDC_GDOE__CSI_HSYNC 0x1b088
+ MX6SLL_PAD_EPDC_DATA02__CSI_DATA02 0x1b088
+ MX6SLL_PAD_EPDC_DATA03__CSI_DATA03 0x1b088
+ MX6SLL_PAD_EPDC_DATA04__CSI_DATA04 0x1b088
+ MX6SLL_PAD_EPDC_DATA05__CSI_DATA05 0x1b088
+ MX6SLL_PAD_EPDC_DATA06__CSI_DATA06 0x1b088
+ MX6SLL_PAD_EPDC_DATA07__CSI_DATA07 0x1b088
+ MX6SLL_PAD_EPDC_SDCLK__CSI_DATA08 0x1b088
+ MX6SLL_PAD_EPDC_SDLE__CSI_DATA09 0x1b088
+ MX6SLL_PAD_EPDC_SDSHR__GPIO1_IO26 0x80000000
+ MX6SLL_PAD_EPDC_SDOE__GPIO1_IO25 0x80000000
+ >;
+ };
+
+ pinctrl_lcdif_dat: lcdifdatgrp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_DATA00__LCD_DATA00 0x79
+ MX6SLL_PAD_LCD_DATA01__LCD_DATA01 0x79
+ MX6SLL_PAD_LCD_DATA02__LCD_DATA02 0x79
+ MX6SLL_PAD_LCD_DATA03__LCD_DATA03 0x79
+ MX6SLL_PAD_LCD_DATA04__LCD_DATA04 0x79
+ MX6SLL_PAD_LCD_DATA05__LCD_DATA05 0x79
+ MX6SLL_PAD_LCD_DATA06__LCD_DATA06 0x79
+ MX6SLL_PAD_LCD_DATA07__LCD_DATA07 0x79
+ MX6SLL_PAD_LCD_DATA08__LCD_DATA08 0x79
+ MX6SLL_PAD_LCD_DATA09__LCD_DATA09 0x79
+ MX6SLL_PAD_LCD_DATA10__LCD_DATA10 0x79
+ MX6SLL_PAD_LCD_DATA11__LCD_DATA11 0x79
+ MX6SLL_PAD_LCD_DATA12__LCD_DATA12 0x79
+ MX6SLL_PAD_LCD_DATA13__LCD_DATA13 0x79
+ MX6SLL_PAD_LCD_DATA14__LCD_DATA14 0x79
+ MX6SLL_PAD_LCD_DATA15__LCD_DATA15 0x79
+ MX6SLL_PAD_LCD_DATA16__LCD_DATA16 0x79
+ MX6SLL_PAD_LCD_DATA17__LCD_DATA17 0x79
+ MX6SLL_PAD_LCD_DATA18__LCD_DATA18 0x79
+ MX6SLL_PAD_LCD_DATA19__LCD_DATA19 0x79
+ MX6SLL_PAD_LCD_DATA20__LCD_DATA20 0x79
+ MX6SLL_PAD_LCD_DATA21__LCD_DATA21 0x79
+ MX6SLL_PAD_LCD_DATA22__LCD_DATA22 0x79
+ MX6SLL_PAD_LCD_DATA23__LCD_DATA23 0x79
+ >;
+ };
+
+ pinctrl_lcdif_ctrl: lcdifctrlgrp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_CLK__LCD_CLK 0x79
+ MX6SLL_PAD_LCD_ENABLE__LCD_ENABLE 0x79
+ MX6SLL_PAD_LCD_HSYNC__LCD_HSYNC 0x79
+ MX6SLL_PAD_LCD_VSYNC__LCD_VSYNC 0x79
+ MX6SLL_PAD_LCD_RESET__LCD_RESET 0x79
+ MX6SLL_PAD_ECSPI1_SCLK__GPIO4_IO08 0x79
+ >;
+ };
+
+ pinctrl_max17135: max17135grp-1 {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_PWR_STAT__GPIO2_IO13 0x80000000 /* pwrgood */
+ MX6SLL_PAD_EPDC_VCOM0__GPIO2_IO03 0x80000000 /* vcom_ctrl */
+ MX6SLL_PAD_EPDC_PWR_WAKE__GPIO2_IO14 0x80000000 /* wakeup */
+ MX6SLL_PAD_EPDC_PWR_CTRL0__GPIO2_IO07 0x80000000 /* v3p3 */
+ MX6SLL_PAD_EPDC_PWR_IRQ__GPIO2_IO12 0x80000000 /* pwr int */
+ >;
+ };
+
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_DATA4__SPDIF_OUT 0x4130b0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SLL_PAD_UART1_TXD__UART1_DCE_TX 0x1b0b1
+ MX6SLL_PAD_UART1_RXD__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x13059
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x17059
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x17059
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x17059
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp_100mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170b9
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130b9
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170b9
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170b9
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170b9
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp_200mhz {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170f9
+ MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130f9
+ MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170f9
+ MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170f9
+ MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170f9
+ MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
+ MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SLL_PAD_AUD_RXFS__I2C3_SCL 0x4041b8b1
+ MX6SLL_PAD_AUD_RXC__I2C3_SDA 0x4041b8b1
+ >;
+ };
+
+ pinctrl_pwm1: pmw1grp {
+ fsl,pins = <
+ MX6SLL_PAD_PWM1__PWM1_OUT 0x110b0
+ >;
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdif_dat
+ &pinctrl_lcdif_ctrl>;
+ lcd-supply = <®_lcd>;
+ display = <&display>;
+ status = "okay";
+
+ display: display {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <33500000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <89>;
+ hfront-porch = <164>;
+ vback-porch = <23>;
+ vfront-porch = <10>;
+ hsync-len = <10>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pxp {
+ status = "okay";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <®_sd1_vmmc>;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <®_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <®_usb_otg2_vbus>;
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&ssi2 {
+ status = "okay";
+};
--
1.9.1
^ permalink raw reply related
* [PATCH 05/11] ARM: dts: imx: Add basic dtsi for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo-DgEjT+Ai2ygdnm+yROfE0A,
mturquette-rdvid1DuHRBWk0Htik3J/w, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A
Cc: kernel-bIcnvbaLZ9MEGnE8C9+IrQ, fabio.estevam-3arQi8VN3Tc,
daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
tglx-hfZtesqFncYOwBW4kG4KsQ, p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
ping.bai-3arQi8VN3Tc
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai-3arQi8VN3Tc@public.gmane.org>
Add basic dtsi and pinfunc header file for imx6sll
Signed-off-by: Bai Ping <ping.bai-3arQi8VN3Tc@public.gmane.org>
---
arch/arm/boot/dts/imx6sll-pinfunc.h | 882 ++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/imx6sll.dtsi | 854 ++++++++++++++++++++++++++++++++++
2 files changed, 1736 insertions(+)
create mode 100644 arch/arm/boot/dts/imx6sll-pinfunc.h
create mode 100644 arch/arm/boot/dts/imx6sll.dtsi
diff --git a/arch/arm/boot/dts/imx6sll-pinfunc.h b/arch/arm/boot/dts/imx6sll-pinfunc.h
new file mode 100644
index 0000000..5a3700b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll-pinfunc.h
@@ -0,0 +1,882 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DTS_IMX6SLL_PINFUNC_H
+#define __DTS_IMX6SLL_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6SLL_PAD_WDOG_B__WDOG1_B 0x0014 0x02DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_WDOG_B__WDOG1_RESET_B_DEB 0x0014 0x02DC 0x0000 0x1 0x0
+#define MX6SLL_PAD_WDOG_B__UART5_RI_B 0x0014 0x02DC 0x0000 0x2 0x0
+#define MX6SLL_PAD_WDOG_B__GPIO3_IO18 0x0014 0x02DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_24M__XTALOSC_REF_CLK_24M 0x0018 0x02E0 0x0000 0x0 0x0
+#define MX6SLL_PAD_REF_CLK_24M__I2C3_SCL 0x0018 0x02E0 0x068C 0x1 0x0
+#define MX6SLL_PAD_REF_CLK_24M__PWM3_OUT 0x0018 0x02E0 0x0000 0x2 0x0
+#define MX6SLL_PAD_REF_CLK_24M__USB_OTG2_ID 0x0018 0x02E0 0x0560 0x3 0x0
+#define MX6SLL_PAD_REF_CLK_24M__CCM_PMIC_READY 0x0018 0x02E0 0x05AC 0x4 0x0
+#define MX6SLL_PAD_REF_CLK_24M__GPIO3_IO21 0x0018 0x02E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_24M__SD3_WP 0x0018 0x02E0 0x0794 0x6 0x0
+#define MX6SLL_PAD_REF_CLK_32K__XTALOSC_REF_CLK_32K 0x001C 0x02E4 0x0000 0x0 0x0
+#define MX6SLL_PAD_REF_CLK_32K__I2C3_SDA 0x001C 0x02E4 0x0690 0x1 0x0
+#define MX6SLL_PAD_REF_CLK_32K__PWM4_OUT 0x001C 0x02E4 0x0000 0x2 0x0
+#define MX6SLL_PAD_REF_CLK_32K__USB_OTG1_ID 0x001C 0x02E4 0x055C 0x3 0x0
+#define MX6SLL_PAD_REF_CLK_32K__SD1_LCTL 0x001C 0x02E4 0x0000 0x4 0x0
+#define MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22 0x001C 0x02E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_32K__SD3_CD_B 0x001C 0x02E4 0x0780 0x6 0x0
+#define MX6SLL_PAD_PWM1__PWM1_OUT 0x0020 0x02E8 0x0000 0x0 0x0
+#define MX6SLL_PAD_PWM1__CCM_CLKO 0x0020 0x02E8 0x0000 0x1 0x0
+#define MX6SLL_PAD_PWM1__AUDIO_CLK_OUT 0x0020 0x02E8 0x0000 0x2 0x0
+#define MX6SLL_PAD_PWM1__CSI_MCLK 0x0020 0x02E8 0x0000 0x4 0x0
+#define MX6SLL_PAD_PWM1__GPIO3_IO23 0x0020 0x02E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_PWM1__EPIT1_OUT 0x0020 0x02E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL0__KEY_COL0 0x0024 0x02EC 0x06A0 0x0 0x0
+#define MX6SLL_PAD_KEY_COL0__I2C2_SCL 0x0024 0x02EC 0x0684 0x1 0x0
+#define MX6SLL_PAD_KEY_COL0__LCD_DATA00 0x0024 0x02EC 0x06D8 0x2 0x0
+#define MX6SLL_PAD_KEY_COL0__SD1_CD_B 0x0024 0x02EC 0x0770 0x4 0x1
+#define MX6SLL_PAD_KEY_COL0__GPIO3_IO24 0x0024 0x02EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW0__KEY_ROW0 0x0028 0x02F0 0x06C0 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW0__I2C2_SDA 0x0028 0x02F0 0x0688 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW0__LCD_DATA01 0x0028 0x02F0 0x06DC 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW0__SD1_WP 0x0028 0x02F0 0x0774 0x4 0x1
+#define MX6SLL_PAD_KEY_ROW0__GPIO3_IO25 0x0028 0x02F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL1__KEY_COL1 0x002C 0x02F4 0x06A4 0x0 0x0
+#define MX6SLL_PAD_KEY_COL1__ECSPI4_MOSI 0x002C 0x02F4 0x0658 0x1 0x1
+#define MX6SLL_PAD_KEY_COL1__LCD_DATA02 0x002C 0x02F4 0x06E0 0x2 0x0
+#define MX6SLL_PAD_KEY_COL1__SD3_DATA4 0x002C 0x02F4 0x0784 0x4 0x0
+#define MX6SLL_PAD_KEY_COL1__GPIO3_IO26 0x002C 0x02F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW1__KEY_ROW1 0x0030 0x02F8 0x06C4 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW1__ECSPI4_MISO 0x0030 0x02F8 0x0654 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW1__LCD_DATA03 0x0030 0x02F8 0x06E4 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW1__CSI_FIELD 0x0030 0x02F8 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW1__SD3_DATA5 0x0030 0x02F8 0x0788 0x4 0x0
+#define MX6SLL_PAD_KEY_ROW1__GPIO3_IO27 0x0030 0x02F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL2__KEY_COL2 0x0034 0x02FC 0x06A8 0x0 0x0
+#define MX6SLL_PAD_KEY_COL2__ECSPI4_SS0 0x0034 0x02FC 0x065C 0x1 0x1
+#define MX6SLL_PAD_KEY_COL2__LCD_DATA04 0x0034 0x02FC 0x06E8 0x2 0x0
+#define MX6SLL_PAD_KEY_COL2__CSI_DATA12 0x0034 0x02FC 0x05B8 0x3 0x1
+#define MX6SLL_PAD_KEY_COL2__SD3_DATA6 0x0034 0x02FC 0x078C 0x4 0x0
+#define MX6SLL_PAD_KEY_COL2__GPIO3_IO28 0x0034 0x02FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW2__KEY_ROW2 0x0038 0x0300 0x06C8 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW2__ECSPI4_SCLK 0x0038 0x0300 0x0650 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW2__LCD_DATA05 0x0038 0x0300 0x06EC 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW2__CSI_DATA13 0x0038 0x0300 0x05BC 0x3 0x1
+#define MX6SLL_PAD_KEY_ROW2__SD3_DATA7 0x0038 0x0300 0x0790 0x4 0x0
+#define MX6SLL_PAD_KEY_ROW2__GPIO3_IO29 0x0038 0x0300 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL3__KEY_COL3 0x003C 0x0304 0x06AC 0x0 0x0
+#define MX6SLL_PAD_KEY_COL3__AUD6_RXFS 0x003C 0x0304 0x05A0 0x1 0x1
+#define MX6SLL_PAD_KEY_COL3__LCD_DATA06 0x003C 0x0304 0x06F0 0x2 0x0
+#define MX6SLL_PAD_KEY_COL3__CSI_DATA14 0x003C 0x0304 0x05C0 0x3 0x1
+#define MX6SLL_PAD_KEY_COL3__GPIO3_IO30 0x003C 0x0304 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL3__SD1_RESET 0x003C 0x0304 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW3__KEY_ROW3 0x0040 0x0308 0x06CC 0x0 0x1
+#define MX6SLL_PAD_KEY_ROW3__AUD6_RXC 0x0040 0x0308 0x059C 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW3__LCD_DATA07 0x0040 0x0308 0x06F4 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW3__CSI_DATA15 0x0040 0x0308 0x05C4 0x3 0x2
+#define MX6SLL_PAD_KEY_ROW3__GPIO3_IO31 0x0040 0x0308 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW3__SD1_VSELECT 0x0040 0x0308 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL4__KEY_COL4 0x0044 0x030C 0x06B0 0x0 0x1
+#define MX6SLL_PAD_KEY_COL4__AUD6_RXD 0x0044 0x030C 0x0594 0x1 0x1
+#define MX6SLL_PAD_KEY_COL4__LCD_DATA08 0x0044 0x030C 0x06F8 0x2 0x1
+#define MX6SLL_PAD_KEY_COL4__CSI_DATA16 0x0044 0x030C 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL4__GPIO4_IO00 0x0044 0x030C 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL4__USB_OTG1_PWR 0x0044 0x030C 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW4__KEY_ROW4 0x0048 0x0310 0x06D0 0x0 0x1
+#define MX6SLL_PAD_KEY_ROW4__AUD6_TXC 0x0048 0x0310 0x05A4 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW4__LCD_DATA09 0x0048 0x0310 0x06FC 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW4__CSI_DATA17 0x0048 0x0310 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW4__GPIO4_IO01 0x0048 0x0310 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW4__USB_OTG1_OC 0x0048 0x0310 0x076C 0x6 0x2
+#define MX6SLL_PAD_KEY_COL5__KEY_COL5 0x004C 0x0314 0x0694 0x0 0x1
+#define MX6SLL_PAD_KEY_COL5__AUD6_TXFS 0x004C 0x0314 0x05A8 0x1 0x1
+#define MX6SLL_PAD_KEY_COL5__LCD_DATA10 0x004C 0x0314 0x0700 0x2 0x0
+#define MX6SLL_PAD_KEY_COL5__CSI_DATA18 0x004C 0x0314 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL5__GPIO4_IO02 0x004C 0x0314 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL5__USB_OTG2_PWR 0x004C 0x0314 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW5__KEY_ROW5 0x0050 0x0318 0x06B4 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW5__AUD6_TXD 0x0050 0x0318 0x0598 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW5__LCD_DATA11 0x0050 0x0318 0x0704 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW5__CSI_DATA19 0x0050 0x0318 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW5__GPIO4_IO03 0x0050 0x0318 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW5__USB_OTG2_OC 0x0050 0x0318 0x0768 0x6 0x3
+#define MX6SLL_PAD_KEY_COL6__KEY_COL6 0x0054 0x031C 0x0698 0x0 0x2
+#define MX6SLL_PAD_KEY_COL6__UART4_DCE_RX 0x0054 0x031C 0x075C 0x1 0x2
+#define MX6SLL_PAD_KEY_COL6__UART4_DTE_TX 0x0054 0x031C 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_COL6__LCD_DATA12 0x0054 0x031C 0x0708 0x2 0x1
+#define MX6SLL_PAD_KEY_COL6__CSI_DATA20 0x0054 0x031C 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL6__GPIO4_IO04 0x0054 0x031C 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL6__SD3_RESET 0x0054 0x031C 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW6__KEY_ROW6 0x0058 0x0320 0x06B8 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW6__UART4_DCE_TX 0x0058 0x0320 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW6__UART4_DTE_RX 0x0058 0x0320 0x075C 0x1 0x3
+#define MX6SLL_PAD_KEY_ROW6__LCD_DATA13 0x0058 0x0320 0x070C 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW6__CSI_DATA21 0x0058 0x0320 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW6__GPIO4_IO05 0x0058 0x0320 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW6__SD3_VSELECT 0x0058 0x0320 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL7__KEY_COL7 0x005C 0x0324 0x069C 0x0 0x2
+#define MX6SLL_PAD_KEY_COL7__UART4_DCE_RTS 0x005C 0x0324 0x0758 0x1 0x2
+#define MX6SLL_PAD_KEY_COL7__UART4_DTE_CTS 0x005C 0x0324 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_COL7__LCD_DATA14 0x005C 0x0324 0x0710 0x2 0x1
+#define MX6SLL_PAD_KEY_COL7__CSI_DATA22 0x005C 0x0324 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL7__GPIO4_IO06 0x005C 0x0324 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL7__SD1_WP 0x005C 0x0324 0x0774 0x6 0x3
+#define MX6SLL_PAD_KEY_ROW7__KEY_ROW7 0x0060 0x0328 0x06BC 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW7__UART4_DCE_CTS 0x0060 0x0328 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW7__UART4_DTE_RTS 0x0060 0x0328 0x0758 0x1 0x3
+#define MX6SLL_PAD_KEY_ROW7__LCD_DATA15 0x0060 0x0328 0x0714 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW7__CSI_DATA23 0x0060 0x0328 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW7__GPIO4_IO07 0x0060 0x0328 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW7__SD1_CD_B 0x0060 0x0328 0x0770 0x6 0x3
+#define MX6SLL_PAD_EPDC_DATA00__EPDC_DATA00 0x0064 0x032C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA00__ECSPI4_MOSI 0x0064 0x032C 0x0658 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA00__LCD_DATA24 0x0064 0x032C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA00__CSI_DATA00 0x0064 0x032C 0x05C8 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA00__GPIO1_IO07 0x0064 0x032C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA01__EPDC_DATA01 0x0068 0x0330 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA01__ECSPI4_MISO 0x0068 0x0330 0x0654 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA01__LCD_DATA25 0x0068 0x0330 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA01__CSI_DATA01 0x0068 0x0330 0x05CC 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA01__GPIO1_IO08 0x0068 0x0330 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA02__EPDC_DATA02 0x006C 0x0334 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA02__ECSPI4_SS0 0x006C 0x0334 0x065C 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA02__LCD_DATA26 0x006C 0x0334 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA02__CSI_DATA02 0x006C 0x0334 0x05D0 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA02__GPIO1_IO09 0x006C 0x0334 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA03__EPDC_DATA03 0x0070 0x0338 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA03__ECSPI4_SCLK 0x0070 0x0338 0x0650 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA03__LCD_DATA27 0x0070 0x0338 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA03__CSI_DATA03 0x0070 0x0338 0x05D4 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA03__GPIO1_IO10 0x0070 0x0338 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA04__EPDC_DATA04 0x0074 0x033C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA04__ECSPI4_SS1 0x0074 0x033C 0x0660 0x1 0x1
+#define MX6SLL_PAD_EPDC_DATA04__LCD_DATA28 0x0074 0x033C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA04__CSI_DATA04 0x0074 0x033C 0x05D8 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA04__GPIO1_IO11 0x0074 0x033C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA05__EPDC_DATA05 0x0078 0x0340 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA05__ECSPI4_SS2 0x0078 0x0340 0x0664 0x1 0x1
+#define MX6SLL_PAD_EPDC_DATA05__LCD_DATA29 0x0078 0x0340 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA05__CSI_DATA05 0x0078 0x0340 0x05DC 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA05__GPIO1_IO12 0x0078 0x0340 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA06__EPDC_DATA06 0x007C 0x0344 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA06__ECSPI4_SS3 0x007C 0x0344 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA06__LCD_DATA30 0x007C 0x0344 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA06__CSI_DATA06 0x007C 0x0344 0x05E0 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA06__GPIO1_IO13 0x007C 0x0344 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA07__EPDC_DATA07 0x0080 0x0348 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA07__ECSPI4_RDY 0x0080 0x0348 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA07__LCD_DATA31 0x0080 0x0348 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA07__CSI_DATA07 0x0080 0x0348 0x05E4 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA07__GPIO1_IO14 0x0080 0x0348 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA08__EPDC_DATA08 0x0084 0x034C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA08__ECSPI3_MOSI 0x0084 0x034C 0x063C 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA08__EPDC_PWR_CTRL0 0x0084 0x034C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA08__GPIO1_IO15 0x0084 0x034C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA09__EPDC_DATA09 0x0088 0x0350 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA09__ECSPI3_MISO 0x0088 0x0350 0x0638 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA09__EPDC_PWR_CTRL1 0x0088 0x0350 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA09__GPIO1_IO16 0x0088 0x0350 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA10__EPDC_DATA10 0x008C 0x0354 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA10__ECSPI3_SS0 0x008C 0x0354 0x0648 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA10__EPDC_PWR_CTRL2 0x008C 0x0354 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA10__GPIO1_IO17 0x008C 0x0354 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA11__EPDC_DATA11 0x0090 0x0358 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA11__ECSPI3_SCLK 0x0090 0x0358 0x0630 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA11__EPDC_PWR_CTRL3 0x0090 0x0358 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA11__GPIO1_IO18 0x0090 0x0358 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA12__EPDC_DATA12 0x0094 0x035C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA12__UART2_DCE_RX 0x0094 0x035C 0x074C 0x1 0x4
+#define MX6SLL_PAD_EPDC_DATA12__UART2_DTE_TX 0x0094 0x035C 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA12__EPDC_PWR_COM 0x0094 0x035C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA12__GPIO1_IO19 0x0094 0x035C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA12__ECSPI3_SS1 0x0094 0x035C 0x064C 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA13__EPDC_DATA13 0x0098 0x0360 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA13__UART2_DCE_TX 0x0098 0x0360 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA13__UART2_DTE_RX 0x0098 0x0360 0x074C 0x1 0x5
+#define MX6SLL_PAD_EPDC_DATA13__EPDC_PWR_IRQ 0x0098 0x0360 0x0668 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA13__GPIO1_IO20 0x0098 0x0360 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA13__ECSPI3_SS2 0x0098 0x0360 0x0640 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA14__EPDC_DATA14 0x009C 0x0364 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA14__UART2_DCE_RTS 0x009C 0x0364 0x0748 0x1 0x4
+#define MX6SLL_PAD_EPDC_DATA14__UART2_DTE_CTS 0x009C 0x0364 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA14__EPDC_PWR_STAT 0x009C 0x0364 0x066C 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA14__GPIO1_IO21 0x009C 0x0364 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA14__ECSPI3_SS3 0x009C 0x0364 0x0644 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA15__EPDC_DATA15 0x00A0 0x0368 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA15__UART2_DCE_CTS 0x00A0 0x0368 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA15__UART2_DTE_RTS 0x00A0 0x0368 0x0748 0x1 0x5
+#define MX6SLL_PAD_EPDC_DATA15__EPDC_PWR_WAKE 0x00A0 0x0368 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA15__GPIO1_IO22 0x00A0 0x0368 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA15__ECSPI3_RDY 0x00A0 0x0368 0x0634 0x6 0x1
+#define MX6SLL_PAD_EPDC_SDCLK__EPDC_SDCLK_P 0x00A4 0x036C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCLK__ECSPI2_MOSI 0x00A4 0x036C 0x0624 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__I2C2_SCL 0x00A4 0x036C 0x0684 0x2 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__CSI_DATA08 0x00A4 0x036C 0x05E8 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__GPIO1_IO23 0x00A4 0x036C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDLE__EPDC_SDLE 0x00A8 0x0370 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDLE__ECSPI2_MISO 0x00A8 0x0370 0x0620 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDLE__I2C2_SDA 0x00A8 0x0370 0x0688 0x2 0x2
+#define MX6SLL_PAD_EPDC_SDLE__CSI_DATA09 0x00A8 0x0370 0x05EC 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDLE__GPIO1_IO24 0x00A8 0x0370 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDOE__EPDC_SDOE 0x00AC 0x0374 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDOE__ECSPI2_SS0 0x00AC 0x0374 0x0628 0x1 0x1
+#define MX6SLL_PAD_EPDC_SDOE__CSI_DATA10 0x00AC 0x0374 0x05B0 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDOE__GPIO1_IO25 0x00AC 0x0374 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__EPDC_SDSHR 0x00B0 0x0378 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__ECSPI2_SCLK 0x00B0 0x0378 0x061C 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDSHR__EPDC_SDCE4 0x00B0 0x0378 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__CSI_DATA11 0x00B0 0x0378 0x05B4 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDSHR__GPIO1_IO26 0x00B0 0x0378 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__EPDC_SDCE0 0x00B4 0x037C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__ECSPI2_SS1 0x00B4 0x037C 0x062C 0x1 0x1
+#define MX6SLL_PAD_EPDC_SDCE0__PWM3_OUT 0x00B4 0x037C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__GPIO1_IO27 0x00B4 0x037C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__EPDC_SDCE1 0x00B8 0x0380 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__WDOG2_B 0x00B8 0x0380 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__PWM4_OUT 0x00B8 0x0380 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__GPIO1_IO28 0x00B8 0x0380 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__EPDC_SDCE2 0x00BC 0x0384 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__I2C3_SCL 0x00BC 0x0384 0x068C 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCE2__PWM1_OUT 0x00BC 0x0384 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__GPIO1_IO29 0x00BC 0x0384 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__EPDC_SDCE3 0x00C0 0x0388 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__I2C3_SDA 0x00C0 0x0388 0x0690 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCE3__PWM2_OUT 0x00C0 0x0388 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__GPIO1_IO30 0x00C0 0x0388 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__EPDC_GDCLK 0x00C4 0x038C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__ECSPI2_SS2 0x00C4 0x038C 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x00C4 0x038C 0x05F4 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDCLK__GPIO1_IO31 0x00C4 0x038C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__SD2_RESET 0x00C4 0x038C 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_GDOE__EPDC_GDOE 0x00C8 0x0390 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDOE__ECSPI2_SS3 0x00C8 0x0390 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDOE__CSI_HSYNC 0x00C8 0x0390 0x05F0 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDOE__GPIO2_IO00 0x00C8 0x0390 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDOE__SD2_VSELECT 0x00C8 0x0390 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_GDRL__EPDC_GDRL 0x00CC 0x0394 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDRL__ECSPI2_RDY 0x00CC 0x0394 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDRL__CSI_MCLK 0x00CC 0x0394 0x0000 0x3 0x0
+#define MX6SLL_PAD_EPDC_GDRL__GPIO2_IO01 0x00CC 0x0394 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDRL__SD2_WP 0x00CC 0x0394 0x077C 0x6 0x2
+#define MX6SLL_PAD_EPDC_GDSP__EPDC_GDSP 0x00D0 0x0398 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDSP__PWM4_OUT 0x00D0 0x0398 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDSP__CSI_VSYNC 0x00D0 0x0398 0x05F8 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDSP__GPIO2_IO02 0x00D0 0x0398 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDSP__SD2_CD_B 0x00D0 0x0398 0x0778 0x6 0x2
+#define MX6SLL_PAD_EPDC_VCOM0__EPDC_VCOM0 0x00D4 0x039C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__AUD5_RXFS 0x00D4 0x039C 0x0588 0x1 0x1
+#define MX6SLL_PAD_EPDC_VCOM0__UART3_DCE_RX 0x00D4 0x039C 0x0754 0x2 0x4
+#define MX6SLL_PAD_EPDC_VCOM0__UART3_DTE_TX 0x00D4 0x039C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__GPIO2_IO03 0x00D4 0x039C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__EPDC_SDCE5 0x00D4 0x039C 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__EPDC_VCOM1 0x00D8 0x03A0 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__AUD5_RXD 0x00D8 0x03A0 0x057C 0x1 0x1
+#define MX6SLL_PAD_EPDC_VCOM1__UART3_DCE_TX 0x00D8 0x03A0 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__UART3_DTE_RX 0x00D8 0x03A0 0x0754 0x2 0x5
+#define MX6SLL_PAD_EPDC_VCOM1__GPIO2_IO04 0x00D8 0x03A0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__EPDC_SDCE6 0x00D8 0x03A0 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_BDR0__EPDC_BDR0 0x00DC 0x03A4 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_BDR0__UART3_DCE_RTS 0x00DC 0x03A4 0x0750 0x2 0x2
+#define MX6SLL_PAD_EPDC_BDR0__UART3_DTE_CTS 0x00DC 0x03A4 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_BDR0__GPIO2_IO05 0x00DC 0x03A4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_BDR0__EPDC_SDCE7 0x00DC 0x03A4 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_BDR1__EPDC_BDR1 0x00E0 0x03A8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_BDR1__UART3_DCE_CTS 0x00E0 0x03A8 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_BDR1__UART3_DTE_RTS 0x00E0 0x03A8 0x0750 0x2 0x3
+#define MX6SLL_PAD_EPDC_BDR1__GPIO2_IO06 0x00E0 0x03A8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_BDR1__EPDC_SDCE8 0x00E0 0x03A8 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__EPDC_PWR_CTRL0 0x00E4 0x03AC 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__AUD5_RXC 0x00E4 0x03AC 0x0584 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__LCD_DATA16 0x00E4 0x03AC 0x0718 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__GPIO2_IO07 0x00E4 0x03AC 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__EPDC_PWR_CTRL1 0x00E8 0x03B0 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__AUD5_TXFS 0x00E8 0x03B0 0x0590 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__LCD_DATA17 0x00E8 0x03B0 0x071C 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__GPIO2_IO08 0x00E8 0x03B0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__EPDC_PWR_CTRL2 0x00EC 0x03B4 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__AUD5_TXD 0x00EC 0x03B4 0x0580 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__LCD_DATA18 0x00EC 0x03B4 0x0720 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__GPIO2_IO09 0x00EC 0x03B4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__EPDC_PWR_CTRL3 0x00F0 0x03B8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__AUD5_TXC 0x00F0 0x03B8 0x058C 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__LCD_DATA19 0x00F0 0x03B8 0x0724 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__GPIO2_IO10 0x00F0 0x03B8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__EPDC_PWR_COM 0x00F4 0x03BC 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__LCD_DATA20 0x00F4 0x03BC 0x0728 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x00F4 0x03BC 0x055C 0x4 0x4
+#define MX6SLL_PAD_EPDC_PWR_COM__GPIO2_IO11 0x00F4 0x03BC 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__SD3_RESET 0x00F4 0x03BC 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_IRQ__EPDC_PWR_IRQ 0x00F8 0x03C0 0x0668 0x0 0x1
+#define MX6SLL_PAD_EPDC_PWR_IRQ__LCD_DATA21 0x00F8 0x03C0 0x072C 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_IRQ__USB_OTG2_ID 0x00F8 0x03C0 0x0560 0x4 0x3
+#define MX6SLL_PAD_EPDC_PWR_IRQ__GPIO2_IO12 0x00F8 0x03C0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_IRQ__SD3_VSELECT 0x00F8 0x03C0 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__EPDC_PWR_STAT 0x00FC 0x03C4 0x066C 0x0 0x1
+#define MX6SLL_PAD_EPDC_PWR_STAT__LCD_DATA22 0x00FC 0x03C4 0x0730 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_STAT__ARM_EVENTI 0x00FC 0x03C4 0x0000 0x4 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__GPIO2_IO13 0x00FC 0x03C4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__SD3_WP 0x00FC 0x03C4 0x0794 0x6 0x2
+#define MX6SLL_PAD_EPDC_PWR_WAKE__EPDC_PWR_WAKE 0x0100 0x03C8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__LCD_DATA23 0x0100 0x03C8 0x0734 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_WAKE__ARM_EVENTO 0x0100 0x03C8 0x0000 0x4 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__GPIO2_IO14 0x0100 0x03C8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__SD3_CD_B 0x0100 0x03C8 0x0780 0x6 0x2
+#define MX6SLL_PAD_LCD_CLK__LCD_CLK 0x0104 0x03CC 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_CLK__LCD_WR_RWN 0x0104 0x03CC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_CLK__PWM4_OUT 0x0104 0x03CC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_CLK__GPIO2_IO15 0x0104 0x03CC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_ENABLE__LCD_ENABLE 0x0108 0x03D0 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_ENABLE__LCD_RD_E 0x0108 0x03D0 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_ENABLE__UART2_DCE_RX 0x0108 0x03D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_ENABLE__UART2_DTE_TX 0x0108 0x03D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_ENABLE__GPIO2_IO16 0x0108 0x03D0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_HSYNC__LCD_HSYNC 0x010C 0x03D4 0x06D4 0x0 0x0
+#define MX6SLL_PAD_LCD_HSYNC__LCD_CS 0x010C 0x03D4 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_HSYNC__UART2_DCE_TX 0x010C 0x03D4 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_HSYNC__UART2_DTE_RX 0x010C 0x03D4 0x074C 0x4 0x1
+#define MX6SLL_PAD_LCD_HSYNC__GPIO2_IO17 0x010C 0x03D4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_HSYNC__ARM_TRACE_CLK 0x010C 0x03D4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_VSYNC__LCD_VSYNC 0x0110 0x03D8 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_VSYNC__LCD_RS 0x0110 0x03D8 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_VSYNC__UART2_DCE_RTS 0x0110 0x03D8 0x0748 0x4 0x0
+#define MX6SLL_PAD_LCD_VSYNC__UART2_DTE_CTS 0x0110 0x03D8 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_VSYNC__GPIO2_IO18 0x0110 0x03D8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_VSYNC__ARM_TRACE_CTL 0x0110 0x03D8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_RESET__LCD_RESET 0x0114 0x03DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_RESET__LCD_BUSY 0x0114 0x03DC 0x06D4 0x2 0x1
+#define MX6SLL_PAD_LCD_RESET__UART2_DCE_CTS 0x0114 0x03DC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_RESET__UART2_DTE_RTS 0x0114 0x03DC 0x0748 0x4 0x1
+#define MX6SLL_PAD_LCD_RESET__GPIO2_IO19 0x0114 0x03DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_RESET__CCM_PMIC_READY 0x0114 0x03DC 0x05AC 0x6 0x2
+#define MX6SLL_PAD_LCD_DATA00__LCD_DATA00 0x0118 0x03E0 0x06D8 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA00__ECSPI1_MOSI 0x0118 0x03E0 0x0608 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA00__USB_OTG2_ID 0x0118 0x03E0 0x0560 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA00__PWM1_OUT 0x0118 0x03E0 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA00__UART5_DTR_B 0x0118 0x03E0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA00__GPIO2_IO20 0x0118 0x03E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA00__ARM_TRACE00 0x0118 0x03E0 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA00__SRC_BOOT_CFG00 0x0118 0x03E0 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA01__LCD_DATA01 0x011C 0x03E4 0x06DC 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA01__ECSPI1_MISO 0x011C 0x03E4 0x0604 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA01__USB_OTG1_ID 0x011C 0x03E4 0x055C 0x2 0x3
+#define MX6SLL_PAD_LCD_DATA01__PWM2_OUT 0x011C 0x03E4 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA01__AUD4_RXFS 0x011C 0x03E4 0x0570 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA01__GPIO2_IO21 0x011C 0x03E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA01__ARM_TRACE01 0x011C 0x03E4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA01__SRC_BOOT_CFG01 0x011C 0x03E4 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA02__LCD_DATA02 0x0120 0x03E8 0x06E0 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA02__ECSPI1_SS0 0x0120 0x03E8 0x0614 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA02__EPIT2_OUT 0x0120 0x03E8 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA02__PWM3_OUT 0x0120 0x03E8 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA02__AUD4_RXC 0x0120 0x03E8 0x056C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA02__GPIO2_IO22 0x0120 0x03E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA02__ARM_TRACE02 0x0120 0x03E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA02__SRC_BOOT_CFG02 0x0120 0x03E8 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA03__LCD_DATA03 0x0124 0x03EC 0x06E4 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA03__ECSPI1_SCLK 0x0124 0x03EC 0x05FC 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA03__UART5_DSR_B 0x0124 0x03EC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA03__PWM4_OUT 0x0124 0x03EC 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA03__AUD4_RXD 0x0124 0x03EC 0x0564 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA03__GPIO2_IO23 0x0124 0x03EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA03__ARM_TRACE03 0x0124 0x03EC 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA03__SRC_BOOT_CFG03 0x0124 0x03EC 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA04__LCD_DATA04 0x0128 0x03F0 0x06E8 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA04__ECSPI1_SS1 0x0128 0x03F0 0x060C 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA04__CSI_VSYNC 0x0128 0x03F0 0x05F8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA04__WDOG2_RESET_B_DEB 0x0128 0x03F0 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA04__AUD4_TXC 0x0128 0x03F0 0x0574 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA04__GPIO2_IO24 0x0128 0x03F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA04__ARM_TRACE04 0x0128 0x03F0 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA04__SRC_BOOT_CFG04 0x0128 0x03F0 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA05__LCD_DATA05 0x012C 0x03F4 0x06EC 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA05__ECSPI1_SS2 0x012C 0x03F4 0x0610 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA05__CSI_HSYNC 0x012C 0x03F4 0x05F0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA05__AUD4_TXFS 0x012C 0x03F4 0x0578 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA05__GPIO2_IO25 0x012C 0x03F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA05__ARM_TRACE05 0x012C 0x03F4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA05__SRC_BOOT_CFG05 0x012C 0x03F4 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA06__LCD_DATA06 0x0130 0x03F8 0x06F0 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA06__ECSPI1_SS3 0x0130 0x03F8 0x0618 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA06__CSI_PIXCLK 0x0130 0x03F8 0x05F4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA06__AUD4_TXD 0x0130 0x03F8 0x0568 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA06__GPIO2_IO26 0x0130 0x03F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA06__ARM_TRACE06 0x0130 0x03F8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA06__SRC_BOOT_CFG06 0x0130 0x03F8 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA07__LCD_DATA07 0x0134 0x03FC 0x06F4 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA07__ECSPI1_RDY 0x0134 0x03FC 0x0600 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA07__CSI_MCLK 0x0134 0x03FC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA07__AUDIO_CLK_OUT 0x0134 0x03FC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA07__GPIO2_IO27 0x0134 0x03FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA07__ARM_TRACE07 0x0134 0x03FC 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA07__SRC_BOOT_CFG07 0x0134 0x03FC 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA08__LCD_DATA08 0x0138 0x0400 0x06F8 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA08__KEY_COL0 0x0138 0x0400 0x06A0 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA08__CSI_DATA09 0x0138 0x0400 0x05EC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA08__ECSPI2_SCLK 0x0138 0x0400 0x061C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA08__GPIO2_IO28 0x0138 0x0400 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA08__ARM_TRACE08 0x0138 0x0400 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA08__SRC_BOOT_CFG08 0x0138 0x0400 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA09__LCD_DATA09 0x013C 0x0404 0x06FC 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA09__KEY_ROW0 0x013C 0x0404 0x06C0 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA09__CSI_DATA08 0x013C 0x0404 0x05E8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA09__ECSPI2_MOSI 0x013C 0x0404 0x0624 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA09__GPIO2_IO29 0x013C 0x0404 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA09__ARM_TRACE09 0x013C 0x0404 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA09__SRC_BOOT_CFG09 0x013C 0x0404 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA10__LCD_DATA10 0x0140 0x0408 0x0700 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA10__KEY_COL1 0x0140 0x0408 0x06A4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA10__CSI_DATA07 0x0140 0x0408 0x05E4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA10__ECSPI2_MISO 0x0140 0x0408 0x0620 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA10__GPIO2_IO30 0x0140 0x0408 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA10__ARM_TRACE10 0x0140 0x0408 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA10__SRC_BOOT_CFG10 0x0140 0x0408 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA11__LCD_DATA11 0x0144 0x040C 0x0704 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA11__KEY_ROW1 0x0144 0x040C 0x06C4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA11__CSI_DATA06 0x0144 0x040C 0x05E0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA11__ECSPI2_SS1 0x0144 0x040C 0x062C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA11__GPIO2_IO31 0x0144 0x040C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA11__ARM_TRACE11 0x0144 0x040C 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA11__SRC_BOOT_CFG11 0x0144 0x040C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA12__LCD_DATA12 0x0148 0x0410 0x0708 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA12__KEY_COL2 0x0148 0x0410 0x06A8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA12__CSI_DATA05 0x0148 0x0410 0x05DC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA12__UART5_DCE_RTS 0x0148 0x0410 0x0760 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA12__UART5_DTE_CTS 0x0148 0x0410 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA12__GPIO3_IO00 0x0148 0x0410 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA12__ARM_TRACE12 0x0148 0x0410 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA12__SRC_BOOT_CFG12 0x0148 0x0410 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA13__LCD_DATA13 0x014C 0x0414 0x070C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA13__KEY_ROW2 0x014C 0x0414 0x06C8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA13__CSI_DATA04 0x014C 0x0414 0x05D8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA13__UART5_DCE_CTS 0x014C 0x0414 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA13__UART5_DTE_RTS 0x014C 0x0414 0x0760 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA13__GPIO3_IO01 0x014C 0x0414 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA13__ARM_TRACE13 0x014C 0x0414 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA13__SRC_BOOT_CFG13 0x014C 0x0414 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA14__LCD_DATA14 0x0150 0x0418 0x0710 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA14__KEY_COL3 0x0150 0x0418 0x06AC 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA14__CSI_DATA03 0x0150 0x0418 0x05D4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA14__UART5_DCE_RX 0x0150 0x0418 0x0764 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA14__UART5_DTE_TX 0x0150 0x0418 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA14__GPIO3_IO02 0x0150 0x0418 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA14__ARM_TRACE14 0x0150 0x0418 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA14__SRC_BOOT_CFG14 0x0150 0x0418 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA15__LCD_DATA15 0x0154 0x041C 0x0714 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA15__KEY_ROW3 0x0154 0x041C 0x06CC 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA15__CSI_DATA02 0x0154 0x041C 0x05D0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA15__UART5_DCE_TX 0x0154 0x041C 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA15__UART5_DTE_RX 0x0154 0x041C 0x0764 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA15__GPIO3_IO03 0x0154 0x041C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA15__ARM_TRACE15 0x0154 0x041C 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA15__SRC_BOOT_CFG15 0x0154 0x041C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA16__LCD_DATA16 0x0158 0x0420 0x0718 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA16__KEY_COL4 0x0158 0x0420 0x06B0 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA16__CSI_DATA01 0x0158 0x0420 0x05CC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA16__I2C2_SCL 0x0158 0x0420 0x0684 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA16__GPIO3_IO04 0x0158 0x0420 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA16__SRC_BOOT_CFG24 0x0158 0x0420 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA17__LCD_DATA17 0x015C 0x0424 0x071C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA17__KEY_ROW4 0x015C 0x0424 0x06D0 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA17__CSI_DATA00 0x015C 0x0424 0x05C8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA17__I2C2_SDA 0x015C 0x0424 0x0688 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA17__GPIO3_IO05 0x015C 0x0424 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA17__SRC_BOOT_CFG25 0x015C 0x0424 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA18__LCD_DATA18 0x0160 0x0428 0x0720 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA18__KEY_COL5 0x0160 0x0428 0x0694 0x1 0x2
+#define MX6SLL_PAD_LCD_DATA18__CSI_DATA15 0x0160 0x0428 0x05C4 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA18__GPT_CAPTURE1 0x0160 0x0428 0x0670 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA18__GPIO3_IO06 0x0160 0x0428 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA18__SRC_BOOT_CFG26 0x0160 0x0428 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA19__LCD_DATA19 0x0164 0x042C 0x0724 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA19__KEY_ROW5 0x0164 0x042C 0x06B4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA19__CSI_DATA14 0x0164 0x042C 0x05C0 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA19__GPT_CAPTURE2 0x0164 0x042C 0x0674 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA19__GPIO3_IO07 0x0164 0x042C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA19__SRC_BOOT_CFG27 0x0164 0x042C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA20__LCD_DATA20 0x0168 0x0430 0x0728 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA20__KEY_COL6 0x0168 0x0430 0x0698 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA20__CSI_DATA13 0x0168 0x0430 0x05BC 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA20__GPT_COMPARE1 0x0168 0x0430 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA20__GPIO3_IO08 0x0168 0x0430 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA20__SRC_BOOT_CFG28 0x0168 0x0430 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA21__LCD_DATA21 0x016C 0x0434 0x072C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA21__KEY_ROW6 0x016C 0x0434 0x06B8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA21__CSI_DATA12 0x016C 0x0434 0x05B8 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA21__GPT_COMPARE2 0x016C 0x0434 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA21__GPIO3_IO09 0x016C 0x0434 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA21__SRC_BOOT_CFG29 0x016C 0x0434 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA22__LCD_DATA22 0x0170 0x0438 0x0730 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA22__KEY_COL7 0x0170 0x0438 0x069C 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA22__CSI_DATA11 0x0170 0x0438 0x05B4 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA22__GPT_COMPARE3 0x0170 0x0438 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA22__GPIO3_IO10 0x0170 0x0438 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA22__SRC_BOOT_CFG30 0x0170 0x0438 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA23__LCD_DATA23 0x0174 0x043C 0x0734 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA23__KEY_ROW7 0x0174 0x043C 0x06BC 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA23__CSI_DATA10 0x0174 0x043C 0x05B0 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA23__GPT_CLKIN 0x0174 0x043C 0x0678 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA23__GPIO3_IO11 0x0174 0x043C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA23__SRC_BOOT_CFG31 0x0174 0x043C 0x0000 0x7 0x0
+#define MX6SLL_PAD_AUD_RXFS__AUD3_RXFS 0x0178 0x0440 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXFS__I2C1_SCL 0x0178 0x0440 0x067C 0x1 0x1
+#define MX6SLL_PAD_AUD_RXFS__UART3_DCE_RX 0x0178 0x0440 0x0754 0x2 0x0
+#define MX6SLL_PAD_AUD_RXFS__UART3_DTE_TX 0x0178 0x0440 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXFS__I2C3_SCL 0x0178 0x0440 0x068C 0x4 0x1
+#define MX6SLL_PAD_AUD_RXFS__GPIO1_IO00 0x0178 0x0440 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_RXFS__ECSPI3_SS0 0x0178 0x0440 0x0648 0x6 0x0
+#define MX6SLL_PAD_AUD_RXFS__MBIST_BEND 0x0178 0x0440 0x0000 0x7 0x0
+#define MX6SLL_PAD_AUD_RXC__AUD3_RXC 0x017C 0x0444 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXC__I2C1_SDA 0x017C 0x0444 0x0680 0x1 0x1
+#define MX6SLL_PAD_AUD_RXC__UART3_DCE_TX 0x017C 0x0444 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXC__UART3_DTE_RX 0x017C 0x0444 0x0754 0x2 0x1
+#define MX6SLL_PAD_AUD_RXC__I2C3_SDA 0x017C 0x0444 0x0690 0x4 0x1
+#define MX6SLL_PAD_AUD_RXC__GPIO1_IO01 0x017C 0x0444 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_RXC__ECSPI3_SS1 0x017C 0x0444 0x064C 0x6 0x0
+#define MX6SLL_PAD_AUD_RXD__AUD3_RXD 0x0180 0x0448 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXD__ECSPI3_MOSI 0x0180 0x0448 0x063C 0x1 0x0
+#define MX6SLL_PAD_AUD_RXD__UART4_DCE_RX 0x0180 0x0448 0x075C 0x2 0x0
+#define MX6SLL_PAD_AUD_RXD__UART4_DTE_TX 0x0180 0x0448 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXD__SD1_LCTL 0x0180 0x0448 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_RXD__GPIO1_IO02 0x0180 0x0448 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXC__AUD3_TXC 0x0184 0x044C 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXC__ECSPI3_MISO 0x0184 0x044C 0x0638 0x1 0x0
+#define MX6SLL_PAD_AUD_TXC__UART4_DCE_TX 0x0184 0x044C 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXC__UART4_DTE_RX 0x0184 0x044C 0x075C 0x2 0x1
+#define MX6SLL_PAD_AUD_TXC__SD2_LCTL 0x0184 0x044C 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_TXC__GPIO1_IO03 0x0184 0x044C 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXFS__AUD3_TXFS 0x0188 0x0450 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXFS__PWM3_OUT 0x0188 0x0450 0x0000 0x1 0x0
+#define MX6SLL_PAD_AUD_TXFS__UART4_DCE_RTS 0x0188 0x0450 0x0758 0x2 0x0
+#define MX6SLL_PAD_AUD_TXFS__UART4_DTE_CTS 0x0188 0x0450 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXFS__SD3_LCTL 0x0188 0x0450 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_TXFS__GPIO1_IO04 0x0188 0x0450 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXD__AUD3_TXD 0x018C 0x0454 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXD__ECSPI3_SCLK 0x018C 0x0454 0x0630 0x1 0x0
+#define MX6SLL_PAD_AUD_TXD__UART4_DCE_CTS 0x018C 0x0454 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXD__UART4_DTE_RTS 0x018C 0x0454 0x0758 0x2 0x1
+#define MX6SLL_PAD_AUD_TXD__GPIO1_IO05 0x018C 0x0454 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x0190 0x0458 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_MCLK__PWM4_OUT 0x0190 0x0458 0x0000 0x1 0x0
+#define MX6SLL_PAD_AUD_MCLK__ECSPI3_RDY 0x0190 0x0458 0x0634 0x2 0x0
+#define MX6SLL_PAD_AUD_MCLK__WDOG2_RESET_B_DEB 0x0190 0x0458 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_MCLK__GPIO1_IO06 0x0190 0x0458 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_MCLK__SPDIF_EXT_CLK 0x0190 0x0458 0x073C 0x6 0x1
+#define MX6SLL_PAD_UART1_RXD__UART1_DCE_RX 0x0194 0x045C 0x0744 0x0 0x0
+#define MX6SLL_PAD_UART1_RXD__UART1_DTE_TX 0x0194 0x045C 0x0000 0x0 0x0
+#define MX6SLL_PAD_UART1_RXD__PWM1_OUT 0x0194 0x045C 0x0000 0x1 0x0
+#define MX6SLL_PAD_UART1_RXD__UART4_DCE_RX 0x0194 0x045C 0x075C 0x2 0x4
+#define MX6SLL_PAD_UART1_RXD__UART4_DTE_TX 0x0194 0x045C 0x0000 0x2 0x0
+#define MX6SLL_PAD_UART1_RXD__UART5_DCE_RX 0x0194 0x045C 0x0764 0x4 0x6
+#define MX6SLL_PAD_UART1_RXD__UART5_DTE_TX 0x0194 0x045C 0x0000 0x4 0x0
+#define MX6SLL_PAD_UART1_RXD__GPIO3_IO16 0x0194 0x045C 0x0000 0x5 0x0
+#define MX6SLL_PAD_UART1_TXD__UART1_DCE_TX 0x0198 0x0460 0x0000 0x0 0x0
+#define MX6SLL_PAD_UART1_TXD__UART1_DTE_RX 0x0198 0x0460 0x0744 0x0 0x1
+#define MX6SLL_PAD_UART1_TXD__PWM2_OUT 0x0198 0x0460 0x0000 0x1 0x0
+#define MX6SLL_PAD_UART1_TXD__UART4_DCE_TX 0x0198 0x0460 0x0000 0x2 0x0
+#define MX6SLL_PAD_UART1_TXD__UART4_DTE_RX 0x0198 0x0460 0x075C 0x2 0x5
+#define MX6SLL_PAD_UART1_TXD__UART5_DCE_TX 0x0198 0x0460 0x0000 0x4 0x0
+#define MX6SLL_PAD_UART1_TXD__UART5_DTE_RX 0x0198 0x0460 0x0764 0x4 0x7
+#define MX6SLL_PAD_UART1_TXD__GPIO3_IO17 0x0198 0x0460 0x0000 0x5 0x0
+#define MX6SLL_PAD_UART1_TXD__UART5_DCD_B 0x0198 0x0460 0x0000 0x7 0x0
+#define MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x019C 0x0464 0x067C 0x0 0x0
+#define MX6SLL_PAD_I2C1_SCL__UART1_DCE_RTS 0x019C 0x0464 0x0740 0x1 0x0
+#define MX6SLL_PAD_I2C1_SCL__UART1_DTE_CTS 0x019C 0x0464 0x0000 0x1 0x0
+#define MX6SLL_PAD_I2C1_SCL__ECSPI3_SS2 0x019C 0x0464 0x0640 0x2 0x0
+#define MX6SLL_PAD_I2C1_SCL__SD3_RESET 0x019C 0x0464 0x0000 0x4 0x0
+#define MX6SLL_PAD_I2C1_SCL__GPIO3_IO12 0x019C 0x0464 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C1_SCL__ECSPI1_SS1 0x019C 0x0464 0x060C 0x6 0x0
+#define MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x01A0 0x0468 0x0680 0x0 0x0
+#define MX6SLL_PAD_I2C1_SDA__UART1_DCE_CTS 0x01A0 0x0468 0x0000 0x1 0x0
+#define MX6SLL_PAD_I2C1_SDA__UART1_DTE_RTS 0x01A0 0x0468 0x0740 0x1 0x1
+#define MX6SLL_PAD_I2C1_SDA__ECSPI3_SS3 0x01A0 0x0468 0x0644 0x2 0x0
+#define MX6SLL_PAD_I2C1_SDA__SD3_VSELECT 0x01A0 0x0468 0x0000 0x4 0x0
+#define MX6SLL_PAD_I2C1_SDA__GPIO3_IO13 0x01A0 0x0468 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C1_SDA__ECSPI1_SS2 0x01A0 0x0468 0x0610 0x6 0x0
+#define MX6SLL_PAD_I2C2_SCL__I2C2_SCL 0x01A4 0x046C 0x0684 0x0 0x3
+#define MX6SLL_PAD_I2C2_SCL__AUD4_RXFS 0x01A4 0x046C 0x0570 0x1 0x2
+#define MX6SLL_PAD_I2C2_SCL__SPDIF_IN 0x01A4 0x046C 0x0738 0x2 0x2
+#define MX6SLL_PAD_I2C2_SCL__SD3_WP 0x01A4 0x046C 0x0794 0x4 0x3
+#define MX6SLL_PAD_I2C2_SCL__GPIO3_IO14 0x01A4 0x046C 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C2_SCL__ECSPI1_RDY 0x01A4 0x046C 0x0600 0x6 0x1
+#define MX6SLL_PAD_I2C2_SDA__I2C2_SDA 0x01A8 0x0470 0x0688 0x0 0x3
+#define MX6SLL_PAD_I2C2_SDA__AUD4_RXC 0x01A8 0x0470 0x056C 0x1 0x2
+#define MX6SLL_PAD_I2C2_SDA__SPDIF_OUT 0x01A8 0x0470 0x0000 0x2 0x0
+#define MX6SLL_PAD_I2C2_SDA__SD3_CD_B 0x01A8 0x0470 0x0780 0x4 0x3
+#define MX6SLL_PAD_I2C2_SDA__GPIO3_IO15 0x01A8 0x0470 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x01AC 0x0474 0x05FC 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_SCLK__AUD4_TXD 0x01AC 0x0474 0x0568 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_SCLK__UART5_DCE_RX 0x01AC 0x0474 0x0764 0x2 0x2
+#define MX6SLL_PAD_ECSPI1_SCLK__UART5_DTE_TX 0x01AC 0x0474 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__EPDC_VCOM0 0x01AC 0x0474 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__SD2_RESET 0x01AC 0x0474 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__GPIO4_IO08 0x01AC 0x0474 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__USB_OTG2_OC 0x01AC 0x0474 0x0768 0x6 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x01B0 0x0478 0x0608 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__AUD4_TXC 0x01B0 0x0478 0x0574 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__UART5_DCE_TX 0x01B0 0x0478 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__UART5_DTE_RX 0x01B0 0x0478 0x0764 0x2 0x3
+#define MX6SLL_PAD_ECSPI1_MOSI__EPDC_VCOM1 0x01B0 0x0478 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__SD2_VSELECT 0x01B0 0x0478 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__GPIO4_IO09 0x01B0 0x0478 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x01B4 0x047C 0x0604 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_MISO__AUD4_TXFS 0x01B4 0x047C 0x0578 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_MISO__UART5_DCE_RTS 0x01B4 0x047C 0x0760 0x2 0x2
+#define MX6SLL_PAD_ECSPI1_MISO__UART5_DTE_CTS 0x01B4 0x047C 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__EPDC_BDR0 0x01B4 0x047C 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__SD2_WP 0x01B4 0x047C 0x077C 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__GPIO4_IO10 0x01B4 0x047C 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__ECSPI1_SS0 0x01B8 0x0480 0x0614 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_SS0__AUD4_RXD 0x01B8 0x0480 0x0564 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_SS0__UART5_DCE_CTS 0x01B8 0x0480 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__UART5_DTE_RTS 0x01B8 0x0480 0x0760 0x2 0x3
+#define MX6SLL_PAD_ECSPI1_SS0__EPDC_BDR1 0x01B8 0x0480 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__SD2_CD_B 0x01B8 0x0480 0x0778 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__GPIO4_IO11 0x01B8 0x0480 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__USB_OTG2_PWR 0x01B8 0x0480 0x0000 0x6 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__ECSPI2_SCLK 0x01BC 0x0484 0x061C 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_SCLK__SPDIF_EXT_CLK 0x01BC 0x0484 0x073C 0x1 0x2
+#define MX6SLL_PAD_ECSPI2_SCLK__UART3_DCE_RX 0x01BC 0x0484 0x0754 0x2 0x2
+#define MX6SLL_PAD_ECSPI2_SCLK__UART3_DTE_TX 0x01BC 0x0484 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__CSI_PIXCLK 0x01BC 0x0484 0x05F4 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_SCLK__SD1_RESET 0x01BC 0x0484 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__GPIO4_IO12 0x01BC 0x0484 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__USB_OTG2_OC 0x01BC 0x0484 0x0768 0x6 0x2
+#define MX6SLL_PAD_ECSPI2_MOSI__ECSPI2_MOSI 0x01C0 0x0488 0x0624 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_MOSI__SDMA_EXT_EVENT1 0x01C0 0x0488 0x0000 0x1 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__UART3_DCE_TX 0x01C0 0x0488 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__UART3_DTE_RX 0x01C0 0x0488 0x0754 0x2 0x3
+#define MX6SLL_PAD_ECSPI2_MOSI__CSI_HSYNC 0x01C0 0x0488 0x05F0 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_MOSI__SD1_VSELECT 0x01C0 0x0488 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__GPIO4_IO13 0x01C0 0x0488 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__ECSPI2_MISO 0x01C4 0x048C 0x0620 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_MISO__SDMA_EXT_EVENT0 0x01C4 0x048C 0x0000 0x1 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__UART3_DCE_RTS 0x01C4 0x048C 0x0750 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__UART3_DTE_CTS 0x01C4 0x048C 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__CSI_MCLK 0x01C4 0x048C 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__SD1_WP 0x01C4 0x048C 0x0774 0x4 0x2
+#define MX6SLL_PAD_ECSPI2_MISO__GPIO4_IO14 0x01C4 0x048C 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__USB_OTG1_OC 0x01C4 0x048C 0x076C 0x6 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__ECSPI2_SS0 0x01C8 0x0490 0x0628 0x0 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__ECSPI1_SS3 0x01C8 0x0490 0x0618 0x1 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__UART3_DCE_CTS 0x01C8 0x0490 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__UART3_DTE_RTS 0x01C8 0x0490 0x0750 0x2 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__CSI_VSYNC 0x01C8 0x0490 0x05F8 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__SD1_CD_B 0x01C8 0x0490 0x0770 0x4 0x2
+#define MX6SLL_PAD_ECSPI2_SS0__GPIO4_IO15 0x01C8 0x0490 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__USB_OTG1_PWR 0x01C8 0x0490 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD1_CLK__SD1_CLK 0x01CC 0x0494 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_CLK__KEY_COL0 0x01CC 0x0494 0x06A0 0x2 0x2
+#define MX6SLL_PAD_SD1_CLK__EPDC_SDCE4 0x01CC 0x0494 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_CLK__GPIO5_IO15 0x01CC 0x0494 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_CMD__SD1_CMD 0x01D0 0x0498 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_CMD__KEY_ROW0 0x01D0 0x0498 0x06C0 0x2 0x2
+#define MX6SLL_PAD_SD1_CMD__EPDC_SDCE5 0x01D0 0x0498 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_CMD__GPIO5_IO14 0x01D0 0x0498 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x01D4 0x049C 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA0__KEY_COL1 0x01D4 0x049C 0x06A4 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA0__EPDC_SDCE6 0x01D4 0x049C 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA0__GPIO5_IO11 0x01D4 0x049C 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x01D8 0x04A0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA1__KEY_ROW1 0x01D8 0x04A0 0x06C4 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA1__EPDC_SDCE7 0x01D8 0x04A0 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA1__GPIO5_IO08 0x01D8 0x04A0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x01DC 0x04A4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA2__KEY_COL2 0x01DC 0x04A4 0x06A8 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA2__EPDC_SDCE8 0x01DC 0x04A4 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA2__GPIO5_IO13 0x01DC 0x04A4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x01E0 0x04A8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA3__KEY_ROW2 0x01E0 0x04A8 0x06C8 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA3__EPDC_SDCE9 0x01E0 0x04A8 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA3__GPIO5_IO06 0x01E0 0x04A8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA4__SD1_DATA4 0x01E4 0x04AC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA4__KEY_COL3 0x01E4 0x04AC 0x06AC 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA4__EPDC_SDCLK_N 0x01E4 0x04AC 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA4__UART4_DCE_RX 0x01E4 0x04AC 0x075C 0x4 0x6
+#define MX6SLL_PAD_SD1_DATA4__UART4_DTE_TX 0x01E4 0x04AC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA4__GPIO5_IO12 0x01E4 0x04AC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA5__SD1_DATA5 0x01E8 0x04B0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA5__KEY_ROW3 0x01E8 0x04B0 0x06CC 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA5__EPDC_SDOED 0x01E8 0x04B0 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA5__UART4_DCE_TX 0x01E8 0x04B0 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA5__UART4_DTE_RX 0x01E8 0x04B0 0x075C 0x4 0x7
+#define MX6SLL_PAD_SD1_DATA5__GPIO5_IO09 0x01E8 0x04B0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA6__SD1_DATA6 0x01EC 0x04B4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA6__KEY_COL4 0x01EC 0x04B4 0x06B0 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA6__EPDC_SDOEZ 0x01EC 0x04B4 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA6__UART4_DCE_RTS 0x01EC 0x04B4 0x0758 0x4 0x4
+#define MX6SLL_PAD_SD1_DATA6__UART4_DTE_CTS 0x01EC 0x04B4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA6__GPIO5_IO07 0x01EC 0x04B4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA7__SD1_DATA7 0x01F0 0x04B8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA7__KEY_ROW4 0x01F0 0x04B8 0x06D0 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA7__CCM_PMIC_READY 0x01F0 0x04B8 0x05AC 0x3 0x3
+#define MX6SLL_PAD_SD1_DATA7__UART4_DCE_CTS 0x01F0 0x04B8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA7__UART4_DTE_RTS 0x01F0 0x04B8 0x0758 0x4 0x5
+#define MX6SLL_PAD_SD1_DATA7__GPIO5_IO10 0x01F0 0x04B8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_RESET__SD2_RESET 0x01F4 0x04BC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_RESET__WDOG2_B 0x01F4 0x04BC 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_RESET__SPDIF_OUT 0x01F4 0x04BC 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD2_RESET__CSI_MCLK 0x01F4 0x04BC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_RESET__GPIO4_IO27 0x01F4 0x04BC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_CLK__SD2_CLK 0x01F8 0x04C0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_CLK__AUD4_RXFS 0x01F8 0x04C0 0x0570 0x1 0x1
+#define MX6SLL_PAD_SD2_CLK__ECSPI3_SCLK 0x01F8 0x04C0 0x0630 0x2 0x1
+#define MX6SLL_PAD_SD2_CLK__CSI_DATA00 0x01F8 0x04C0 0x05C8 0x3 0x1
+#define MX6SLL_PAD_SD2_CLK__GPIO5_IO05 0x01F8 0x04C0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_CMD__SD2_CMD 0x01FC 0x04C4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_CMD__AUD4_RXC 0x01FC 0x04C4 0x056C 0x1 0x1
+#define MX6SLL_PAD_SD2_CMD__ECSPI3_SS0 0x01FC 0x04C4 0x0648 0x2 0x1
+#define MX6SLL_PAD_SD2_CMD__CSI_DATA01 0x01FC 0x04C4 0x05CC 0x3 0x1
+#define MX6SLL_PAD_SD2_CMD__EPIT1_OUT 0x01FC 0x04C4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_CMD__GPIO5_IO04 0x01FC 0x04C4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x0200 0x04C8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA0__AUD4_RXD 0x0200 0x04C8 0x0564 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA0__ECSPI3_MOSI 0x0200 0x04C8 0x063C 0x2 0x1
+#define MX6SLL_PAD_SD2_DATA0__CSI_DATA02 0x0200 0x04C8 0x05D0 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA0__UART5_DCE_RTS 0x0200 0x04C8 0x0760 0x4 0x4
+#define MX6SLL_PAD_SD2_DATA0__UART5_DTE_CTS 0x0200 0x04C8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA0__GPIO5_IO01 0x0200 0x04C8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x0204 0x04CC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA1__AUD4_TXC 0x0204 0x04CC 0x0574 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA1__ECSPI3_MISO 0x0204 0x04CC 0x0638 0x2 0x1
+#define MX6SLL_PAD_SD2_DATA1__CSI_DATA03 0x0204 0x04CC 0x05D4 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA1__UART5_DCE_CTS 0x0204 0x04CC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA1__UART5_DTE_RTS 0x0204 0x04CC 0x0760 0x4 0x5
+#define MX6SLL_PAD_SD2_DATA1__GPIO4_IO30 0x0204 0x04CC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x0208 0x04D0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA2__AUD4_TXFS 0x0208 0x04D0 0x0578 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA2__CSI_DATA04 0x0208 0x04D0 0x05D8 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA2__UART5_DCE_RX 0x0208 0x04D0 0x0764 0x4 0x4
+#define MX6SLL_PAD_SD2_DATA2__UART5_DTE_TX 0x0208 0x04D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA2__GPIO5_IO03 0x0208 0x04D0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x020C 0x04D4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA3__AUD4_TXD 0x020C 0x04D4 0x0568 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA3__CSI_DATA05 0x020C 0x04D4 0x05DC 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA3__UART5_DCE_TX 0x020C 0x04D4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA3__UART5_DTE_RX 0x020C 0x04D4 0x0764 0x4 0x5
+#define MX6SLL_PAD_SD2_DATA3__GPIO4_IO28 0x020C 0x04D4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x0210 0x04D8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA4__SD3_DATA4 0x0210 0x04D8 0x0784 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA4__UART2_DCE_RX 0x0210 0x04D8 0x074C 0x2 0x2
+#define MX6SLL_PAD_SD2_DATA4__UART2_DTE_TX 0x0210 0x04D8 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA4__CSI_DATA06 0x0210 0x04D8 0x05E0 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA4__SPDIF_OUT 0x0210 0x04D8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA4__GPIO5_IO02 0x0210 0x04D8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x0214 0x04DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA5__SD3_DATA5 0x0214 0x04DC 0x0788 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA5__UART2_DCE_TX 0x0214 0x04DC 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA5__UART2_DTE_RX 0x0214 0x04DC 0x074C 0x2 0x3
+#define MX6SLL_PAD_SD2_DATA5__CSI_DATA07 0x0214 0x04DC 0x05E4 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA5__SPDIF_IN 0x0214 0x04DC 0x0738 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA5__GPIO4_IO31 0x0214 0x04DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x0218 0x04E0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA6__SD3_DATA6 0x0218 0x04E0 0x078C 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA6__UART2_DCE_RTS 0x0218 0x04E0 0x0748 0x2 0x2
+#define MX6SLL_PAD_SD2_DATA6__UART2_DTE_CTS 0x0218 0x04E0 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA6__CSI_DATA08 0x0218 0x04E0 0x05E8 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA6__SD2_WP 0x0218 0x04E0 0x077C 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA6__GPIO4_IO29 0x0218 0x04E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x021C 0x04E4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA7__SD3_DATA7 0x021C 0x04E4 0x0790 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA7__UART2_DCE_CTS 0x021C 0x04E4 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA7__UART2_DTE_RTS 0x021C 0x04E4 0x0748 0x2 0x3
+#define MX6SLL_PAD_SD2_DATA7__CSI_DATA09 0x021C 0x04E4 0x05EC 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA7__SD2_CD_B 0x021C 0x04E4 0x0778 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA7__GPIO5_IO00 0x021C 0x04E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CLK__SD3_CLK 0x0220 0x04E8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_CLK__AUD5_RXFS 0x0220 0x04E8 0x0588 0x1 0x0
+#define MX6SLL_PAD_SD3_CLK__KEY_COL5 0x0220 0x04E8 0x0694 0x2 0x0
+#define MX6SLL_PAD_SD3_CLK__CSI_DATA10 0x0220 0x04E8 0x05B0 0x3 0x0
+#define MX6SLL_PAD_SD3_CLK__WDOG1_RESET_B_DEB 0x0220 0x04E8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_CLK__GPIO5_IO18 0x0220 0x04E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CLK__USB_OTG1_PWR 0x0220 0x04E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_CMD__SD3_CMD 0x0224 0x04EC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_CMD__AUD5_RXC 0x0224 0x04EC 0x0584 0x1 0x0
+#define MX6SLL_PAD_SD3_CMD__KEY_ROW5 0x0224 0x04EC 0x06B4 0x2 0x0
+#define MX6SLL_PAD_SD3_CMD__CSI_DATA11 0x0224 0x04EC 0x05B4 0x3 0x0
+#define MX6SLL_PAD_SD3_CMD__USB_OTG2_ID 0x0224 0x04EC 0x0560 0x4 0x1
+#define MX6SLL_PAD_SD3_CMD__GPIO5_IO21 0x0224 0x04EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CMD__USB_OTG2_PWR 0x0224 0x04EC 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x0228 0x04F0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA0__AUD5_RXD 0x0228 0x04F0 0x057C 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA0__KEY_COL6 0x0228 0x04F0 0x0698 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA0__CSI_DATA12 0x0228 0x04F0 0x05B8 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA0__USB_OTG1_ID 0x0228 0x04F0 0x055C 0x4 0x1
+#define MX6SLL_PAD_SD3_DATA0__GPIO5_IO19 0x0228 0x04F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x022C 0x04F4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA1__AUD5_TXC 0x022C 0x04F4 0x058C 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA1__KEY_ROW6 0x022C 0x04F4 0x06B8 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA1__CSI_DATA13 0x022C 0x04F4 0x05BC 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA1__SD1_VSELECT 0x022C 0x04F4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA1__GPIO5_IO20 0x022C 0x04F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA1__JTAG_DE_B 0x022C 0x04F4 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x0230 0x04F8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA2__AUD5_TXFS 0x0230 0x04F8 0x0590 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA2__KEY_COL7 0x0230 0x04F8 0x069C 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA2__CSI_DATA14 0x0230 0x04F8 0x05C0 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA2__EPIT1_OUT 0x0230 0x04F8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA2__GPIO5_IO16 0x0230 0x04F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA2__USB_OTG2_OC 0x0230 0x04F8 0x0768 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x0234 0x04FC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA3__AUD5_TXD 0x0234 0x04FC 0x0580 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA3__KEY_ROW7 0x0234 0x04FC 0x06BC 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA3__CSI_DATA15 0x0234 0x04FC 0x05C4 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA3__EPIT2_OUT 0x0234 0x04FC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA3__GPIO5_IO17 0x0234 0x04FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA3__USB_OTG1_OC 0x0234 0x04FC 0x076C 0x6 0x0
+#define MX6SLL_PAD_GPIO4_IO20__SD1_STROBE 0x0238 0x0500 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO20__AUD6_RXFS 0x0238 0x0500 0x05A0 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO20__ECSPI4_SS0 0x0238 0x0500 0x065C 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO20__GPT_CAPTURE1 0x0238 0x0500 0x0670 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO20__GPIO4_IO20 0x0238 0x0500 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x023C 0x0504 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO21__AUD6_RXC 0x023C 0x0504 0x059C 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO21__ECSPI4_SCLK 0x023C 0x0504 0x0650 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO21__GPT_CAPTURE2 0x023C 0x0504 0x0674 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO21__GPIO4_IO21 0x023C 0x0504 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO19__SD3_STROBE 0x0240 0x0508 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO19__AUD6_RXD 0x0240 0x0508 0x0594 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO19__ECSPI4_MOSI 0x0240 0x0508 0x0658 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO19__GPT_COMPARE1 0x0240 0x0508 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO19__GPIO4_IO19 0x0240 0x0508 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO25__AUD6_TXC 0x0244 0x050C 0x05A4 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO25__ECSPI4_MISO 0x0244 0x050C 0x0654 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO25__GPT_COMPARE2 0x0244 0x050C 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO25__GPIO4_IO25 0x0244 0x050C 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO18__AUD6_TXFS 0x0248 0x0510 0x05A8 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO18__ECSPI4_SS1 0x0248 0x0510 0x0660 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO18__GPT_COMPARE3 0x0248 0x0510 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO18__GPIO4_IO18 0x0248 0x0510 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO24__AUD6_TXD 0x024C 0x0514 0x0598 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO24__ECSPI4_SS2 0x024C 0x0514 0x0664 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO24__GPT_CLKIN 0x024C 0x0514 0x0678 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x024C 0x0514 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO23__AUDIO_CLK_OUT 0x0250 0x0518 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO23__SD1_RESET 0x0250 0x0518 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO23__SD3_RESET 0x0250 0x0518 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO23__GPIO4_IO23 0x0250 0x0518 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO17__USB_OTG1_ID 0x0254 0x051C 0x055C 0x2 0x2
+#define MX6SLL_PAD_GPIO4_IO17__SD1_VSELECT 0x0254 0x051C 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO17__SD3_VSELECT 0x0254 0x051C 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO17__GPIO4_IO17 0x0254 0x051C 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SPDIF_IN 0x0258 0x0520 0x0738 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SD1_WP 0x0258 0x0520 0x0774 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SD3_WP 0x0258 0x0520 0x0794 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO22__GPIO4_IO22 0x0258 0x0520 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SPDIF_OUT 0x025C 0x0524 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SD1_CD_B 0x025C 0x0524 0x0770 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SD3_CD_B 0x025C 0x0524 0x0780 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO16__GPIO4_IO16 0x025C 0x0524 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO26__WDOG1_B 0x0260 0x0528 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO26__PWM4_OUT 0x0260 0x0528 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO26__CCM_PMIC_READY 0x0260 0x0528 0x05AC 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO26__GPIO4_IO26 0x0260 0x0528 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO26__SPDIF_EXT_CLK 0x0260 0x0528 0x073C 0x6 0x0
+
+#endif /* __DTS_IMX6SLL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
new file mode 100644
index 0000000..8eb9b7a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sll.dtsi
@@ -0,0 +1,854 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/clock/imx6sll-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "imx6sll-pinfunc.h"
+#include "skeleton.dtsi"
+
+/ {
+ aliases {
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
+ gpio4 = &gpio5;
+ gpio5 = &gpio6;
+ i2c0 = &i2c1;
+ i2c1 = &i2c2;
+ i2c2 = &i2c3;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ serial4 = &uart5;
+ spi0 = &ecspi1;
+ spi1 = &ecspi2;
+ spi3 = &ecspi3;
+ spi4 = &ecspi4;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ operating-points = <
+ /* kHz uV */
+ 996000 1225000
+ 792000 1175000
+ 396000 1075000
+ 198000 975000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC-PU uV */
+ 996000 1225000
+ 792000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+ clock-latency = <61036>; /* two CLK32 periods */
+ fsl,low-power-run;
+ clocks = <&clks IMX6SLL_CLK_ARM>,
+ <&clks IMX6SLL_CLK_PLL2_PFD2>,
+ <&clks IMX6SLL_CLK_STEP>,
+ <&clks IMX6SLL_CLK_PLL1_SW>,
+ <&clks IMX6SLL_CLK_PLL1_SYS>,
+ <&clks IMX6SLL_CLK_PLL1>,
+ <&clks IMX6SLL_PLL1_BYPASS>,
+ <&clks IMX6SLL_PLL1_BYPASS_SRC>;
+ clock-names = "arm", "pll2_pfd2_396m", "step",
+ "pll1_sw", "pll1_sys", "pll1", "pll1_bypass",
+ "pll1_bypass_src";
+ };
+ };
+
+ intc: interrupt-controller@00a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ interrupt-parent = <&intc>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil: clock@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "ckil";
+ };
+
+ osc: clock@1 {
+ compatible = "fixed-clock";
+ reg = <1>;
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc";
+ };
+
+ ipp_di0: clock@2 {
+ compatible = "fixed-clock";
+ reg = <2>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di0";
+ };
+
+ ipp_di1: clock@3 {
+ compatible = "fixed-clock";
+ reg = <3>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di1";
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gpc>;
+ ranges;
+
+ ocram: sram@00900000 {
+ compatible = "mmio-sram";
+ reg = <0x00905000 0x20000>;
+ };
+
+ L2: l2-cache@00a02000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x00a02000 0x1000>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ cache-unified;
+ cache-level = <2>;
+ arm,tag-latency = <4 2 3>;
+ arm,data-latency = <4 2 3>;
+ };
+
+ aips1: aips-bus@02000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x100000>;
+ ranges;
+
+ spba: spba-bus@02000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x40000>;
+ ranges;
+
+ spdif: spdif@02004000 {
+ compatible = "fsl,imx6sl-spdif", "fsl,imx35-spdif";
+ reg = <0x02004000 0x4000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 14 18 0>, <&sdma 15 18 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_SPDIF_GCLK>,
+ <&clks IMX6SLL_CLK_OSC>,
+ <&clks IMX6SLL_CLK_SPDIF>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_IPG>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_SPBA>;
+ clock-names = "core", "rxtx0",
+ "rxtx1", "rxtx2",
+ "rxtx3", "rxtx4",
+ "rxtx5", "rxtx6",
+ "rxtx7", "dma";
+ status = "disabled";
+ };
+
+ ecspi1: ecspi@02008000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02008000 0x4000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI1>,
+ <&clks IMX6SLL_CLK_ECSPI1>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi2: ecspi@0200c000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x0200c000 0x4000>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI2>,
+ <&clks IMX6SLL_CLK_ECSPI2>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi3: ecspi@02010000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02010000 0x4000>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI3>,
+ <&clks IMX6SLL_CLK_ECSPI3>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi4: ecspi@02014000 {
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02014000 0x4000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_ECSPI4>,
+ <&clks IMX6SLL_CLK_ECSPI4>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart4: serial@02018000 {
+ compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02018000 0x4000>;
+ interrupts =<GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART4_IPG>,
+ <&clks IMX6SLL_CLK_UART4_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart1: serial@02020000 {
+ compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02020000 0x4000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART1_IPG>,
+ <&clks IMX6SLL_CLK_UART1_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart2: serial@02024000 {
+ compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02024000 0x4000>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART2_IPG>,
+ <&clks IMX6SLL_CLK_UART2_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ssi1: ssi@02028000 {
+ compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
+ reg = <0x02028000 0x4000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 37 22 0>, <&sdma 38 22 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ clocks = <&clks IMX6SLL_CLK_SSI1_IPG>,
+ <&clks IMX6SLL_CLK_SSI1>;
+ clock-names = "ipg", "baud";
+ status = "disabled";
+ };
+
+ ssi2: ssi2@0202c000 {
+ compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
+ reg = <0x0202c000 0x4000>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 41 22 0>, <&sdma 42 22 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ clocks = <&clks IMX6SLL_CLK_SSI2_IPG>,
+ <&clks IMX6SLL_CLK_SSI2>;
+ clock-names = "ipg", "baud";
+ status = "disabled";
+ };
+
+ ssi3: ssi@02030000 {
+ compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
+ reg = <0x02030000 0x4000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 45 22 0>, <&sdma 46 22 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ clocks = <&clks IMX6SLL_CLK_SSI3_IPG>,
+ <&clks IMX6SLL_CLK_SSI3>;
+ clock-names = "ipg", "baud";
+ status = "disabled";
+ };
+
+ uart3: serial@02034000 {
+ compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02034000 0x4000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+ dma-name = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART3_IPG>,
+ <&clks IMX6SLL_CLK_UART3_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+ };
+
+ pwm1: pwm@02080000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x02080000 0x4000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM1>,
+ <&clks IMX6SLL_CLK_PWM1>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm2: pwm@02084000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x02084000 0x4000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM2>,
+ <&clks IMX6SLL_CLK_PWM2>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm3: pwm@02088000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x02088000 0x4000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM3>,
+ <&clks IMX6SLL_CLK_PWM3>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm4: pwm@0208c000 {
+ compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+ reg = <0x0208c000 0x4000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_PWM4>,
+ <&clks IMX6SLL_CLK_PWM4>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ gpt1: gpt@02098000 {
+ compatible = "fsl,imx6sll-gpt";
+ reg = <0x02098000 0x4000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_GPT_BUS>,
+ <&clks IMX6SLL_CLK_GPT_SERIAL>;
+ clock-names = "ipg", "per";
+ };
+
+ gpio1: gpio@0209c000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x0209c000 0x4000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@020a0000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020a0000 0x4000>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@020a4000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020a4000 0x4000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio@020a8000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020a8000 0x4000>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio5: gpio@020ac000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020ac000 0x4000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio6: gpio@020b0000 {
+ compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+ reg = <0x020b0000 0x4000>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ kpp: kpp@020b8000 {
+ compatible = "fsl,imx6sll-kpp", "fsl,imx21-kpp";
+ reg = <0x020b8000 0x4000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_KPP>;
+ status = "disabled";
+ };
+
+ wdog1: wdog@020bc000 {
+ compatible = "fsl,imx6sll-wdt", "fsl,imx21-wdt";
+ reg = <0x020bc000 0x4000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_WDOG1>;
+ };
+
+ wdog2: wdog@020c0000 {
+ compatible = "fsl,imx6sll-wdt", "fsl,imx21-wdt";
+ reg = <0x020c0000 0x4000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_WDOG2>;
+ status = "disabled";
+ };
+
+ clks: ccm@020c4000 {
+ compatible = "fsl,imx6sll-ccm";
+ reg = <0x020c4000 0x4000>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ #clock-cells = <1>;
+ clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
+ clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+ };
+
+ anatop: anatop@020c8000 {
+ compatible = "fsl,imx6sll-anatop",
+ "fsl,imx6q-anatop",
+ "syscon", "simple-bus";
+ reg = <0x020c8000 0x4000>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+
+ reg_3p0: regulator-3p0@120 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd3p0";
+ regulator-min-microvolt = <2625000>;
+ regulator-max-microvolt = <3400000>;
+ anatop-reg-offset = <0x120>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <0>;
+ anatop-min-voltage = <2625000>;
+ anatop-max-voltage = <3400000>;
+ anatop-enable-bit = <0>;
+ };
+ };
+
+ tempmon: tempmon {
+ compatible = "fsl,imx6sll-tempmon", "fsl,imx6sx-tempmon";
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,tempmon = <&anatop>;
+ fsl,tempmon-data = <&ocotp>;
+ clocks = <&clks IMX6SLL_CLK_PLL3_USB_OTG>;
+ status = "disabled";
+ };
+
+ usbphy1: usbphy@020c9000 {
+ compatible = "fsl,imx6sll-usbphy", "fsl,imx6ul-usbphy",
+ "fsl,imx23-usbphy";
+ reg = <0x020c9000 0x1000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBPHY1>;
+ phy-3p0-supply = <®_3p0>;
+ fsl,anatop = <&anatop>;
+ };
+
+ usbphy2: usbphy@020ca000 {
+ compatible = "fsl,imx6sll-usbphy", "fsl,imx6ul-usbphy",
+ "fsl,imx23-usbphy";
+ reg = <0x020ca000 0x1000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBPHY2>;
+ phy-reg_3p0-supply = <®_3p0>;
+ fsl,anatop = <&anatop>;
+ };
+
+ snvs: snvs@020cc000 {
+ compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
+ reg = <0x020cc000 0x4000>;
+
+ snvs_rtc: snvs-rtc-lp {
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ regmap = <&snvs>;
+ offset = <0x34>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ snvs_poweroff: snvs-poweroff {
+ compatible = "syscon-poweroff";
+ regmap = <&snvs>;
+ offset = <0x38>;
+ mask = <0x61>;
+ };
+
+ snvs_pwrkey: snvs-powerkey {
+ compatible = "fsl,sec-v4.0-pwrkey";
+ regmap = <&snvs>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ linux,keycode = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
+
+ epit1: epit@020d0000 {
+ reg = <0x020d0000 0x4000>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ epit2: epit@020d4000 {
+ reg = <0x020d4000 0x4000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ src: src@020d8000 {
+ compatible = "fsl,imx6sll-src", "fsl,imx51-src";
+ reg = <0x020d8000 0x4000>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ #reset-cells = <1>;
+ };
+
+ gpc: gpc@020dc000 {
+ compatible = "fsl,imx6sll-gpc", "fsl,imx6q-gpc";
+ reg = <0x020dc000 0x4000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&intc>;
+ fsl,mf-mix-wakeup-irq = <0x7c00000 0x7d00 0x0 0x1400640>;
+ };
+
+ iomuxc: iomuxc@020e0000 {
+ compatible = "fsl,imx6sll-iomuxc";
+ reg = <0x020e0000 0x4000>;
+ };
+
+ gpr: iomuxc-gpr@020e4000 {
+ compatible = "fsl,imx6sll-iomuxc-gpr",
+ "fsl,imx6q-iomuxc-gpr", "syscon";
+ reg = <0x020e4000 0x4000>;
+ };
+
+ csi: csi@020e8000 {
+ compatible = "fsl,imx6sll-csi", "fsl,imx6s-csi";
+ reg = <0x020e8000 0x4000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_CSI>,
+ <&clks IMX6SLL_CLK_DUMMY>;
+ clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+ status = "disabled";
+ };
+
+ sdma: sdma@020ec000 {
+ compatible = "fsl,imx6sll-sdma", "fsl,imx35-sdma";
+ reg = <0x020ec000 0x4000>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_SDMA>,
+ <&clks IMX6SLL_CLK_SDMA>;
+ clock-names = "ipg", "ahb";
+ #dma-cells = <3>;
+ iram = <&ocram>;
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
+ };
+
+ pxp: pxp@020f0000 {
+ compatible = "fsl,imx6ull-pxp-dma", "fsl,imx7d-pxp-dma";
+ reg = <0x020f0000 0x4000>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DUMMY>,
+ <&clks IMX6SLL_CLK_PXP>;
+ clock-names = "pxp_ipg", "pxp_axi";
+ status = "disabled";
+ };
+
+ lcdif: lcdif@020f8000 {
+ compatible = "fsl,imx6sll-lcdif", "fsl,imx28-lcdif";
+ reg = <0x020f8000 0x4000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_LCDIF_PIX>,
+ <&clks IMX6SLL_CLK_LCDIF_APB>,
+ <&clks IMX6SLL_CLK_DUMMY>;
+ clock-names = "pix", "axi", "disp_axi";
+ status = "disabled";
+ };
+
+ dcp: dcp@020fc000 {
+ compatible = "fsl,imx6sl-dcp";
+ reg = <0x020fc000 0x4000>;
+ interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DCP>;
+ clock-names = "dcp";
+ };
+ };
+
+ aips2: aips-bus@02100000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02100000 0x100000>;
+ ranges;
+
+ usbotg1: usb@02184000 {
+ compatible = "fsl,imx6sll-usb", "fsl,imx6ul-usb",
+ "fsl,imx27-usb";
+ reg = <0x02184000 0x200>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc 0>;
+ fsl,anatop = <&anatop>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ status = "disabled";
+ };
+
+ usbotg2: usb@02184200 {
+ compatible = "fsl,imx6sll-usb", "fsl,imx6ul-usb",
+ "fsl,imx27-usb";
+ reg = <0x02184200 0x200>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy2>;
+ fsl,usbmisc = <&usbmisc 1>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ status = "disabled";
+ };
+
+ usbmisc: usbmisc@02184800 {
+ #index-cells = <1>;
+ compatible = "fsl,imx6sll-usbmisc", "fsl,imx6ul-usbmisc",
+ "fsl,imx6q-usbmisc";
+ reg = <0x02184800 0x200>;
+ };
+
+ usdhc1: usdhc@02190000 {
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+ reg = <0x02190000 0x4000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USDHC1>,
+ <&clks IMX6SLL_CLK_USDHC1>,
+ <&clks IMX6SLL_CLK_USDHC1>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
+ status = "disabled";
+ };
+
+ usdhc2: usdhc@02194000 {
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+ reg = <0x02194000 0x4000>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USDHC2>,
+ <&clks IMX6SLL_CLK_USDHC2>,
+ <&clks IMX6SLL_CLK_USDHC2>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
+ status = "disabled";
+ };
+
+ usdhc3: usdhc@02198000 {
+ compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+ reg = <0x02198000 0x4000>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USDHC3>,
+ <&clks IMX6SLL_CLK_USDHC3>,
+ <&clks IMX6SLL_CLK_USDHC3>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ fsl,tuning-step = <2>;
+ fsl,tuning-start-tap = <20>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@021a0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fs,imx6sll-i2c", "fsl,imx21-i2c";
+ reg = <0x021a0000 0x4000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_I2C1>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@021a4000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sll-i2c", "fsl,imx21-i2c";
+ reg = <0x021a4000 0x4000>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_I2C2>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@021a8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sll-i2c", "fsl,imx21-i2c";
+ reg = <0x021a8000 0x4000>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_I2C3>;
+ status = "disabled";
+ };
+
+ romcp@021ac000 {
+ compatible = "fsl,imx6sll-romcp", "syscon";
+ reg = <0x021ac000 0x4000>;
+ };
+
+ mmdc: mmdc@021b0000 {
+ compatible = "fsl,imx6sll-mmdc", "fsl,imx6q-mmdc";
+ reg = <0x021b0000 0x4000>;
+ };
+
+ rngb: rngb@021b4000 {
+ compatible = "fsl,imx6sl-rng", "fsl,imx-rng", "imx-rng";
+ reg = <0x021b4000 0x4000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_DUMMY>;
+ };
+
+ ocotp: ocotp-ctrl@021bc000 {
+ compatible = "fsl,imx6sll-ocotp", "syscon";
+ reg = <0x021bc000 0x4000>;
+ clocks = <&clks IMX6SLL_CLK_OCOTP>;
+ };
+
+ csu: csu@021c0000 {
+ compatible = "fsl,imx6sll-csu";
+ reg = <0x021c0000 0x4000>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ snvs_gpr: snvs-gpr@0x021c4000 {
+ compatible = "fsl, imx6sll-snvs-gpr";
+ reg = <0x021c4000 0x10000>;
+ };
+
+ iomuxc_snvs: iomuxc-snvs@021c8000 {
+ compatible = "fsl,imx6sll-iomuxc-snvs";
+ reg = <0x021c80000 0x10000>;
+ };
+
+ audmux: audmux@021d8000 {
+ compatible = "fsl,imx6sll-audmux", "fsl,imx31-audmux";
+ reg = <0x021d8000 0x4000>;
+ status = "disabled";
+ };
+
+ uart5: serial@021f4000 {
+ compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f4000 0x4000>;
+ interrupts =<GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SLL_CLK_UART5_IPG>,
+ <&clks IMX6SLL_CLK_UART5_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+ };
+ };
+};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 04/11] driver: pinctrl: imx: Add pinctrl driver support for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
Add pinctrl driver support for imx6sll.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
arch/arm/mach-imx/Kconfig | 1 +
drivers/pinctrl/freescale/Kconfig | 7 +
drivers/pinctrl/freescale/Makefile | 1 +
drivers/pinctrl/freescale/pinctrl-imx6sll.c | 385 ++++++++++++++++++++++++++++
4 files changed, 394 insertions(+)
create mode 100644 drivers/pinctrl/freescale/pinctrl-imx6sll.c
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 33bcfda..c907d9f 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -514,6 +514,7 @@ config SOC_IMX6SL
config SOC_IMX6SLL
bool "i.MX6 SoloLiteLite support"
+ select PINCTRL_IMX6SLL
select SOC_IMX6
help
diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig
index fc8cbf6..93ca39f 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -81,6 +81,13 @@ config PINCTRL_IMX6SL
help
Say Y here to enable the imx6sl pinctrl driver
+config PINCTRL_IMX6SLL
+ bool "IMX6SL pinctrl driver"
+ depends on SOC_IMX6SLL
+ select PINCTRL_IMX
+ help
+ Say Y here to enable the imx6sl pinctrl driver
+
config PINCTRL_IMX6SX
bool "IMX6SX pinctrl driver"
depends on SOC_IMX6SX
diff --git a/drivers/pinctrl/freescale/Makefile b/drivers/pinctrl/freescale/Makefile
index d44c9e2..5f23765 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PINCTRL_IMX53) += pinctrl-imx53.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6dl.o
obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o
+obj-$(CONFIG_PINCTRL_IMX6SLL) += pinctrl-imx6sll.o
obj-$(CONFIG_PINCTRL_IMX6SX) += pinctrl-imx6sx.o
obj-$(CONFIG_PINCTRL_IMX6UL) += pinctrl-imx6ul.o
obj-$(CONFIG_PINCTRL_IMX7D) += pinctrl-imx7d.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6sll.c b/drivers/pinctrl/freescale/pinctrl-imx6sll.c
new file mode 100644
index 0000000..2f4baff
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx6sll.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Author: Bai Ping <ping.bai@nxp.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 <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx6sll_pads {
+ MX6SLL_PAD_RESERVE0 = 0,
+ MX6SLL_PAD_RESERVE1 = 1,
+ MX6SLL_PAD_RESERVE2 = 2,
+ MX6SLL_PAD_RESERVE3 = 3,
+ MX6SLL_PAD_RESERVE4 = 4,
+ MX6SLL_PAD_WDOG_B = 5,
+ MX6SLL_PAD_REF_CLK_24M = 6,
+ MX6SLL_PAD_REF_CLK_32K = 7,
+ MX6SLL_PAD_PWM1 = 8,
+ MX6SLL_PAD_KEY_COL0 = 9,
+ MX6SLL_PAD_KEY_ROW0 = 10,
+ MX6SLL_PAD_KEY_COL1 = 11,
+ MX6SLL_PAD_KEY_ROW1 = 12,
+ MX6SLL_PAD_KEY_COL2 = 13,
+ MX6SLL_PAD_KEY_ROW2 = 14,
+ MX6SLL_PAD_KEY_COL3 = 15,
+ MX6SLL_PAD_KEY_ROW3 = 16,
+ MX6SLL_PAD_KEY_COL4 = 17,
+ MX6SLL_PAD_KEY_ROW4 = 18,
+ MX6SLL_PAD_KEY_COL5 = 19,
+ MX6SLL_PAD_KEY_ROW5 = 20,
+ MX6SLL_PAD_KEY_COL6 = 21,
+ MX6SLL_PAD_KEY_ROW6 = 22,
+ MX6SLL_PAD_KEY_COL7 = 23,
+ MX6SLL_PAD_KEY_ROW7 = 24,
+ MX6SLL_PAD_EPDC_DATA00 = 25,
+ MX6SLL_PAD_EPDC_DATA01 = 26,
+ MX6SLL_PAD_EPDC_DATA02 = 27,
+ MX6SLL_PAD_EPDC_DATA03 = 28,
+ MX6SLL_PAD_EPDC_DATA04 = 29,
+ MX6SLL_PAD_EPDC_DATA05 = 30,
+ MX6SLL_PAD_EPDC_DATA06 = 31,
+ MX6SLL_PAD_EPDC_DATA07 = 32,
+ MX6SLL_PAD_EPDC_DATA08 = 33,
+ MX6SLL_PAD_EPDC_DATA09 = 34,
+ MX6SLL_PAD_EPDC_DATA10 = 35,
+ MX6SLL_PAD_EPDC_DATA11 = 36,
+ MX6SLL_PAD_EPDC_DATA12 = 37,
+ MX6SLL_PAD_EPDC_DATA13 = 38,
+ MX6SLL_PAD_EPDC_DATA14 = 39,
+ MX6SLL_PAD_EPDC_DATA15 = 40,
+ MX6SLL_PAD_EPDC_SDCLK = 41,
+ MX6SLL_PAD_EPDC_SDLE = 42,
+ MX6SLL_PAD_EPDC_SDOE = 43,
+ MX6SLL_PAD_EPDC_SDSHR = 44,
+ MX6SLL_PAD_EPDC_SDCE0 = 45,
+ MX6SLL_PAD_EPDC_SDCE1 = 46,
+ MX6SLL_PAD_EPDC_SDCE2 = 47,
+ MX6SLL_PAD_EPDC_SDCE3 = 48,
+ MX6SLL_PAD_EPDC_GDCLK = 49,
+ MX6SLL_PAD_EPDC_GDOE = 50,
+ MX6SLL_PAD_EPDC_GDRL = 51,
+ MX6SLL_PAD_EPDC_GDSP = 52,
+ MX6SLL_PAD_EPDC_VCOM0 = 53,
+ MX6SLL_PAD_EPDC_VCOM1 = 54,
+ MX6SLL_PAD_EPDC_BDR0 = 55,
+ MX6SLL_PAD_EPDC_BDR1 = 56,
+ MX6SLL_PAD_EPDC_PWR_CTRL0 = 57,
+ MX6SLL_PAD_EPDC_PWR_CTRL1 = 58,
+ MX6SLL_PAD_EPDC_PWR_CTRL2 = 59,
+ MX6SLL_PAD_EPDC_PWR_CTRL3 = 60,
+ MX6SLL_PAD_EPDC_PWR_COM = 61,
+ MX6SLL_PAD_EPDC_PWR_INT = 62,
+ MX6SLL_PAD_EPDC_PWR_STAT = 63,
+ MX6SLL_PAD_EPDC_PWR_WAKE = 64,
+ MX6SLL_PAD_LCD_CLK = 65,
+ MX6SLL_PAD_LCD_ENABLE = 66,
+ MX6SLL_PAD_LCD_HSYNC = 67,
+ MX6SLL_PAD_LCD_VSYNC = 68,
+ MX6SLL_PAD_LCD_RESET = 69,
+ MX6SLL_PAD_LCD_DATA00 = 70,
+ MX6SLL_PAD_LCD_DATA01 = 71,
+ MX6SLL_PAD_LCD_DATA02 = 72,
+ MX6SLL_PAD_LCD_DATA03 = 73,
+ MX6SLL_PAD_LCD_DATA04 = 74,
+ MX6SLL_PAD_LCD_DATA05 = 75,
+ MX6SLL_PAD_LCD_DATA06 = 76,
+ MX6SLL_PAD_LCD_DATA07 = 77,
+ MX6SLL_PAD_LCD_DATA08 = 78,
+ MX6SLL_PAD_LCD_DATA09 = 79,
+ MX6SLL_PAD_LCD_DATA10 = 80,
+ MX6SLL_PAD_LCD_DATA11 = 81,
+ MX6SLL_PAD_LCD_DATA12 = 82,
+ MX6SLL_PAD_LCD_DATA13 = 83,
+ MX6SLL_PAD_LCD_DATA14 = 84,
+ MX6SLL_PAD_LCD_DATA15 = 85,
+ MX6SLL_PAD_LCD_DATA16 = 86,
+ MX6SLL_PAD_LCD_DATA17 = 87,
+ MX6SLL_PAD_LCD_DATA18 = 88,
+ MX6SLL_PAD_LCD_DATA19 = 89,
+ MX6SLL_PAD_LCD_DATA20 = 90,
+ MX6SLL_PAD_LCD_DATA21 = 91,
+ MX6SLL_PAD_LCD_DATA22 = 92,
+ MX6SLL_PAD_LCD_DATA23 = 93,
+ MX6SLL_PAD_AUD_RXFS = 94,
+ MX6SLL_PAD_AUD_RXC = 95,
+ MX6SLL_PAD_AUD_RXD = 96,
+ MX6SLL_PAD_AUD_TXC = 97,
+ MX6SLL_PAD_AUD_TXFS = 98,
+ MX6SLL_PAD_AUD_TXD = 99,
+ MX6SLL_PAD_AUD_MCLK = 100,
+ MX6SLL_PAD_UART1_RXD = 101,
+ MX6SLL_PAD_UART1_TXD = 102,
+ MX6SLL_PAD_I2C1_SCL = 103,
+ MX6SLL_PAD_I2C1_SDA = 104,
+ MX6SLL_PAD_I2C2_SCL = 105,
+ MX6SLL_PAD_I2C2_SDA = 106,
+ MX6SLL_PAD_ECSPI1_SCLK = 107,
+ MX6SLL_PAD_ECSPI1_MOSI = 108,
+ MX6SLL_PAD_ECSPI1_MISO = 109,
+ MX6SLL_PAD_ECSPI1_SS0 = 110,
+ MX6SLL_PAD_ECSPI2_SCLK = 111,
+ MX6SLL_PAD_ECSPI2_MOSI = 112,
+ MX6SLL_PAD_ECSPI2_MISO = 113,
+ MX6SLL_PAD_ECSPI2_SS0 = 114,
+ MX6SLL_PAD_SD1_CLK = 115,
+ MX6SLL_PAD_SD1_CMD = 116,
+ MX6SLL_PAD_SD1_DATA0 = 117,
+ MX6SLL_PAD_SD1_DATA1 = 118,
+ MX6SLL_PAD_SD1_DATA2 = 119,
+ MX6SLL_PAD_SD1_DATA3 = 120,
+ MX6SLL_PAD_SD1_DATA4 = 121,
+ MX6SLL_PAD_SD1_DATA5 = 122,
+ MX6SLL_PAD_SD1_DATA6 = 123,
+ MX6SLL_PAD_SD1_DATA7 = 124,
+ MX6SLL_PAD_SD2_RESET = 125,
+ MX6SLL_PAD_SD2_CLK = 126,
+ MX6SLL_PAD_SD2_CMD = 127,
+ MX6SLL_PAD_SD2_DATA0 = 128,
+ MX6SLL_PAD_SD2_DATA1 = 129,
+ MX6SLL_PAD_SD2_DATA2 = 130,
+ MX6SLL_PAD_SD2_DATA3 = 131,
+ MX6SLL_PAD_SD2_DATA4 = 132,
+ MX6SLL_PAD_SD2_DATA5 = 133,
+ MX6SLL_PAD_SD2_DATA6 = 134,
+ MX6SLL_PAD_SD2_DATA7 = 135,
+ MX6SLL_PAD_SD3_CLK = 136,
+ MX6SLL_PAD_SD3_CMD = 137,
+ MX6SLL_PAD_SD3_DATA0 = 138,
+ MX6SLL_PAD_SD3_DATA1 = 139,
+ MX6SLL_PAD_SD3_DATA2 = 140,
+ MX6SLL_PAD_SD3_DATA3 = 141,
+ MX6SLL_PAD_GPIO4_IO20 = 142,
+ MX6SLL_PAD_GPIO4_IO21 = 143,
+ MX6SLL_PAD_GPIO4_IO19 = 144,
+ MX6SLL_PAD_GPIO4_IO25 = 145,
+ MX6SLL_PAD_GPIO4_IO18 = 146,
+ MX6SLL_PAD_GPIO4_IO24 = 147,
+ MX6SLL_PAD_GPIO4_IO23 = 148,
+ MX6SLL_PAD_GPIO4_IO17 = 149,
+ MX6SLL_PAD_GPIO4_IO22 = 150,
+ MX6SLL_PAD_GPIO4_IO16 = 151,
+ MX6SLL_PAD_GPIO4_IO26 = 152,
+};
+
+enum imx6sll_lpsr_pads {
+ MX6SLL_PAD_SNVS_TAMPER = 0,
+ MX6SLL_PAD_SNVS_PMIC_ON_REQ = 1,
+ MX6SLL_PAD_SNVS_PMIC_STBY_REQ = 2,
+ MX6SLL_PAD_SNVS_BOOT_MODE0 = 3,
+ MX6SLL_PAD_SNVS_BOOT_MODE1 = 4,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx6sll_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_RESERVE4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_WDOG_B),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_REF_CLK_24M),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_REF_CLK_32K),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_PWM1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_COL7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_KEY_ROW7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA00),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA01),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA02),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA03),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA04),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA05),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA06),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA07),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA08),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA09),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA10),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA11),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA12),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA13),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA14),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_DATA15),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDLE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDOE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDSHR),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_SDCE3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDOE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDRL),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_GDSP),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_VCOM0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_VCOM1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_BDR0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_BDR1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_CTRL3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_COM),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_INT),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_STAT),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_EPDC_PWR_WAKE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_ENABLE),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_HSYNC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_VSYNC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_RESET),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA00),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA01),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA02),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA03),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA04),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA05),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA06),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA07),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA08),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA09),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA10),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA11),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA12),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA13),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA14),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA15),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA16),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA17),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA18),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA19),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA20),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA21),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA22),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_LCD_DATA23),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_RXFS),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_RXC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_RXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_TXC),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_TXFS),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_TXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_AUD_MCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_UART1_RXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_UART1_TXD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C1_SCL),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C1_SDA),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C2_SCL),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_I2C2_SDA),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_SCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_MOSI),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_MISO),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI1_SS0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_SCLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_MOSI),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_MISO),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_ECSPI2_SS0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_CMD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD1_DATA7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_RESET),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_CMD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA4),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA5),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA6),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD2_DATA7),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_CLK),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_CMD),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA0),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA1),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA2),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_SD3_DATA3),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO20),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO21),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO19),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO25),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO18),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO24),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO23),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO17),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO22),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO16),
+ IMX_PINCTRL_PIN(MX6SLL_PAD_GPIO4_IO26),
+};
+
+static struct imx_pinctrl_soc_info imx6sll_pinctrl_info = {
+ .pins = imx6sll_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx6sll_pinctrl_pads),
+ .gpr_compatible = "fsl,imx6sll-iomuxc-gpr",
+};
+
+static const struct of_device_id imx6sll_pinctrl_of_match[] = {
+ { .compatible = "fsl,imx6sll-iomuxc", .data = &imx6sll_pinctrl_info, },
+ { /* sentinel */ }
+};
+
+static int imx6sll_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct imx_pinctrl_soc_info *pinctrl_info;
+
+ match = of_match_device(imx6sll_pinctrl_of_match, &pdev->dev);
+
+ if (!match)
+ return -ENODEV;
+
+ pinctrl_info = (struct imx_pinctrl_soc_info *) match->data;
+
+ return imx_pinctrl_probe(pdev, pinctrl_info);
+}
+
+static struct platform_driver imx6sll_pinctrl_driver = {
+ .driver = {
+ .name = "imx6sll-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(imx6sll_pinctrl_of_match),
+ },
+ .probe = imx6sll_pinctrl_probe,
+};
+
+static int __init imx6sll_pinctrl_init(void)
+{
+ return platform_driver_register(&imx6sll_pinctrl_driver);
+}
+arch_initcall(imx6sll_pinctrl_init);
+
+static void __exit imx6sll_pinctrl_exit(void)
+{
+ platform_driver_unregister(&imx6sll_pinctrl_driver);
+}
+module_exit(imx6sll_pinctrl_exit);
--
1.9.1
^ permalink raw reply related
* [PATCH 03/11] driver: clk: imx: Add clock driver for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
Add clk driver support for imx6sll.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
drivers/clk/imx/Makefile | 1 +
drivers/clk/imx/clk-imx6sll.c | 366 ++++++++++++++++++++++++++++++
include/dt-bindings/clock/imx6sll-clock.h | 204 +++++++++++++++++
3 files changed, 571 insertions(+)
create mode 100644 drivers/clk/imx/clk-imx6sll.c
create mode 100644 include/dt-bindings/clock/imx6sll-clock.h
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 1ada68a..9fb8e1f 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SOC_IMX35) += clk-imx35.o
obj-$(CONFIG_SOC_IMX5) += clk-imx51-imx53.o
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
+obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o
diff --git a/drivers/clk/imx/clk-imx6sll.c b/drivers/clk/imx/clk-imx6sll.c
new file mode 100644
index 0000000..c5219e1
--- /dev/null
+++ b/drivers/clk/imx/clk-imx6sll.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <dt-bindings/clock/imx6sll-clock.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/types.h>
+
+#include "clk.h"
+
+#define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16)
+#define CCDR 0x4
+
+static const char *pll_bypass_src_sels[] = { "osc", "dummy", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
+static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = {"periph", "axi_alt_sel", };
+static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
+static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", };
+static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", };
+static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
+static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
+static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
+static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *ssi_sels[] = {"pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", "dummy",};
+static const char *spdif_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
+static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", };
+static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
+static const char *lcdif_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", };
+static const char *ecspi_sels[] = { "pll3_60m", "osc", };
+static const char *uart_sels[] = { "pll3_80m", "osc", };
+static const char *perclk_sels[] = { "ipg", "osc", };
+static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static const char *epdc_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *epdc_sels[] = { "epdc_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static struct clk *clks[IMX6SLL_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int const clks_init_on[] __initconst = {
+ IMX6SLL_CLK_AIPSTZ1, IMX6SLL_CLK_AIPSTZ2,
+ IMX6SLL_CLK_OCRAM, IMX6SLL_CLK_ARM, IMX6SLL_CLK_ROM,
+ IMX6SLL_CLK_MMDC_P0_FAST, IMX6SLL_CLK_MMDC_P0_IPG,
+};
+
+static struct clk_div_table post_div_table[] = {
+ { .val = 2, .div = 1, },
+ { .val = 1, .div = 2, },
+ { .val = 0, .div = 4, },
+ { }
+};
+
+static struct clk_div_table video_div_table[] = {
+ { .val = 0, .div = 1, },
+ { .val = 1, .div = 2, },
+ { .val = 2, .div = 1, },
+ { .val = 3, .div = 4, },
+ { }
+};
+
+static u32 share_count_audio;
+static u32 share_count_ssi1;
+static u32 share_count_ssi2;
+static u32 share_count_ssi3;
+
+static void __init imx6sll_clocks_init(struct device_node *ccm_node)
+{
+ struct device_node *np;
+ void __iomem *base;
+ int i;
+
+ clks[IMX6SLL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+
+ clks[IMX6SLL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
+ clks[IMX6SLL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+
+ /* ipp_di clock is external input */
+ clks[IMX6SLL_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0");
+ clks[IMX6SLL_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1");
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6sll-anatop");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks[IMX6SLL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6SLL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+ clks[IMX6SLL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
+ clks[IMX6SLL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
+ clks[IMX6SLL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3);
+ clks[IMX6SLL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
+ clks[IMX6SLL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
+ clks[IMX6SLL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
+ clks[IMX6SLL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+
+ clks[IMX6SLL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SLL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+
+ /* Do not bypass PLLs initially */
+ clk_set_parent(clks[IMX6SLL_PLL1_BYPASS], clks[IMX6SLL_CLK_PLL1]);
+ clk_set_parent(clks[IMX6SLL_PLL2_BYPASS], clks[IMX6SLL_CLK_PLL2]);
+ clk_set_parent(clks[IMX6SLL_PLL3_BYPASS], clks[IMX6SLL_CLK_PLL3]);
+ clk_set_parent(clks[IMX6SLL_PLL4_BYPASS], clks[IMX6SLL_CLK_PLL4]);
+ clk_set_parent(clks[IMX6SLL_PLL5_BYPASS], clks[IMX6SLL_CLK_PLL5]);
+ clk_set_parent(clks[IMX6SLL_PLL6_BYPASS], clks[IMX6SLL_CLK_PLL6]);
+ clk_set_parent(clks[IMX6SLL_PLL7_BYPASS], clks[IMX6SLL_CLK_PLL7]);
+
+ clks[IMX6SLL_CLK_PLL1_SYS] = imx_clk_fixed_factor("pll1_sys", "pll1_bypass", 1, 1);
+ clks[IMX6SLL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13);
+ clks[IMX6SLL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13);
+ clks[IMX6SLL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13);
+ clks[IMX6SLL_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13);
+ clks[IMX6SLL_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13);
+ clks[IMX6SLL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+
+ /*
+ * Bit 20 is the reserved and read-only bit, we do this only for:
+ * - Do nothing for usbphy clk_enable/disable
+ * - Keep refcount when do usbphy clk_enable/disable, in that case,
+ * the clk framework many need to enable/disable usbphy's parent
+ */
+ clks[IMX6SLL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
+ clks[IMX6SLL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+
+ /*
+ * usbphy*_gate needs to be on after system boots up, and software
+ * never needs to control it anymore.
+ */
+ clks[IMX6SLL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+ clks[IMX6SLL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+
+ /* name parent_name reg idx */
+ clks[IMX6SLL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
+ clks[IMX6SLL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
+ clks[IMX6SLL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2);
+ clks[IMX6SLL_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus", base + 0x100, 3);
+ clks[IMX6SLL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0);
+ clks[IMX6SLL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1);
+ clks[IMX6SLL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2);
+ clks[IMX6SLL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3);
+
+ clks[IMX6SLL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clks[IMX6SLL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+ clks[IMX6SLL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clks[IMX6SLL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+
+ /* name parent_name mult div */
+ clks[IMX6SLL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
+ clks[IMX6SLL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
+ clks[IMX6SLL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
+ clks[IMX6SLL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
+
+ np = ccm_node;
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+
+ clks[IMX6SLL_CLK_STEP] = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+ clks[IMX6SLL_CLK_PLL1_SW] = imx_clk_mux_flags("pll1_sw", base + 0x0c, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels), 0);
+ clks[IMX6SLL_CLK_AXI_ALT_SEL] = imx_clk_mux("axi_alt_sel", base + 0x14, 7, 1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+ clks[IMX6SLL_CLK_AXI_SEL] = imx_clk_mux_flags("axi_sel", base + 0x14, 6, 1, axi_sels, ARRAY_SIZE(axi_sels), 0);
+ clks[IMX6SLL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clks[IMX6SLL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+ clks[IMX6SLL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clks[IMX6SLL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+ clks[IMX6SLL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6SLL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6SLL_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6SLL_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ clks[IMX6SLL_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ clks[IMX6SLL_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+ clks[IMX6SLL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
+ clks[IMX6SLL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
+ clks[IMX6SLL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+ clks[IMX6SLL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x30, 7, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+ clks[IMX6SLL_CLK_EPDC_PRE_SEL] = imx_clk_mux("epdc_pre_sel", base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+ clks[IMX6SLL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+ clks[IMX6SLL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
+ clks[IMX6SLL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
+ clks[IMX6SLL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+
+ clks[IMX6SLL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+ clks[IMX6SLL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+
+ clks[IMX6SLL_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3);
+ clks[IMX6SLL_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3);
+ clks[IMX6SLL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
+ clks[IMX6SLL_CLK_LCDIF_PODF] = imx_clk_divider("lcdif_podf", "lcdif_pred", base + 0x18, 23, 3);
+ clks[IMX6SLL_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6);
+ clks[IMX6SLL_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3);
+ clks[IMX6SLL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3);
+ clks[IMX6SLL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3);
+ clks[IMX6SLL_CLK_UART_PODF] = imx_clk_divider("uart_podf", "uart_sel", base + 0x24, 0, 6);
+ clks[IMX6SLL_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3);
+ clks[IMX6SLL_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6);
+ clks[IMX6SLL_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3);
+ clks[IMX6SLL_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6);
+ clks[IMX6SLL_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3);
+ clks[IMX6SLL_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6);
+ clks[IMX6SLL_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
+ clks[IMX6SLL_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
+ clks[IMX6SLL_CLK_EXTERN_AUDIO_PRED] = imx_clk_divider("extern_audio_pred", "extern_audio_sel", base + 0x30, 12, 3);
+ clks[IMX6SLL_CLK_EXTERN_AUDIO_PODF] = imx_clk_divider("extern_audio_podf", "extern_audio_pred", base + 0x30, 9, 3);
+ clks[IMX6SLL_CLK_EPDC_PODF] = imx_clk_divider("epdc_podf", "epdc_pre_sel", base + 0x34, 12, 3);
+ clks[IMX6SLL_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6);
+ clks[IMX6SLL_CLK_LCDIF_PRED] = imx_clk_divider("lcdif_pred", "lcdif_pre_sel", base + 0x38, 12, 3);
+
+ clks[IMX6SLL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16);
+ clks[IMX6SLL_CLK_MMDC_PODF] = imx_clk_busy_divider("mmdc_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2);
+ clks[IMX6SLL_CLK_AXI_PODF] = imx_clk_busy_divider("axi", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0);
+ clks[IMX6SLL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1);
+
+ clks[IMX6SLL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+ clks[IMX6SLL_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7);
+ clks[IMX6SLL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+ clks[IMX6SLL_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7);
+
+ clks[IMX6SLL_CLK_LDB_DI0_SEL] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
+ clks[IMX6SLL_CLK_LDB_DI1_SEL] = imx_clk_mux("ldb_di1_sel", base + 0x1c, 7, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels));
+ clks[IMX6SLL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+ clks[IMX6SLL_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux("ldb_di1_div_sel", base + 0x20, 10, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+
+ /* CCGR0 */
+ clks[IMX6SLL_CLK_AIPSTZ1] = imx_clk_gate2("aips_tz1", "ahb", base + 0x68, 0);
+ clks[IMX6SLL_CLK_AIPSTZ2] = imx_clk_gate2("aips_tz2", "ahb", base + 0x68, 2);
+ clks[IMX6SLL_CLK_DCP] = imx_clk_gate2("dcp", "ahb", base + 0x68, 10);
+ clks[IMX6SLL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28);
+ clks[IMX6SLL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28);
+
+ /* CCGR1 */
+ clks[IMX6SLL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0);
+ clks[IMX6SLL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_podf", base + 0x6c, 2);
+ clks[IMX6SLL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_podf", base + 0x6c, 4);
+ clks[IMX6SLL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_podf", base + 0x6c, 6);
+ clks[IMX6SLL_CLK_UART3_IPG] = imx_clk_gate2("uart3_ipg", "ipg", base + 0x6c, 10);
+ clks[IMX6SLL_CLK_UART3_SERIAL] = imx_clk_gate2("uart3_serial", "uart_podf", base + 0x6c, 10);
+ clks[IMX6SLL_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12);
+ clks[IMX6SLL_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14);
+ clks[IMX6SLL_CLK_GPT_BUS] = imx_clk_gate2("gpt1_bus", "perclk", base + 0x6c, 20);
+ clks[IMX6SLL_CLK_GPT_SERIAL] = imx_clk_gate2("gpt1_serial", "perclk", base + 0x6c, 22);
+ clks[IMX6SLL_CLK_UART4_IPG] = imx_clk_gate2("uart4_ipg", "ipg", base + 0x6c, 24);
+ clks[IMX6SLL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24);
+
+ /* CCGR2 */
+ clks[IMX6SLL_CLK_CSI] = imx_clk_gate2("csi", "axi", base + 0x70, 2);
+ clks[IMX6SLL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6);
+ clks[IMX6SLL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8);
+ clks[IMX6SLL_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10);
+ clks[IMX6SLL_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12);
+ clks[IMX6SLL_CLK_LCDIF_APB] = imx_clk_gate2("lcdif_apb", "axi", base + 0x70, 28);
+ clks[IMX6SLL_CLK_PXP] = imx_clk_gate2("pxp", "axi", base + 0x70, 30);
+
+ /* CCGR3 */
+ clks[IMX6SLL_CLK_UART5_IPG] = imx_clk_gate2("uart5_ipg", "ipg", base + 0x74, 2);
+ clks[IMX6SLL_CLK_UART5_SERIAL] = imx_clk_gate2("uart5_serial", "uart_podf", base + 0x74, 2);
+ clks[IMX6SLL_CLK_EPDC_AXI] = imx_clk_gate2("epdc_aclk", "axi", base + 0x74, 4);
+ clks[IMX6SLL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_podf", base + 0x74, 4);
+ clks[IMX6SLL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_podf", base + 0x74, 10);
+ clks[IMX6SLL_CLK_WDOG1] = imx_clk_gate2("wdog1", "ipg", base + 0x74, 16);
+ clks[IMX6SLL_CLK_MMDC_P0_FAST] = imx_clk_gate("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20);
+ clks[IMX6SLL_CLK_MMDC_P0_IPG] = imx_clk_gate2("mmdc_p0_ipg", "ipg", base + 0x74, 24);
+ clks[IMX6SLL_CLK_OCRAM] = imx_clk_gate("ocram", "ahb", base + 0x74, 28);
+
+ /* CCGR4 */
+ clks[IMX6SLL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16);
+ clks[IMX6SLL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18);
+ clks[IMX6SLL_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20);
+ clks[IMX6SLL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22);
+
+ /* CCGR5 */
+ clks[IMX6SLL_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0);
+ clks[IMX6SLL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
+ clks[IMX6SLL_CLK_WDOG2] = imx_clk_gate2("wdog2", "ipg", base + 0x7c, 10);
+ clks[IMX6SLL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
+ clks[IMX6SLL_CLK_EXTERN_AUDIO] = imx_clk_gate2_shared("extern_audio", "extern_audio_podf", base + 0x7c, 14, &share_count_audio);
+ clks[IMX6SLL_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio);
+ clks[IMX6SLL_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_audio);
+ clks[IMX6SLL_CLK_SSI1] = imx_clk_gate2_shared("ssi1", "ssi1_podf", base + 0x7c, 18, &share_count_ssi1);
+ clks[IMX6SLL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
+ clks[IMX6SLL_CLK_SSI2] = imx_clk_gate2_shared("ssi2", "ssi2_podf", base + 0x7c, 20, &share_count_ssi2);
+ clks[IMX6SLL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
+ clks[IMX6SLL_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3);
+ clks[IMX6SLL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
+ clks[IMX6SLL_CLK_UART1_IPG] = imx_clk_gate2("uart1_ipg", "ipg", base + 0x7c, 24);
+ clks[IMX6SLL_CLK_UART1_SERIAL] = imx_clk_gate2("uart1_serial", "uart_podf", base + 0x7c, 24);
+
+ /* CCGR6 */
+ clks[IMX6SLL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
+ clks[IMX6SLL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
+ clks[IMX6SLL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
+ clks[IMX6SLL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
+
+ /* mask handshake of mmdc */
+ writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ if (IS_ERR(clks[i]))
+ pr_err("i.MX6SLL clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+ /* set perclk to from OSC */
+ clk_set_parent(clks[IMX6SLL_CLK_PERCLK_SEL], clks[IMX6SLL_CLK_OSC]);
+
+ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+ clk_prepare_enable(clks[clks_init_on[i]]);
+
+ if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
+ clk_prepare_enable(clks[IMX6SLL_CLK_USBPHY1_GATE]);
+ clk_prepare_enable(clks[IMX6SLL_CLK_USBPHY2_GATE]);
+ }
+
+ /* Lower the AHB clock rate before changing the clock source. */
+ clk_set_rate(clks[IMX6SLL_CLK_AHB], 99000000);
+
+ /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
+ clk_set_parent(clks[IMX6SLL_CLK_PERIPH_CLK2_SEL], clks[IMX6SLL_CLK_PLL3_USB_OTG]);
+ clk_set_parent(clks[IMX6SLL_CLK_PERIPH], clks[IMX6SLL_CLK_PERIPH_CLK2]);
+ clk_set_parent(clks[IMX6SLL_CLK_PERIPH_PRE], clks[IMX6SLL_CLK_PLL2_BUS]);
+ clk_set_parent(clks[IMX6SLL_CLK_PERIPH], clks[IMX6SLL_CLK_PERIPH_PRE]);
+
+ clk_set_rate(clks[IMX6SLL_CLK_AHB], 132000000);
+}
+
+CLK_OF_DECLARE(imx6sll, "fsl,imx6sll-ccm", imx6sll_clocks_init);
+
diff --git a/include/dt-bindings/clock/imx6sll-clock.h b/include/dt-bindings/clock/imx6sll-clock.h
new file mode 100644
index 0000000..39c2567
--- /dev/null
+++ b/include/dt-bindings/clock/imx6sll-clock.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX6SLL_H
+#define __DT_BINDINGS_CLOCK_IMX6SLL_H
+
+#define IMX6SLL_CLK_DUMMY 0
+#define IMX6SLL_CLK_CKIL 1
+#define IMX6SLL_CLK_OSC 2
+#define IMX6SLL_PLL1_BYPASS_SRC 3
+#define IMX6SLL_PLL2_BYPASS_SRC 4
+#define IMX6SLL_PLL3_BYPASS_SRC 5
+#define IMX6SLL_PLL4_BYPASS_SRC 6
+#define IMX6SLL_PLL5_BYPASS_SRC 7
+#define IMX6SLL_PLL6_BYPASS_SRC 8
+#define IMX6SLL_PLL7_BYPASS_SRC 9
+#define IMX6SLL_CLK_PLL1 10
+#define IMX6SLL_CLK_PLL2 11
+#define IMX6SLL_CLK_PLL3 12
+#define IMX6SLL_CLK_PLL4 13
+#define IMX6SLL_CLK_PLL5 14
+#define IMX6SLL_CLK_PLL6 15
+#define IMX6SLL_CLK_PLL7 16
+#define IMX6SLL_PLL1_BYPASS 17
+#define IMX6SLL_PLL2_BYPASS 18
+#define IMX6SLL_PLL3_BYPASS 19
+#define IMX6SLL_PLL4_BYPASS 20
+#define IMX6SLL_PLL5_BYPASS 21
+#define IMX6SLL_PLL6_BYPASS 22
+#define IMX6SLL_PLL7_BYPASS 23
+#define IMX6SLL_CLK_PLL1_SYS 24
+#define IMX6SLL_CLK_PLL2_BUS 25
+#define IMX6SLL_CLK_PLL3_USB_OTG 26
+#define IMX6SLL_CLK_PLL4_AUDIO 27
+#define IMX6SLL_CLK_PLL5_VIDEO 28
+#define IMX6SLL_CLK_PLL6_ENET 29
+#define IMX6SLL_CLK_PLL7_USB_HOST 30
+#define IMX6SLL_CLK_USBPHY1 31
+#define IMX6SLL_CLK_USBPHY2 32
+#define IMX6SLL_CLK_USBPHY1_GATE 33
+#define IMX6SLL_CLK_USBPHY2_GATE 34
+#define IMX6SLL_CLK_PLL2_PFD0 35
+#define IMX6SLL_CLK_PLL2_PFD1 36
+#define IMX6SLL_CLK_PLL2_PFD2 37
+#define IMX6SLL_CLK_PLL2_PFD3 38
+#define IMX6SLL_CLK_PLL3_PFD0 39
+#define IMX6SLL_CLK_PLL3_PFD1 40
+#define IMX6SLL_CLK_PLL3_PFD2 41
+#define IMX6SLL_CLK_PLL3_PFD3 42
+#define IMX6SLL_CLK_PLL4_POST_DIV 43
+#define IMX6SLL_CLK_PLL4_AUDIO_DIV 44
+#define IMX6SLL_CLK_PLL5_POST_DIV 45
+#define IMX6SLL_CLK_PLL5_VIDEO_DIV 46
+#define IMX6SLL_CLK_PLL2_198M 47
+#define IMX6SLL_CLK_PLL3_120M 48
+#define IMX6SLL_CLK_PLL3_80M 49
+#define IMX6SLL_CLK_PLL3_60M 50
+#define IMX6SLL_CLK_STEP 51
+#define IMX6SLL_CLK_PLL1_SW 52
+#define IMX6SLL_CLK_AXI_ALT_SEL 53
+#define IMX6SLL_CLK_AXI_SEL 54
+#define IMX6SLL_CLK_PERIPH_PRE 55
+#define IMX6SLL_CLK_PERIPH2_PRE 56
+#define IMX6SLL_CLK_PERIPH_CLK2_SEL 57
+#define IMX6SLL_CLK_PERIPH2_CLK2_SEL 58
+#define IMX6SLL_CLK_PERCLK_SEL 59
+#define IMX6SLL_CLK_USDHC1_SEL 60
+#define IMX6SLL_CLK_USDHC2_SEL 61
+#define IMX6SLL_CLK_USDHC3_SEL 62
+#define IMX6SLL_CLK_SSI1_SEL 63
+#define IMX6SLL_CLK_SSI2_SEL 64
+#define IMX6SLL_CLK_SSI3_SEL 65
+#define IMX6SLL_CLK_PXP_SEL 66
+#define IMX6SLL_CLK_LCDIF_PRE_SEL 67
+#define IMX6SLL_CLK_LCDIF_SEL 68
+#define IMX6SLL_CLK_EPDC_PRE_SEL 69
+#define IMX6SLL_CLK_SPDIF_SEL 70
+#define IMX6SLL_CLK_ECSPI_SEL 71
+#define IMX6SLL_CLK_UART_SEL 72
+#define IMX6SLL_CLK_ARM 73
+#define IMX6SLL_CLK_PERIPH 74
+#define IMX6SLL_CLK_PERIPH2 75
+#define IMX6SLL_CLK_PERIPH2_CLK2 76
+#define IMX6SLL_CLK_PERIPH_CLK2 77
+#define IMX6SLL_CLK_MMDC_PODF 78
+#define IMX6SLL_CLK_AXI_PODF 79
+#define IMX6SLL_CLK_AHB 80
+#define IMX6SLL_CLK_IPG 81
+#define IMX6SLL_CLK_PERCLK 82
+#define IMX6SLL_CLK_USDHC1_PODF 83
+#define IMX6SLL_CLK_USDHC2_PODF 84
+#define IMX6SLL_CLK_USDHC3_PODF 85
+#define IMX6SLL_CLK_SSI1_PRED 86
+#define IMX6SLL_CLK_SSI2_PRED 87
+#define IMX6SLL_CLK_SSI3_PRED 88
+#define IMX6SLL_CLK_SSI1_PODF 89
+#define IMX6SLL_CLK_SSI2_PODF 90
+#define IMX6SLL_CLK_SSI3_PODF 91
+#define IMX6SLL_CLK_PXP_PODF 92
+#define IMX6SLL_CLK_LCDIF_PRED 93
+#define IMX6SLL_CLK_LCDIF_PODF 94
+#define IMX6SLL_CLK_EPDC_SEL 95
+#define IMX6SLL_CLK_EPDC_PODF 96
+#define IMX6SLL_CLK_SPDIF_PRED 97
+#define IMX6SLL_CLK_SPDIF_PODF 98
+#define IMX6SLL_CLK_ECSPI_PODF 99
+#define IMX6SLL_CLK_UART_PODF 100
+
+/* CCGR 0 */
+#define IMX6SLL_CLK_AIPSTZ1 101
+#define IMX6SLL_CLK_AIPSTZ2 102
+#define IMX6SLL_CLK_DCP 103
+#define IMX6SLL_CLK_UART2_IPG 104
+#define IMX6SLL_CLK_UART2_SERIAL 105
+
+/* CCGR 1 */
+#define IMX6SLL_CLK_ECSPI1 106
+#define IMX6SLL_CLK_ECSPI2 107
+#define IMX6SLL_CLK_ECSPI3 108
+#define IMX6SLL_CLK_ECSPI4 109
+#define IMX6SLL_CLK_UART3_IPG 110
+#define IMX6SLL_CLK_UART3_SERIAL 111
+#define IMX6SLL_CLK_UART4_IPG 112
+#define IMX6SLL_CLK_UART4_SERIAL 113
+#define IMX6SLL_CLK_EPIT1 114
+#define IMX6SLL_CLK_EPIT2 115
+#define IMX6SLL_CLK_GPT_BUS 116
+#define IMX6SLL_CLK_GPT_SERIAL 117
+
+/* CCGR2 */
+#define IMX6SLL_CLK_CSI 118
+#define IMX6SLL_CLK_I2C1 119
+#define IMX6SLL_CLK_I2C2 120
+#define IMX6SLL_CLK_I2C3 121
+#define IMX6SLL_CLK_OCOTP 122
+#define IMX6SLL_CLK_LCDIF_APB 123
+#define IMX6SLL_CLK_PXP 124
+
+/* CCGR3 */
+#define IMX6SLL_CLK_UART5_IPG 125
+#define IMX6SLL_CLK_UART5_SERIAL 126
+#define IMX6SLL_CLK_EPDC_AXI 127
+#define IMX6SLL_CLK_EPDC_PIX 128
+#define IMX6SLL_CLK_LCDIF_PIX 129
+#define IMX6SLL_CLK_WDOG1 130
+#define IMX6SLL_CLK_MMDC_P0_FAST 131
+#define IMX6SLL_CLK_MMDC_P0_IPG 132
+#define IMX6SLL_CLK_OCRAM 133
+
+/* CCGR4 */
+#define IMX6SLL_CLK_PWM1 134
+#define IMX6SLL_CLK_PWM2 135
+#define IMX6SLL_CLK_PWM3 136
+#define IMX6SLL_CLK_PWM4 137
+
+/* CCGR 5 */
+#define IMX6SLL_CLK_ROM 138
+#define IMX6SLL_CLK_SDMA 139
+#define IMX6SLL_CLK_KPP 140
+#define IMX6SLL_CLK_WDOG2 141
+#define IMX6SLL_CLK_SPBA 142
+#define IMX6SLL_CLK_SPDIF 143
+#define IMX6SLL_CLK_SPDIF_GCLK 144
+#define IMX6SLL_CLK_SSI1 145
+#define IMX6SLL_CLK_SSI1_IPG 146
+#define IMX6SLL_CLK_SSI2 147
+#define IMX6SLL_CLK_SSI2_IPG 148
+#define IMX6SLL_CLK_SSI3 149
+#define IMX6SLL_CLK_SSI3_IPG 150
+#define IMX6SLL_CLK_UART1_IPG 151
+#define IMX6SLL_CLK_UART1_SERIAL 152
+
+/* CCGR 6 */
+#define IMX6SLL_CLK_USBOH3 153
+#define IMX6SLL_CLK_USDHC1 154
+#define IMX6SLL_CLK_USDHC2 155
+#define IMX6SLL_CLK_USDHC3 156
+
+#define IMX6SLL_CLK_IPP_DI0 157
+#define IMX6SLL_CLK_IPP_DI1 158
+#define IMX6SLL_CLK_LDB_DI0_SEL 159
+#define IMX6SLL_CLK_LDB_DI0_DIV_3_5 160
+#define IMX6SLL_CLK_LDB_DI0_DIV_7 161
+#define IMX6SLL_CLK_LDB_DI0_DIV_SEL 162
+#define IMX6SLL_CLK_LDB_DI0 163
+#define IMX6SLL_CLK_LDB_DI1_SEL 164
+#define IMX6SLL_CLK_LDB_DI1_DIV_3_5 165
+#define IMX6SLL_CLK_LDB_DI1_DIV_7 166
+#define IMX6SLL_CLK_LDB_DI1_DIV_SEL 167
+#define IMX6SLL_CLK_LDB_DI1 168
+#define IMX6SLL_CLK_EXTERN_AUDIO_SEL 169
+#define IMX6SLL_CLK_EXTERN_AUDIO_PRED 170
+#define IMX6SLL_CLK_EXTERN_AUDIO_PODF 171
+#define IMX6SLL_CLK_EXTERN_AUDIO 172
+
+#define IMX6SLL_CLK_END 173
+
+#endif /* __DT_BINDINGS_CLOCK_IMX6SLL_H */
--
1.9.1
^ permalink raw reply related
* [PATCH 02/11] driver: clocksource: add gpt timer for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
Add gpt timer support for i.MX6SLL.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
drivers/clocksource/timer-imx-gpt.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index f595460..f71822d 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -556,4 +556,5 @@ static int __init imx6dl_timer_init_dt(struct device_node *np)
CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx6sll_timer, "fsl,imx6sll-gpt", imx6dl_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
--
1.9.1
^ permalink raw reply related
* [PATCH 01/11] ARM: imx: Add basic msl support for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
In-Reply-To: <1480660774-25055-1-git-send-email-ping.bai@nxp.com>
Add basic MSL support for i.MX6SLL.
The i.MX 6SoloLiteLite application processors are NXP's latest
additions to a growing family of multimedia-focused products
offering high-performance processing optimized for lowest power
consumption. The i.MX 6SoloLiteLite processors feature NXP's advanced
implementation of the ARM Cortex-A9 core, which can be interfaced
with LPDDR3 and LPDDR2 DRAM memory devices.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
---
arch/arm/mach-imx/Kconfig | 7 +++++++
arch/arm/mach-imx/Makefile | 1 +
arch/arm/mach-imx/cpu.c | 3 +++
arch/arm/mach-imx/cpuidle-imx6sl.c | 7 +++++--
arch/arm/mach-imx/gpc.c | 8 ++++++++
arch/arm/mach-imx/mach-imx6sl.c | 10 ++++++++--
arch/arm/mach-imx/mxc.h | 6 ++++++
7 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 936c59d..33bcfda 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -512,6 +512,13 @@ config SOC_IMX6SL
help
This enables support for Freescale i.MX6 SoloLite processor.
+config SOC_IMX6SLL
+ bool "i.MX6 SoloLiteLite support"
+ select SOC_IMX6
+
+ help
+ This enables support for Freescale i.MX6 SoloLiteLite processor.
+
config SOC_IMX6SX
bool "i.MX6 SoloX support"
select PINCTRL_IMX6SX
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index cab1289..f2bf650 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
endif
obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
+obj-$(CONFIG_SOC_IMX6SLL) += mach-imx6sl.o
obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index b3347d3..62e8c0f 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -131,6 +131,9 @@ struct device * __init imx_soc_device_init(void)
case MXC_CPU_IMX6UL:
soc_id = "i.MX6UL";
break;
+ case MXC_CPU_IMX6SLL:
+ soc_id = "i.MX6SLL";
+ break;
case MXC_CPU_IMX7D:
soc_id = "i.MX7D";
break;
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
index 8d866fb..124f982 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sl.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -11,6 +11,7 @@
#include <asm/cpuidle.h>
#include "common.h"
+#include "hardware.h"
#include "cpuidle.h"
static int imx6sl_enter_wait(struct cpuidle_device *dev,
@@ -21,9 +22,11 @@ static int imx6sl_enter_wait(struct cpuidle_device *dev,
* Software workaround for ERR005311, see function
* description for details.
*/
- imx6sl_set_wait_clk(true);
+ if (cpu_is_imx6sl())
+ imx6sl_set_wait_clk(true);
cpu_do_idle();
- imx6sl_set_wait_clk(false);
+ if (cpu_is_imx6sl())
+ imx6sl_set_wait_clk(false);
imx6_set_lpm(WAIT_CLOCKED);
return index;
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 1dc2a34..4ed8a63 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -26,6 +26,7 @@
#include "hardware.h"
#define GPC_CNTR 0x000
+#define GPC_CNTR_L2_PGE 22
#define GPC_IMR1 0x008
#define GPC_PGC_GPU_PDN 0x260
#define GPC_PGC_GPU_PUPSCR 0x264
@@ -243,6 +244,7 @@ static int __init imx_gpc_init(struct device_node *node,
{
struct irq_domain *parent_domain, *domain;
int i;
+ u32 val;
if (!parent) {
pr_err("%s: no parent, giving up\n", node->full_name);
@@ -271,6 +273,12 @@ static int __init imx_gpc_init(struct device_node *node,
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
+ /* clear the L2_PGE bit on i.MX6SLL */
+ if (cpu_is_imx6sll()) {
+ val = readl_relaxed(gpc_base + GPC_CNTR);
+ val &= ~(1 << GPC_CNTR_L2_PGE);
+ writel_relaxed(val, gpc_base + GPC_CNTR);
+ }
/*
* Clear the OF_POPULATED flag set in of_irq_init so that
* later the GPC power domain driver will not be skipped.
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 0408490..462ed9c 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -17,6 +17,7 @@
#include <asm/mach/map.h>
#include "common.h"
+#include "hardware.h"
#include "cpuidle.h"
static void __init imx6sl_fec_init(void)
@@ -54,7 +55,8 @@ static void __init imx6sl_init_machine(void)
of_platform_default_populate(NULL, NULL, parent);
- imx6sl_fec_init();
+ if (cpu_is_imx6sl())
+ imx6sl_fec_init();
imx_anatop_init();
imx6sl_pm_init();
}
@@ -66,11 +68,15 @@ static void __init imx6sl_init_irq(void)
imx_init_l2cache();
imx_src_init();
irqchip_init();
- imx6_pm_ccm_init("fsl,imx6sl-ccm");
+ if (cpu_is_imx6sl())
+ imx6_pm_ccm_init("fsl,imx6sl-ccm");
+ else
+ imx6_pm_ccm_init("fsl,imx6sll-ccm");
}
static const char * const imx6sl_dt_compat[] __initconst = {
"fsl,imx6sl",
+ "fsl,imx6sll",
NULL,
};
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index 34f2ff6..e047611 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -39,6 +39,7 @@
#define MXC_CPU_IMX6SX 0x62
#define MXC_CPU_IMX6Q 0x63
#define MXC_CPU_IMX6UL 0x64
+#define MXC_CPU_IMX6SLL 0x67
#define MXC_CPU_IMX7D 0x72
#define IMX_DDR_TYPE_LPDDR2 1
@@ -73,6 +74,11 @@ static inline bool cpu_is_imx6ul(void)
return __mxc_cpu_type == MXC_CPU_IMX6UL;
}
+static inline bool cpu_is_imx6sll(void)
+{
+ return __mxc_cpu_type == MXC_CPU_IMX6SLL;
+}
+
static inline bool cpu_is_imx6q(void)
{
return __mxc_cpu_type == MXC_CPU_IMX6Q;
--
1.9.1
^ permalink raw reply related
* [PATCH 00/11] Add basic code support for imx6sll
From: Bai Ping @ 2016-12-02 6:39 UTC (permalink / raw)
To: shawnguo, mturquette, sboyd, robh+dt, mark.rutland, linus.walleij
Cc: devicetree, kernel, daniel.lezcano, linux-gpio, p.zabel,
fabio.estevam, tglx, linux-clk, linux-arm-kernel, ping.bai
The i.MX 6SoloLiteLite application processors are NXP's
latest additions to a growing family of multimedia-focused
products offering high-performance processing optimized for
lowest power consumption. The i.MX 6SoloLiteLite processors
feature NXP's advanced implementation of the ARM Cortex-A9 core,
which can be interfaced with LPDDR3 and LPDDR2 DRAM memory devices.
i.MX6SLL is a new SOC of the i.MX6 family, shares many common modules,
so most of the MSL code can be resued from i.MX6 serious SOC.
Bai Ping (11):
ARM: imx: Add basic msl support for imx6sll
driver: clocksource: add gpt timer for imx6sll
driver: clk: imx: Add clock driver for imx6sll
driver: pinctrl: imx: Add pinctrl driver support for imx6sll
ARM: dts: imx: Add basic dtsi for imx6sll
ARM: dts: imx: Add imx6sll EVK board dts support
ARM: debug: Add low level debug support for imx6sll
ARM: imx: Add suspend/resume support for imx6sll
ARM: imx: correct i.mx6sll dram io low power mode
Document: dt: binding: imx: update doc for imx6sll
ARM: configs: enable imx6sll support in defconfig
.../devicetree/bindings/clock/imx6sll-clock.txt | 13 +
.../bindings/pinctrl/fsl,imx6sll-pinctrl.txt | 37 +
arch/arm/Kconfig.debug | 9 +
arch/arm/boot/dts/Makefile | 2 +
arch/arm/boot/dts/imx6sll-evk.dts | 652 +++++++++++++++
arch/arm/boot/dts/imx6sll-pinfunc.h | 882 +++++++++++++++++++++
arch/arm/boot/dts/imx6sll.dtsi | 854 ++++++++++++++++++++
arch/arm/configs/imx_v6_v7_defconfig | 1 +
arch/arm/include/debug/imx-uart.h | 10 +
arch/arm/mach-imx/Kconfig | 8 +
arch/arm/mach-imx/Makefile | 1 +
arch/arm/mach-imx/cpu.c | 3 +
arch/arm/mach-imx/cpuidle-imx6sl.c | 7 +-
arch/arm/mach-imx/gpc.c | 8 +
arch/arm/mach-imx/mach-imx6sl.c | 10 +-
arch/arm/mach-imx/mxc.h | 6 +
arch/arm/mach-imx/pm-imx6.c | 49 +-
arch/arm/mach-imx/suspend-imx6.S | 29 +-
drivers/clk/imx/Makefile | 1 +
drivers/clk/imx/clk-imx6sll.c | 366 +++++++++
drivers/clocksource/timer-imx-gpt.c | 1 +
drivers/pinctrl/freescale/Kconfig | 7 +
drivers/pinctrl/freescale/Makefile | 1 +
drivers/pinctrl/freescale/pinctrl-imx6sll.c | 385 +++++++++
include/dt-bindings/clock/imx6sll-clock.h | 204 +++++
25 files changed, 3514 insertions(+), 32 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/imx6sll-clock.txt
create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx6sll-pinctrl.txt
create mode 100644 arch/arm/boot/dts/imx6sll-evk.dts
create mode 100644 arch/arm/boot/dts/imx6sll-pinfunc.h
create mode 100644 arch/arm/boot/dts/imx6sll.dtsi
create mode 100644 drivers/clk/imx/clk-imx6sll.c
create mode 100644 drivers/pinctrl/freescale/pinctrl-imx6sll.c
create mode 100644 include/dt-bindings/clock/imx6sll-clock.h
--
1.9.1
^ permalink raw reply
* [PATCH 4/4] mmc: pwrseq-simple: add disable-post-power-on option
From: Matt Ranostay @ 2016-12-02 6:17 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: Matt Ranostay, Tony Lindgren, Ulf Hansson
In-Reply-To: <1480659462-29536-1-git-send-email-matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Add optional device-post-power-on parameters to disable post_power_on
function from being called since this breaks some device.
Cc: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
Cc: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
---
Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++
drivers/mmc/core/pwrseq_simple.c | 7 +++++++
2 files changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
index bea306d772d1..09fa153f743e 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
@@ -24,6 +24,8 @@ Optional properties:
de-asserting the reset-gpios (if any)
- invert-off-state: Invert the power down state for the reset-gpios (if any)
and pwrdn-gpios (if any)
+- disable-post-power-on : Avoid post_power_on function from being called since
+ this breaks some devices
Example:
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 857dde3e0456..d34084c51f9c 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -26,6 +26,7 @@
struct mmc_pwrseq_simple {
struct mmc_pwrseq pwrseq;
bool clk_enabled;
+ bool disable_post_power_on;
bool invert_off_state;
u32 pre_power_on_delay_ms;
u32 post_power_on_delay_ms;
@@ -72,6 +73,9 @@ static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
{
struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
+ if (pwrseq->disable_post_power_on)
+ return;
+
mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->reset_gpios, 0);
if (pwrseq->post_power_on_delay_ms)
@@ -139,6 +143,9 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
device_property_read_u32(dev, "post-power-on-delay-ms",
&pwrseq->post_power_on_delay_ms);
+ if (device_property_read_bool(dev, "disable-post-power-on"))
+ pwrseq->disable_post_power_on = true;
+
pwrseq->pwrseq.dev = dev;
pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;
pwrseq->pwrseq.owner = THIS_MODULE;
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 3/4] mmc: pwrseq-simple: allow inverting of off state logic
From: Matt Ranostay @ 2016-12-02 6:17 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: Matt Ranostay, Tony Lindgren, Ulf Hansson
In-Reply-To: <1480659462-29536-1-git-send-email-matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Some devices need a logic level low instead of high to be in the
off state.
Cc: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
Cc: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
---
.../devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++
drivers/mmc/core/pwrseq_simple.c | 15 +++++++++++----
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
index 703a714201d8..bea306d772d1 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
@@ -22,6 +22,8 @@ Optional properties:
the reset-gpios (if any) are asserted
- post-power-on-delay-ms : Delay in ms after powering the card and
de-asserting the reset-gpios (if any)
+- invert-off-state: Invert the power down state for the reset-gpios (if any)
+ and pwrdn-gpios (if any)
Example:
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index adf1f7161fe3..857dde3e0456 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -26,6 +26,7 @@
struct mmc_pwrseq_simple {
struct mmc_pwrseq pwrseq;
bool clk_enabled;
+ bool invert_off_state;
u32 pre_power_on_delay_ms;
u32 post_power_on_delay_ms;
struct clk *ext_clk;
@@ -80,9 +81,10 @@ static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
{
struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
+ unsigned int off_state = !(pwrseq->invert_off_state);
- mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->reset_gpios, 1);
- mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->pwrdn_gpios, 1);
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->reset_gpios, off_state);
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->pwrdn_gpios, off_state);
if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) {
clk_disable_unprepare(pwrseq->ext_clk);
@@ -107,6 +109,7 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
{
struct mmc_pwrseq_simple *pwrseq;
struct device *dev = &pdev->dev;
+ bool invert_off_state = false;
pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
if (!pwrseq)
@@ -116,8 +119,11 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT)
return PTR_ERR(pwrseq->ext_clk);
+ if (device_property_read_bool(dev, "invert-off-state"))
+ invert_off_state = true;
+
pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset",
- GPIOD_OUT_HIGH);
+ invert_off_state ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
if (IS_ERR(pwrseq->reset_gpios) &&
PTR_ERR(pwrseq->reset_gpios) != -ENOENT &&
PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) {
@@ -125,7 +131,7 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
}
pwrseq->pwrdn_gpios = devm_gpiod_get_array(dev, "pwrdn",
- GPIOD_OUT_HIGH);
+ invert_off_state ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
device_property_read_u32(dev, "pre-power-on-delay-ms",
&pwrseq->pre_power_on_delay_ms);
@@ -136,6 +142,7 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
pwrseq->pwrseq.dev = dev;
pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;
pwrseq->pwrseq.owner = THIS_MODULE;
+ pwrseq->invert_off_state = invert_off_state;
platform_set_drvdata(pdev, pwrseq);
return mmc_pwrseq_register(&pwrseq->pwrseq);
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 2/4] mmc: pwrseq-simple: add support for power down GPIO pins
From: Matt Ranostay @ 2016-12-02 6:17 UTC (permalink / raw)
To: devicetree, linux-mmc; +Cc: Matt Ranostay, Tony Lindgren, Ulf Hansson
In-Reply-To: <1480659462-29536-1-git-send-email-matt@ranostay.consulting>
Some devices have additional pins that control power but need to
asserted separately from reset-gpios using a defined time delay.
Cc: Tony Lindgren <tony@atomide.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
---
.../devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++
drivers/mmc/core/pwrseq_simple.c | 26 +++++++++++++---------
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
index 88826f7d1d38..703a714201d8 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
@@ -12,6 +12,8 @@ Optional properties:
at initialization and prior we start the power up procedure of the card.
They will be de-asserted right after the power has been provided to the
card.
+- pwrdn-gpios : contains a list of GPIO specifiers. The pwrdn GPIOs are asserted
+ at initialization and prior we start the power up procedure of the card.
- clocks : Must contain an entry for the entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entry:
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index cb2ba7b11383..adf1f7161fe3 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -30,24 +30,23 @@ struct mmc_pwrseq_simple {
u32 post_power_on_delay_ms;
struct clk *ext_clk;
struct gpio_descs *reset_gpios;
+ struct gpio_descs *pwrdn_gpios;
};
#define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
+ struct gpio_descs *gpios,
int value)
{
- struct gpio_descs *reset_gpios = pwrseq->reset_gpios;
-
- if (!IS_ERR(reset_gpios)) {
+ if (!IS_ERR(gpios)) {
int i;
- int values[reset_gpios->ndescs];
+ int values[gpios->ndescs];
- for (i = 0; i < reset_gpios->ndescs; i++)
+ for (i = 0; i < gpios->ndescs; i++)
values[i] = value;
- gpiod_set_array_value_cansleep(
- reset_gpios->ndescs, reset_gpios->desc, values);
+ gpiod_set_array_value_cansleep(gpios->ndescs, gpios->desc, values);
}
}
@@ -60,17 +59,19 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
pwrseq->clk_enabled = true;
}
- mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->reset_gpios, 1);
if (pwrseq->pre_power_on_delay_ms)
msleep(pwrseq->pre_power_on_delay_ms);
+
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->pwrdn_gpios, 1);
}
static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
{
struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
- mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->reset_gpios, 0);
if (pwrseq->post_power_on_delay_ms)
msleep(pwrseq->post_power_on_delay_ms);
@@ -80,12 +81,14 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
{
struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
- mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->reset_gpios, 1);
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, pwrseq->pwrdn_gpios, 1);
if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) {
clk_disable_unprepare(pwrseq->ext_clk);
pwrseq->clk_enabled = false;
}
+
}
static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
@@ -121,6 +124,9 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
return PTR_ERR(pwrseq->reset_gpios);
}
+ pwrseq->pwrdn_gpios = devm_gpiod_get_array(dev, "pwrdn",
+ GPIOD_OUT_HIGH);
+
device_property_read_u32(dev, "pre-power-on-delay-ms",
&pwrseq->pre_power_on_delay_ms);
--
2.7.4
^ permalink raw reply related
* [PATCH 1/4] mmc: pwrseq-simple: add an optional pre-power-on-delay
From: Matt Ranostay @ 2016-12-02 6:17 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: Matt Ranostay, Tony Lindgren, Ulf Hansson
In-Reply-To: <1480659462-29536-1-git-send-email-matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Some devices need some time between asserting reset-gpios before can
receive sdio commands.
This commits adds a pre-power-on-delay-ms devicetree property to
mmc-pwrseq-simple for use with such devices.
Cc: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
Cc: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
---
Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++
drivers/mmc/core/pwrseq_simple.c | 7 +++++++
2 files changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
index e25436861867..88826f7d1d38 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
@@ -16,6 +16,8 @@ Optional properties:
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entry:
"ext_clock" (External clock provided to the card).
+- pre-power-on-delay-ms : Delay in ms before powering the card which
+ the reset-gpios (if any) are asserted
- post-power-on-delay-ms : Delay in ms after powering the card and
de-asserting the reset-gpios (if any)
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 1304160de168..cb2ba7b11383 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -26,6 +26,7 @@
struct mmc_pwrseq_simple {
struct mmc_pwrseq pwrseq;
bool clk_enabled;
+ u32 pre_power_on_delay_ms;
u32 post_power_on_delay_ms;
struct clk *ext_clk;
struct gpio_descs *reset_gpios;
@@ -60,6 +61,9 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
}
mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+
+ if (pwrseq->pre_power_on_delay_ms)
+ msleep(pwrseq->pre_power_on_delay_ms);
}
static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
@@ -117,6 +121,9 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
return PTR_ERR(pwrseq->reset_gpios);
}
+ device_property_read_u32(dev, "pre-power-on-delay-ms",
+ &pwrseq->pre_power_on_delay_ms);
+
device_property_read_u32(dev, "post-power-on-delay-ms",
&pwrseq->post_power_on_delay_ms);
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/4] mmc: pwrseq-simple: add various functionality for devices
From: Matt Ranostay @ 2016-12-02 6:17 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA
Cc: Matt Ranostay
Primarily these additions are used with wifi cards that have an
power down pin, and timing constraints betweens assertions/deassertions.
Matt Ranostay (4):
mmc: pwrseq-simple: add an optional pre-power-on-delay
mmc: pwrseq-simple: add support for power down GPIO pins
mmc: pwrseq-simple: allow inverting of off state logic
mmc: pwrseq-simple: add disable-post-power-on option
.../devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 8 ++++
drivers/mmc/core/pwrseq_simple.c | 49 +++++++++++++++++-----
2 files changed, 46 insertions(+), 11 deletions(-)
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v4] of: Fix issue where code would fall through to error case.
From: Moritz Fischer @ 2016-12-02 6:10 UTC (permalink / raw)
To: devicetree
Cc: linux-kernel, frowand.list, robh+dt, pantelis.antoniou,
Moritz Fischer
From: Moritz Fischer <mdf@kernel.org>
No longer fall through into the error case that prints out
an error if no error (err = 0) occurred.
Fixes d9181b20a83(of: Add back an error message, restructured)
Signed-off-by: Moritz Fischer <mdf@kernel.org>
Reviewed-by: Frank Rowand <frank.rowand@am.sony.com>
---
Hi Frank, Rob
sorry for the noise before.
Thanks,
Moritz
---
drivers/of/resolver.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
index 783bd09..8bf12e9 100644
--- a/drivers/of/resolver.c
+++ b/drivers/of/resolver.c
@@ -298,12 +298,12 @@ int of_resolve_phandles(struct device_node *overlay)
if (!overlay) {
pr_err("null overlay\n");
err = -EINVAL;
- goto err_out;
+ goto out;
}
if (!of_node_check_flag(overlay, OF_DETACHED)) {
pr_err("overlay not detached\n");
err = -EINVAL;
- goto err_out;
+ goto out;
}
phandle_delta = live_tree_max_phandle() + 1;
@@ -315,7 +315,7 @@ int of_resolve_phandles(struct device_node *overlay)
err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta);
if (err)
- goto err_out;
+ goto out;
overlay_fixups = NULL;
@@ -333,7 +333,7 @@ int of_resolve_phandles(struct device_node *overlay)
if (!tree_symbols) {
pr_err("no symbols in root of device tree.\n");
err = -EINVAL;
- goto err_out;
+ goto out;
}
for_each_property_of_node(overlay_fixups, prop) {
@@ -345,12 +345,12 @@ int of_resolve_phandles(struct device_node *overlay)
err = of_property_read_string(tree_symbols,
prop->name, &refpath);
if (err)
- goto err_out;
+ goto out;
refnode = of_find_node_by_path(refpath);
if (!refnode) {
err = -ENOENT;
- goto err_out;
+ goto out;
}
phandle = refnode->phandle;
@@ -361,9 +361,9 @@ int of_resolve_phandles(struct device_node *overlay)
break;
}
-err_out:
- pr_err("overlay phandle fixup failed: %d\n", err);
out:
+ if (err)
+ pr_err("overlay phandle fixup failed: %d\n", err);
of_node_put(tree_symbols);
return err;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2] arm64: dts: zx: support cpu-freq for zx296718
From: Viresh Kumar @ 2016-12-02 6:00 UTC (permalink / raw)
To: Baoyou Xie
Cc: mark.rutland, devicetree, catalin.marinas, xie.baoyou,
Will Deacon, Linux Kernel Mailing List, Rob Herring, chen.chaokai,
wang.qiang01, Jun Nie, Shawn Guo, linux-arm-kernel
In-Reply-To: <CA+DQWkzGOzn1TRa9041Jjksj-=509XWXS_U1uaaJXNydB8Apow@mail.gmail.com>
On 02-12-16, 13:58, Baoyou Xie wrote:
> + Viresh, the author of the bindings.
>
> On 2 December 2016 at 13:52, Baoyou Xie <baoyou.xie@linaro.org> wrote:
>
> > This patch adds the CPU clock phandle in CPU's node
> > and uses operating-points-v2 to register operating points.
> >
> > So it can be used by cpufreq-dt driver.
> >
> > Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> > ---
> > arch/arm64/boot/dts/zte/zx296718.dtsi | 39 ++++++++++++++++++++++++++++++
> > +++++
> > 1 file changed, 39 insertions(+)
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* Re: [PATCH v2] arm64: dts: zx: support cpu-freq for zx296718
From: Baoyou Xie @ 2016-12-02 5:58 UTC (permalink / raw)
To: Rob Herring, mark.rutland, catalin.marinas, Will Deacon,
Shawn Guo, Jun Nie, Viresh Kumar
Cc: devicetree, linux-arm-kernel, Linux Kernel Mailing List,
Baoyou Xie, xie.baoyou, chen.chaokai, wang.qiang01
In-Reply-To: <1480657956-8140-1-git-send-email-baoyou.xie@linaro.org>
[-- Attachment #1: Type: text/plain, Size: 3356 bytes --]
+ Viresh, the author of the bindings.
On 2 December 2016 at 13:52, Baoyou Xie <baoyou.xie@linaro.org> wrote:
> This patch adds the CPU clock phandle in CPU's node
> and uses operating-points-v2 to register operating points.
>
> So it can be used by cpufreq-dt driver.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> arch/arm64/boot/dts/zte/zx296718.dtsi | 39 ++++++++++++++++++++++++++++++
> +++++
> 1 file changed, 39 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi
> b/arch/arm64/boot/dts/zte/zx296718.dtsi
> index 7a1aed7..b44d1d1 100644
> --- a/arch/arm64/boot/dts/zte/zx296718.dtsi
> +++ b/arch/arm64/boot/dts/zte/zx296718.dtsi
> @@ -44,6 +44,7 @@
> #include <dt-bindings/input/input.h>
> #include <dt-bindings/interrupt-controller/arm-gic.h>
> #include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/clock/zx296718-clock.h>
>
> / {
> compatible = "zte,zx296718";
> @@ -81,6 +82,8 @@
> compatible = "arm,cortex-a53","arm,armv8";
> reg = <0x0 0x0>;
> enable-method = "psci";
> + clocks = <&topcrm A53_GATE>;
> + operating-points-v2 = <&cluster0_opp>;
> };
>
> cpu1: cpu@1 {
> @@ -88,6 +91,8 @@
> compatible = "arm,cortex-a53","arm,armv8";
> reg = <0x0 0x1>;
> enable-method = "psci";
> + clocks = <&topcrm A53_GATE>;
> + operating-points-v2 = <&cluster0_opp>;
> };
>
> cpu2: cpu@2 {
> @@ -95,6 +100,8 @@
> compatible = "arm,cortex-a53","arm,armv8";
> reg = <0x0 0x2>;
> enable-method = "psci";
> + clocks = <&topcrm A53_GATE>;
> + operating-points-v2 = <&cluster0_opp>;
> };
>
> cpu3: cpu@3 {
> @@ -102,6 +109,38 @@
> compatible = "arm,cortex-a53","arm,armv8";
> reg = <0x0 0x3>;
> enable-method = "psci";
> + clocks = <&topcrm A53_GATE>;
> + operating-points-v2 = <&cluster0_opp>;
> + };
> + };
> +
> + cluster0_opp: opp-table0 {
> + compatible = "operating-points-v2";
> + opp-shared;
> +
> + opp@500000000 {
> + opp-hz = /bits/ 64 <500000000>;
> + clock-latency-ns = <500000>;
> + };
> +
> + opp@648000000 {
> + opp-hz = /bits/ 64 <648000000>;
> + clock-latency-ns = <500000>;
> + };
> +
> + opp@800000000 {
> + opp-hz = /bits/ 64 <800000000>;
> + clock-latency-ns = <500000>;
> + };
> +
> + opp@1000000000 {
> + opp-hz = /bits/ 64 <1000000000>;
> + clock-latency-ns = <500000>;
> + };
> +
> + opp@1188000000 {
> + opp-hz = /bits/ 64 <1188000000>;
> + clock-latency-ns = <500000>;
> };
> };
>
> --
> 2.7.4
>
>
[-- Attachment #2: Type: text/html, Size: 5002 bytes --]
^ permalink raw reply
* [PATCH v2] arm64: dts: zx: support cpu-freq for zx296718
From: Baoyou Xie @ 2016-12-02 5:52 UTC (permalink / raw)
To: robh+dt, mark.rutland, catalin.marinas, will.deacon, shawnguo,
jun.nie
Cc: devicetree, linux-arm-kernel, linux-kernel, baoyou.xie,
xie.baoyou, chen.chaokai, wang.qiang01
This patch adds the CPU clock phandle in CPU's node
and uses operating-points-v2 to register operating points.
So it can be used by cpufreq-dt driver.
Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
---
arch/arm64/boot/dts/zte/zx296718.dtsi | 39 +++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi b/arch/arm64/boot/dts/zte/zx296718.dtsi
index 7a1aed7..b44d1d1 100644
--- a/arch/arm64/boot/dts/zte/zx296718.dtsi
+++ b/arch/arm64/boot/dts/zte/zx296718.dtsi
@@ -44,6 +44,7 @@
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/zx296718-clock.h>
/ {
compatible = "zte,zx296718";
@@ -81,6 +82,8 @@
compatible = "arm,cortex-a53","arm,armv8";
reg = <0x0 0x0>;
enable-method = "psci";
+ clocks = <&topcrm A53_GATE>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu1: cpu@1 {
@@ -88,6 +91,8 @@
compatible = "arm,cortex-a53","arm,armv8";
reg = <0x0 0x1>;
enable-method = "psci";
+ clocks = <&topcrm A53_GATE>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu2: cpu@2 {
@@ -95,6 +100,8 @@
compatible = "arm,cortex-a53","arm,armv8";
reg = <0x0 0x2>;
enable-method = "psci";
+ clocks = <&topcrm A53_GATE>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu3: cpu@3 {
@@ -102,6 +109,38 @@
compatible = "arm,cortex-a53","arm,armv8";
reg = <0x0 0x3>;
enable-method = "psci";
+ clocks = <&topcrm A53_GATE>;
+ operating-points-v2 = <&cluster0_opp>;
+ };
+ };
+
+ cluster0_opp: opp-table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp@500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ clock-latency-ns = <500000>;
+ };
+
+ opp@648000000 {
+ opp-hz = /bits/ 64 <648000000>;
+ clock-latency-ns = <500000>;
+ };
+
+ opp@800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ clock-latency-ns = <500000>;
+ };
+
+ opp@1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ clock-latency-ns = <500000>;
+ };
+
+ opp@1188000000 {
+ opp-hz = /bits/ 64 <1188000000>;
+ clock-latency-ns = <500000>;
};
};
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 3/3] ARM: dts: sunxi: enable SDIO Wi-Fi on Orange Pi Zero
From: Alexey Kardashevskiy @ 2016-12-02 4:47 UTC (permalink / raw)
To: Andre Przywara, Icenowy Zheng
Cc: Mark Rutland, devicetree, Vishnu Patekar, Arnd Bergmann,
Jonathan Corbet, linux-doc, Russell King, LKML, Hans de Goede,
Chen-Yu Tsai, Maxime Ripard, linux-arm-kernel
In-Reply-To: <da84928a-25a2-1615-1d8e-e6570b1a6323@arm.com>
On 30/11/16 20:25, Andre Przywara wrote:
> Hi,
>
> On 29/11/16 10:19, Icenowy Zheng wrote:
>>
>> 2016年11月29日 15:16于 Alexey Kardashevskiy <aik@ozlabs.ru>写道:
>>>
>>>
>>>
>>> On Wed, Nov 23, 2016 at 6:59 PM, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> On Tue, Nov 22, 2016 at 12:24:21AM +0800, Icenowy Zheng wrote:
>>>>> There's a Allwinner's XR819 SDIO Wi-Fi module soldered on the board of
>>>>> Orange Pi Zero, which used a dedicated regulator to power.
>>>>>
>>>>> Add the device tree node of the regulator, the enable gpio (with
>>>>> mmc-pwrseq) and the sdio controller.
>>>>>
>>>>> There's a out-of-tree driver tested to work with this device tree.
>>>
>>>
>>> btw could you please give a pointer where to find a XR819 driver for
>> relatively recent kernel (4.8 may be, just not 3.4)? Thanks.
>>
>> https://github.com/Icenowy/xradio
>
> I was just curious, so pulled your tree and tried to just compile it. It
> still threw warnings at me for ARM, and even more so for arm64.
> I fixed all of them and put that on my github[1]. Feel free to just pick
> them from there or wait till I manage to clean them up and send you a
> pull request.
> And also just a a test, I quickly put it in drivers/net/wireless/xradio,
> where it compiled fine after registering it with the upper level Kconfig
> and Makefile.
>
> And while looking at it: This looks like typical AW code, not even
> remotely upstreameable and probably far too complicated. Enabling some
> Kconfig options made it complain about missing functions.
> Has anyone checked if this is close to an existing WiFi chip? That
> wouldn't be a first ;-)
>
> Cheers,
> Andre.
>
> [1] https://github.com/apritzel/xradio/commits/quickfixes
>
I just tried this branch + 4.9.0-rc7 but I am still getting:
[ 0.960429] [XRADIO] Driver Label:L34M.01.08.0002
[ 0.965233] [XRADIO] Allocated hw_priv @ df6a4dc0
[ 3.038180] [SBUS_ERR] sdio probe timeout!
[ 3.042288] [XRADIO_ERR] sbus_sdio_init failed
I am missing huge amount of SDIO knowledge. Or the device tree is wrong.
Any idea?
--
Alexey
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2 2/2] dt-bindings: Add DT bindings info for FlexRM ring manager
From: Anup Patel @ 2016-12-02 4:38 UTC (permalink / raw)
To: Jassi Brar, Rob Herring
Cc: Mark Rutland, Ray Jui, Scott Branden, Pramod KUMAR, Rob Rice,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Anup Patel
In-Reply-To: <1480653536-5551-1-git-send-email-anup.patel-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
This patch adds device tree bindings document for the FlexRM
ring manager found on Broadcom iProc SoCs.
Reviewed-by: Ray Jui <ray.jui-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
Reviewed-by: Scott Branden <scott.branden-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
Signed-off-by: Anup Patel <anup.patel-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
---
.../bindings/mailbox/brcm,iproc-flexrm-mbox.txt | 60 ++++++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt
diff --git a/Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt b/Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt
new file mode 100644
index 0000000..e81f116
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt
@@ -0,0 +1,60 @@
+Broadcom FlexRM Ring Manager
+============================
+The Broadcom FlexRM ring manager provides a set of rings which can be
+used to submit work to offload engines. An SoC may have multiple FlexRM
+hardware blocks. There is one device tree entry per FlexRM block. The
+FlexRM driver will create a mailbox-controller instance for given FlexRM
+hardware block where each mailbox channel is a separate FlexRM ring.
+
+Required properties:
+--------------------
+- compatible: Should be "brcm,iproc-flexrm-mbox"
+- reg: Specifies base physical address and size of the FlexRM
+ ring registers
+- msi-parent: Phandles (and potential Device IDs) to MSI controllers
+ The FlexRM engine will send MSIs (instead of wired
+ interrupts) to CPU. There is one MSI for each FlexRM ring.
+ Refer devicetree/bindings/interrupt-controller/msi.txt
+- #mbox-cells: Specifies the number of cells needed to encode a mailbox
+ channel. This should be 3.
+
+ The 1st cell is the mailbox channel number.
+
+ The 2nd cell contains MSI completion threshold. This is the
+ number of completion messages for which FlexRM will inject
+ one MSI interrupt to CPU.
+
+ The 3nd cell contains MSI timer value representing time for
+ which FlexRM will wait to accumulate N completion messages
+ where N is the value specified by 2nd cell above. If FlexRM
+ does not get required number of completion messages in time
+ specified by this cell then it will inject one MSI interrupt
+ to CPU provided atleast one completion message is available.
+
+Optional properties:
+--------------------
+- dma-coherent: Present if DMA operations made by the FlexRM engine (such
+ as DMA descriptor access, access to buffers pointed by DMA
+ descriptors and read/write pointer updates to DDR) are
+ cache coherent with the CPU.
+
+Example:
+--------
+crypto_mbox: mbox@67000000 {
+ compatible = "brcm,flexrm-mbox";
+ reg = <0x67000000 0x200000>;
+ msi-parent = <&gic_its 0x7f00>;
+ #mbox-cells = <3>;
+};
+
+crypto_client {
+ ...
+ mboxes = <&crypto_mbox 0 0x1 0xffff>,
+ <&crypto_mbox 1 0x1 0xffff>,
+ <&crypto_mbox 16 0x1 0xffff>,
+ <&crypto_mbox 17 0x1 0xffff>,
+ <&crypto_mbox 30 0x1 0xffff>,
+ <&crypto_mbox 31 0x1 0xffff>;
+ };
+ ...
+};
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 1/2] mailbox: Add driver for Broadcom FlexRM ring manager
From: Anup Patel @ 2016-12-02 4:38 UTC (permalink / raw)
To: Jassi Brar, Rob Herring
Cc: Mark Rutland, Ray Jui, Scott Branden, Pramod KUMAR, Rob Rice,
devicetree, linux-kernel, linux-arm-kernel,
bcm-kernel-feedback-list, Anup Patel
In-Reply-To: <1480653536-5551-1-git-send-email-anup.patel@broadcom.com>
Some of the Broadcom iProc SoCs have FlexRM ring manager
which provides a ring-based programming interface to various
offload engines (e.g. RAID, Crypto, etc).
This patch adds a common mailbox driver for Broadcom FlexRM
ring manager which can be shared by various offload engine
drivers (implemented as mailbox clients).
Reviewed-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Scott Branden <scott.branden@broadcom.com>
Reviewed-by: Pramod KUMAR <pramod.kumar@broadcom.com>
Signed-off-by: Anup Patel <anup.patel@broadcom.com>
---
drivers/mailbox/Kconfig | 11 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/mailbox-flexrm/Makefile | 6 +
drivers/mailbox/mailbox-flexrm/flexrm-desc.c | 764 ++++++++++++++++++++++++
drivers/mailbox/mailbox-flexrm/flexrm-desc.h | 47 ++
drivers/mailbox/mailbox-flexrm/flexrm-main.c | 829 +++++++++++++++++++++++++++
include/linux/mailbox/brcm-message.h | 14 +-
7 files changed, 1669 insertions(+), 4 deletions(-)
create mode 100644 drivers/mailbox/mailbox-flexrm/Makefile
create mode 100644 drivers/mailbox/mailbox-flexrm/flexrm-desc.c
create mode 100644 drivers/mailbox/mailbox-flexrm/flexrm-desc.h
create mode 100644 drivers/mailbox/mailbox-flexrm/flexrm-main.c
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 11eebfe..bfeced1 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -143,4 +143,15 @@ config BCM_PDC_MBOX
Mailbox implementation for the Broadcom PDC ring manager,
which provides access to various offload engines on Broadcom
SoCs. Say Y here if you want to use the Broadcom PDC.
+
+config BCM_FLEXRM_MBOX
+ tristate "Broadcom FlexRM Mailbox"
+ depends on ARM64 || COMPILE_TEST
+ depends on HAS_DMA
+ select GENERIC_MSI_IRQ_DOMAIN
+ default ARCH_BCM_IPROC
+ help
+ Mailbox implementation of the Broadcom FlexRM ring manager,
+ which provides access to various offload engines on Broadcom
+ SoCs. Say Y here if you want to use the Broadcom FlexRM.
endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index ace6fed..9594266 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -29,3 +29,5 @@ obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o
obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o
obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o
+
+obj-$(CONFIG_BCM_FLEXRM_MBOX) += mailbox-flexrm/
diff --git a/drivers/mailbox/mailbox-flexrm/Makefile b/drivers/mailbox/mailbox-flexrm/Makefile
new file mode 100644
index 0000000..f5bf069
--- /dev/null
+++ b/drivers/mailbox/mailbox-flexrm/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Broadcom FlexRM Mailbox Driver.
+#
+
+flexrm-mbox-objs := flexrm-main.o flexrm-desc.o
+obj-$(CONFIG_BCM_FLEXRM_MBOX) += flexrm-mbox.o
diff --git a/drivers/mailbox/mailbox-flexrm/flexrm-desc.c b/drivers/mailbox/mailbox-flexrm/flexrm-desc.c
new file mode 100644
index 0000000..b0449eb
--- /dev/null
+++ b/drivers/mailbox/mailbox-flexrm/flexrm-desc.c
@@ -0,0 +1,764 @@
+/* Broadcom FlexRM Mailbox Driver
+ *
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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.
+ *
+ * FlexRM descriptor library
+ */
+
+#include <asm/barrier.h>
+#include <asm/byteorder.h>
+#include <linux/dma-mapping.h>
+#include <linux/printk.h>
+
+#include "flexrm-desc.h"
+
+/* Completion descriptor format */
+#define CMPL_OPAQUE_SHIFT 0
+#define CMPL_OPAQUE_MASK 0xffff
+#define CMPL_ENGINE_STATUS_SHIFT 16
+#define CMPL_ENGINE_STATUS_MASK 0xffff
+#define CMPL_DME_STATUS_SHIFT 32
+#define CMPL_DME_STATUS_MASK 0xffff
+#define CMPL_RM_STATUS_SHIFT 48
+#define CMPL_RM_STATUS_MASK 0xffff
+
+/* Completion DME status code */
+#define DME_STATUS_MEM_COR_ERR BIT(0)
+#define DME_STATUS_MEM_UCOR_ERR BIT(1)
+#define DME_STATUS_FIFO_UNDERFLOW BIT(2)
+#define DME_STATUS_FIFO_OVERFLOW BIT(3)
+#define DME_STATUS_RRESP_ERR BIT(4)
+#define DME_STATUS_BRESP_ERR BIT(5)
+#define DME_STATUS_ERROR_MASK (DME_STATUS_MEM_COR_ERR | \
+ DME_STATUS_MEM_UCOR_ERR | \
+ DME_STATUS_FIFO_UNDERFLOW | \
+ DME_STATUS_FIFO_OVERFLOW | \
+ DME_STATUS_RRESP_ERR | \
+ DME_STATUS_BRESP_ERR)
+
+/* Completion RM status code */
+#define RM_STATUS_CODE_SHIFT 0
+#define RM_STATUS_CODE_MASK 0x3ff
+#define RM_STATUS_CODE_GOOD 0x0
+#define RM_STATUS_CODE_AE_TIMEOUT 0x3ff
+
+/* General descriptor format */
+#define DESC_TYPE_SHIFT 60
+#define DESC_TYPE_MASK 0xf
+#define DESC_PAYLOAD_SHIFT 0
+#define DESC_PAYLOAD_MASK 0x0fffffffffffffff
+
+/* Null descriptor format */
+#define NULL_TYPE 0
+#define NULL_TOGGLE_SHIFT 58
+#define NULL_TOGGLE_MASK 0x1
+
+/* Header descriptor format */
+#define HEADER_TYPE 1
+#define HEADER_TOGGLE_SHIFT 58
+#define HEADER_TOGGLE_MASK 0x1
+#define HEADER_ENDPKT_SHIFT 57
+#define HEADER_ENDPKT_MASK 0x1
+#define HEADER_STARTPKT_SHIFT 56
+#define HEADER_STARTPKT_MASK 0x1
+#define HEADER_BDCOUNT_SHIFT 36
+#define HEADER_BDCOUNT_MASK 0x1f
+#define HEADER_BDCOUNT_MAX HEADER_BDCOUNT_MASK
+#define HEADER_FLAGS_SHIFT 16
+#define HEADER_FLAGS_MASK 0xffff
+#define HEADER_OPAQUE_SHIFT 0
+#define HEADER_OPAQUE_MASK 0xffff
+
+/* Source (SRC) descriptor format */
+#define SRC_TYPE 2
+#define SRC_LENGTH_SHIFT 44
+#define SRC_LENGTH_MASK 0xffff
+#define SRC_ADDR_SHIFT 0
+#define SRC_ADDR_MASK 0x00000fffffffffff
+
+/* Destination (DST) descriptor format */
+#define DST_TYPE 3
+#define DST_LENGTH_SHIFT 44
+#define DST_LENGTH_MASK 0xffff
+#define DST_ADDR_SHIFT 0
+#define DST_ADDR_MASK 0x00000fffffffffff
+
+/* Immediate (IMM) descriptor format */
+#define IMM_TYPE 4
+#define IMM_DATA_SHIFT 0
+#define IMM_DATA_MASK 0x0fffffffffffffff
+
+/* Next pointer (NPTR) descriptor format */
+#define NPTR_TYPE 5
+#define NPTR_TOGGLE_SHIFT 58
+#define NPTR_TOGGLE_MASK 0x1
+#define NPTR_ADDR_SHIFT 0
+#define NPTR_ADDR_MASK 0x00000fffffffffff
+
+/* Mega source (MSRC) descriptor format */
+#define MSRC_TYPE 6
+#define MSRC_LENGTH_SHIFT 44
+#define MSRC_LENGTH_MASK 0xffff
+#define MSRC_ADDR_SHIFT 0
+#define MSRC_ADDR_MASK 0x00000fffffffffff
+
+/* Mega destination (MDST) descriptor format */
+#define MDST_TYPE 7
+#define MDST_LENGTH_SHIFT 44
+#define MDST_LENGTH_MASK 0xffff
+#define MDST_ADDR_SHIFT 0
+#define MDST_ADDR_MASK 0x00000fffffffffff
+
+/* Source with tlast (SRCT) descriptor format */
+#define SRCT_TYPE 8
+#define SRCT_LENGTH_SHIFT 44
+#define SRCT_LENGTH_MASK 0xffff
+#define SRCT_ADDR_SHIFT 0
+#define SRCT_ADDR_MASK 0x00000fffffffffff
+
+/* Destination with tlast (DSTT) descriptor format */
+#define DSTT_TYPE 9
+#define DSTT_LENGTH_SHIFT 44
+#define DSTT_LENGTH_MASK 0xffff
+#define DSTT_ADDR_SHIFT 0
+#define DSTT_ADDR_MASK 0x00000fffffffffff
+
+/* Immediate with tlast (IMMT) descriptor format */
+#define IMMT_TYPE 10
+#define IMMT_DATA_SHIFT 0
+#define IMMT_DATA_MASK 0x0fffffffffffffff
+
+/* Descriptor helper macros */
+#define DESC_DEC(_d, _s, _m) (((_d) >> (_s)) & (_m))
+#define DESC_ENC(_d, _v, _s, _m) \
+ do { \
+ (_d) &= ~((u64)(_m) << (_s)); \
+ (_d) |= (((u64)(_v) & (_m)) << (_s)); \
+ } while (0)
+
+u64 flexrm_read_desc(void *desc_ptr)
+{
+ return le64_to_cpu(*((u64 *)desc_ptr));
+}
+
+void flexrm_write_desc(void *desc_ptr, u64 desc)
+{
+ *((u64 *)desc_ptr) = cpu_to_le64(desc);
+}
+
+u32 flexrm_cmpl_desc_to_reqid(u64 cmpl_desc)
+{
+ return (u32)(cmpl_desc & CMPL_OPAQUE_MASK);
+}
+
+int flexrm_cmpl_desc_to_error(u64 cmpl_desc)
+{
+ u32 status;
+
+ status = DESC_DEC(cmpl_desc, CMPL_DME_STATUS_SHIFT,
+ CMPL_DME_STATUS_MASK);
+ if (status & DME_STATUS_ERROR_MASK)
+ return -EIO;
+
+ status = DESC_DEC(cmpl_desc, CMPL_RM_STATUS_SHIFT,
+ CMPL_RM_STATUS_MASK);
+ status &= RM_STATUS_CODE_MASK;
+ if (status == RM_STATUS_CODE_AE_TIMEOUT)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+bool flexrm_is_next_table_desc(void *desc_ptr)
+{
+ u64 desc = flexrm_read_desc(desc_ptr);
+ u32 type = DESC_DEC(desc, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+
+ return (type == NPTR_TYPE) ? true : false;
+}
+
+u64 flexrm_next_table_desc(u32 toggle, dma_addr_t next_addr)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, NPTR_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, toggle, NPTR_TOGGLE_SHIFT, NPTR_TOGGLE_MASK);
+ DESC_ENC(desc, next_addr, NPTR_ADDR_SHIFT, NPTR_ADDR_MASK);
+
+ return desc;
+}
+
+u64 flexrm_null_desc(u32 toggle)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, NULL_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, toggle, NULL_TOGGLE_SHIFT, NULL_TOGGLE_MASK);
+
+ return desc;
+}
+
+u32 flexrm_estimate_header_desc_count(u32 nhcnt)
+{
+ u32 hcnt = nhcnt / HEADER_BDCOUNT_MAX;
+
+ if (!(nhcnt % HEADER_BDCOUNT_MAX))
+ hcnt += 1;
+
+ return hcnt;
+}
+
+static void flexrm_flip_header_toogle(void *desc_ptr)
+{
+ u64 desc = flexrm_read_desc(desc_ptr);
+
+ if (desc & ((u64)0x1 << HEADER_TOGGLE_SHIFT))
+ desc &= ~((u64)0x1 << HEADER_TOGGLE_SHIFT);
+ else
+ desc |= ((u64)0x1 << HEADER_TOGGLE_SHIFT);
+
+ flexrm_write_desc(desc_ptr, desc);
+}
+
+static u64 flexrm_header_desc(u32 toggle, u32 startpkt, u32 endpkt,
+ u32 bdcount, u32 flags, u32 opaque)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, HEADER_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, toggle, HEADER_TOGGLE_SHIFT, HEADER_TOGGLE_MASK);
+ DESC_ENC(desc, startpkt, HEADER_STARTPKT_SHIFT, HEADER_STARTPKT_MASK);
+ DESC_ENC(desc, endpkt, HEADER_ENDPKT_SHIFT, HEADER_ENDPKT_MASK);
+ DESC_ENC(desc, bdcount, HEADER_BDCOUNT_SHIFT, HEADER_BDCOUNT_MASK);
+ DESC_ENC(desc, flags, HEADER_FLAGS_SHIFT, HEADER_FLAGS_MASK);
+ DESC_ENC(desc, opaque, HEADER_OPAQUE_SHIFT, HEADER_OPAQUE_MASK);
+
+ return desc;
+}
+
+static void flexrm_enqueue_desc(u32 nhpos, u32 nhcnt, u32 reqid,
+ u64 desc, void **desc_ptr, u32 *toggle,
+ void *start_desc, void *end_desc)
+{
+ u64 d;
+ u32 nhavail, _toggle, _startpkt, _endpkt, _bdcount;
+
+ /* Sanity check */
+ if (nhcnt <= nhpos)
+ return;
+
+ /*
+ * Each request or packet start with a HEADER descriptor followed
+ * by one or more non-HEADER descriptors (SRC, SRCT, MSRC, DST,
+ * DSTT, MDST, IMM, and IMMT). The number of non-HEADER descriptors
+ * following a HEADER descriptor is represented by BDCOUNT field
+ * of HEADER descriptor. The max value of BDCOUNT field is 31 which
+ * means we can only have 31 non-HEADER descriptors following one
+ * HEADER descriptor.
+ *
+ * In general use, number of non-HEADER descriptors can easily go
+ * beyond 31. To tackle this situation, we have packet (or request)
+ * extenstion bits (STARTPKT and ENDPKT) in the HEADER descriptor.
+ *
+ * To use packet extension, the first HEADER descriptor of request
+ * (or packet) will have STARTPKT=1 and ENDPKT=0. The intermediate
+ * HEADER descriptors will have STARTPKT=0 and ENDPKT=0. The last
+ * HEADER descriptor will have STARTPKT=0 and ENDPKT=1. Also, the
+ * TOGGLE bit of the first HEADER will be set to invalid state to
+ * ensure that FlexRM does not start fetching descriptors till all
+ * descriptors are enqueued. The user of this function will flip
+ * the TOGGLE bit of first HEADER after all descriptors are
+ * enqueued.
+ */
+
+ if ((nhpos % HEADER_BDCOUNT_MAX == 0) && (nhcnt - nhpos)) {
+ /* Prepare the header descriptor */
+ nhavail = (nhcnt - nhpos);
+ _toggle = (nhpos == 0) ? !(*toggle) : (*toggle);
+ _startpkt = (nhpos == 0) ? 0x1 : 0x0;
+ _endpkt = (nhavail <= HEADER_BDCOUNT_MAX) ? 0x1 : 0x0;
+ _bdcount = (nhavail <= HEADER_BDCOUNT_MAX) ?
+ nhavail : HEADER_BDCOUNT_MAX;
+ if (nhavail <= HEADER_BDCOUNT_MAX)
+ _bdcount = nhavail;
+ else
+ _bdcount = HEADER_BDCOUNT_MAX;
+ d = flexrm_header_desc(_toggle, _startpkt, _endpkt,
+ _bdcount, 0x0, reqid);
+
+ /* Write header descriptor */
+ flexrm_write_desc(*desc_ptr, d);
+
+ /* Point to next descriptor */
+ *desc_ptr += sizeof(desc);
+ if (*desc_ptr == end_desc)
+ *desc_ptr = start_desc;
+
+ /* Skip next pointer descriptors */
+ while (flexrm_is_next_table_desc(*desc_ptr)) {
+ *toggle = (*toggle) ? 0 : 1;
+ *desc_ptr += sizeof(desc);
+ if (*desc_ptr == end_desc)
+ *desc_ptr = start_desc;
+ }
+ }
+
+ /* Write desired descriptor */
+ flexrm_write_desc(*desc_ptr, desc);
+
+ /* Point to next descriptor */
+ *desc_ptr += sizeof(desc);
+ if (*desc_ptr == end_desc)
+ *desc_ptr = start_desc;
+
+ /* Skip next pointer descriptors */
+ while (flexrm_is_next_table_desc(*desc_ptr)) {
+ *toggle = (*toggle) ? 0 : 1;
+ *desc_ptr += sizeof(desc);
+ if (*desc_ptr == end_desc)
+ *desc_ptr = start_desc;
+ }
+}
+
+static u64 flexrm_src_desc(dma_addr_t addr, unsigned int length)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, SRC_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, length, SRC_LENGTH_SHIFT, SRC_LENGTH_MASK);
+ DESC_ENC(desc, addr, SRC_ADDR_SHIFT, SRC_ADDR_MASK);
+
+ return desc;
+}
+
+static u64 flexrm_msrc_desc(dma_addr_t addr, unsigned int length_div_16)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, MSRC_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, length_div_16, MSRC_LENGTH_SHIFT, MSRC_LENGTH_MASK);
+ DESC_ENC(desc, addr, MSRC_ADDR_SHIFT, MSRC_ADDR_MASK);
+
+ return desc;
+}
+
+static u64 flexrm_dst_desc(dma_addr_t addr, unsigned int length)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, DST_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, length, DST_LENGTH_SHIFT, DST_LENGTH_MASK);
+ DESC_ENC(desc, addr, DST_ADDR_SHIFT, DST_ADDR_MASK);
+
+ return desc;
+}
+
+static u64 flexrm_mdst_desc(dma_addr_t addr, unsigned int length_div_16)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, MDST_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, length_div_16, MDST_LENGTH_SHIFT, MDST_LENGTH_MASK);
+ DESC_ENC(desc, addr, MDST_ADDR_SHIFT, MDST_ADDR_MASK);
+
+ return desc;
+}
+
+static u64 flexrm_imm_desc(u64 data)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, IMM_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, data, IMM_DATA_SHIFT, IMM_DATA_MASK);
+
+ return desc;
+}
+
+static u64 flexrm_srct_desc(dma_addr_t addr, unsigned int length)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, SRCT_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, length, SRCT_LENGTH_SHIFT, SRCT_LENGTH_MASK);
+ DESC_ENC(desc, addr, SRCT_ADDR_SHIFT, SRCT_ADDR_MASK);
+
+ return desc;
+}
+
+static u64 flexrm_dstt_desc(dma_addr_t addr, unsigned int length)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, DSTT_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, length, DSTT_LENGTH_SHIFT, DSTT_LENGTH_MASK);
+ DESC_ENC(desc, addr, DSTT_ADDR_SHIFT, DSTT_ADDR_MASK);
+
+ return desc;
+}
+
+static u64 flexrm_immt_desc(u64 data)
+{
+ u64 desc = 0;
+
+ DESC_ENC(desc, IMMT_TYPE, DESC_TYPE_SHIFT, DESC_TYPE_MASK);
+ DESC_ENC(desc, data, IMMT_DATA_SHIFT, IMMT_DATA_MASK);
+
+ return desc;
+}
+
+static bool flexrm_spu_sanity_check(struct brcm_message *msg)
+{
+ struct scatterlist *sg;
+
+ if (!msg->spu.src || !msg->spu.dst)
+ return false;
+ for (sg = msg->spu.src; sg; sg = sg_next(sg)) {
+ if (sg->length & 0xf) {
+ if (sg->length > SRC_LENGTH_MASK)
+ return false;
+ } else {
+ if (sg->length > (MSRC_LENGTH_MASK * 16))
+ return false;
+ }
+ }
+ for (sg = msg->spu.dst; sg; sg = sg_next(sg)) {
+ if (sg->length & 0xf) {
+ if (sg->length > DST_LENGTH_MASK)
+ return false;
+ } else {
+ if (sg->length > (MDST_LENGTH_MASK * 16))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static u32 flexrm_spu_estimate_nonheader_desc_count(struct brcm_message *msg)
+{
+ u32 cnt = 0;
+ unsigned int dst_target = 0;
+ struct scatterlist *src_sg = msg->spu.src, *dst_sg = msg->spu.dst;
+
+ while (src_sg || dst_sg) {
+ if (src_sg) {
+ cnt++;
+ dst_target = src_sg->length;
+ src_sg = sg_next(src_sg);
+ } else
+ dst_target = UINT_MAX;
+
+ while (dst_target && dst_sg) {
+ cnt++;
+ if (dst_sg->length < dst_target)
+ dst_target -= dst_sg->length;
+ else
+ dst_target = 0;
+ dst_sg = sg_next(dst_sg);
+ }
+ }
+
+ return cnt;
+}
+
+static int flexrm_spu_dma_map(struct device *dev, struct brcm_message *msg)
+{
+ int rc;
+
+ rc = dma_map_sg(dev, msg->spu.src, sg_nents(msg->spu.src),
+ DMA_TO_DEVICE);
+ if (rc < 0)
+ return rc;
+
+ rc = dma_map_sg(dev, msg->spu.dst, sg_nents(msg->spu.dst),
+ DMA_FROM_DEVICE);
+ if (rc < 0) {
+ dma_unmap_sg(dev, msg->spu.src, sg_nents(msg->spu.src),
+ DMA_TO_DEVICE);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void flexrm_spu_dma_unmap(struct device *dev, struct brcm_message *msg)
+{
+ dma_unmap_sg(dev, msg->spu.dst, sg_nents(msg->spu.dst),
+ DMA_FROM_DEVICE);
+ dma_unmap_sg(dev, msg->spu.src, sg_nents(msg->spu.src),
+ DMA_TO_DEVICE);
+}
+
+static void *flexrm_spu_write_descs(struct brcm_message *msg, u32 nhcnt,
+ u32 reqid, void *desc_ptr, u32 toggle,
+ void *start_desc, void *end_desc)
+{
+ u64 d;
+ u32 nhpos = 0;
+ void *orig_desc_ptr = desc_ptr;
+ unsigned int dst_target = 0;
+ struct scatterlist *src_sg = msg->spu.src, *dst_sg = msg->spu.dst;
+
+ while (src_sg || dst_sg) {
+ if (src_sg) {
+ if (sg_dma_len(src_sg) & 0xf)
+ d = flexrm_src_desc(sg_dma_address(src_sg),
+ sg_dma_len(src_sg));
+ else
+ d = flexrm_msrc_desc(sg_dma_address(src_sg),
+ sg_dma_len(src_sg)/16);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ dst_target = sg_dma_len(src_sg);
+ src_sg = sg_next(src_sg);
+ } else
+ dst_target = UINT_MAX;
+
+ while (dst_target && dst_sg) {
+ if (sg_dma_len(dst_sg) & 0xf)
+ d = flexrm_dst_desc(sg_dma_address(dst_sg),
+ sg_dma_len(dst_sg));
+ else
+ d = flexrm_mdst_desc(sg_dma_address(dst_sg),
+ sg_dma_len(dst_sg)/16);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ if (sg_dma_len(dst_sg) < dst_target)
+ dst_target -= sg_dma_len(dst_sg);
+ else
+ dst_target = 0;
+ dst_sg = sg_next(dst_sg);
+ }
+ }
+
+ /* Null descriptor with invalid toggle bit */
+ flexrm_write_desc(desc_ptr, flexrm_null_desc(!toggle));
+
+ /* Ensure that descriptors have been written to memory */
+ wmb();
+
+ /* Flip toggle bit in header */
+ flexrm_flip_header_toogle(orig_desc_ptr);
+
+ return desc_ptr;
+}
+
+static bool flexrm_sba_sanity_check(struct brcm_message *msg)
+{
+ u32 i;
+
+ if (!msg->sba.cmds || !msg->sba.cmds_count)
+ return false;
+
+ for (i = 0; i < msg->sba.cmds_count; i++) {
+ if (((msg->sba.cmds[i].flags & BRCM_SBA_CMD_TYPE_B) ||
+ (msg->sba.cmds[i].flags & BRCM_SBA_CMD_TYPE_C)) &&
+ (msg->sba.cmds[i].flags & BRCM_SBA_CMD_HAS_OUTPUT))
+ return false;
+ if ((msg->sba.cmds[i].flags & BRCM_SBA_CMD_TYPE_B) &&
+ (msg->sba.cmds[i].data_len > SRCT_LENGTH_MASK))
+ return false;
+ if ((msg->sba.cmds[i].flags & BRCM_SBA_CMD_TYPE_C) &&
+ (msg->sba.cmds[i].data_len > SRCT_LENGTH_MASK))
+ return false;
+ if ((msg->sba.cmds[i].flags & BRCM_SBA_CMD_HAS_RESP) &&
+ (msg->sba.cmds[i].resp_len > DSTT_LENGTH_MASK))
+ return false;
+ if ((msg->sba.cmds[i].flags & BRCM_SBA_CMD_HAS_OUTPUT) &&
+ (msg->sba.cmds[i].data_len > DSTT_LENGTH_MASK))
+ return false;
+ }
+
+ return true;
+}
+
+static u32 flexrm_sba_estimate_nonheader_desc_count(struct brcm_message *msg)
+{
+ u32 i, cnt;
+
+ cnt = 0;
+ for (i = 0; i < msg->sba.cmds_count; i++) {
+ cnt++;
+
+ if ((msg->sba.cmds[i].flags & BRCM_SBA_CMD_TYPE_B) ||
+ (msg->sba.cmds[i].flags & BRCM_SBA_CMD_TYPE_C))
+ cnt++;
+
+ if (msg->sba.cmds[i].flags & BRCM_SBA_CMD_HAS_RESP)
+ cnt++;
+
+ if (msg->sba.cmds[i].flags & BRCM_SBA_CMD_HAS_OUTPUT)
+ cnt++;
+ }
+
+ return cnt;
+}
+
+static void *flexrm_sba_write_descs(struct brcm_message *msg, u32 nhcnt,
+ u32 reqid, void *desc_ptr, u32 toggle,
+ void *start_desc, void *end_desc)
+{
+ u64 d;
+ u32 i, nhpos = 0;
+ struct brcm_sba_command *c;
+ void *orig_desc_ptr = desc_ptr;
+
+ /* Convert SBA commands into descriptors */
+ for (i = 0; i < msg->sba.cmds_count; i++) {
+ c = &msg->sba.cmds[i];
+
+ if ((c->flags & BRCM_SBA_CMD_HAS_RESP) &&
+ (c->flags & BRCM_SBA_CMD_HAS_OUTPUT)) {
+ /* Destination response descriptor */
+ d = flexrm_dst_desc(c->resp, c->resp_len);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ } else if (c->flags & BRCM_SBA_CMD_HAS_RESP) {
+ /* Destination response with tlast descriptor */
+ d = flexrm_dstt_desc(c->resp, c->resp_len);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ }
+
+ if (c->flags & BRCM_SBA_CMD_HAS_OUTPUT) {
+ /* Destination with tlast descriptor */
+ d = flexrm_dstt_desc(c->data, c->data_len);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ }
+
+ if (c->flags & BRCM_SBA_CMD_TYPE_B) {
+ /* Command as immediate descriptor */
+ d = flexrm_imm_desc(c->cmd);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ } else {
+ /* Command as immediate descriptor with tlast */
+ d = flexrm_immt_desc(c->cmd);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ }
+
+ if ((c->flags & BRCM_SBA_CMD_TYPE_B) ||
+ (c->flags & BRCM_SBA_CMD_TYPE_C)) {
+ /* Source with tlast descriptor */
+ d = flexrm_srct_desc(c->data, c->data_len);
+ flexrm_enqueue_desc(nhpos, nhcnt, reqid,
+ d, &desc_ptr, &toggle,
+ start_desc, end_desc);
+ nhpos++;
+ }
+ }
+
+ /* Null descriptor with invalid toggle bit */
+ flexrm_write_desc(desc_ptr, flexrm_null_desc(!toggle));
+
+ /* Ensure that descriptors have been written to memory */
+ wmb();
+
+ /* Flip toggle bit in header */
+ flexrm_flip_header_toogle(orig_desc_ptr);
+
+ return desc_ptr;
+}
+
+bool flexrm_sanity_check(struct brcm_message *msg)
+{
+ if (!msg)
+ return false;
+
+ switch (msg->type) {
+ case BRCM_MESSAGE_SPU:
+ return flexrm_spu_sanity_check(msg);
+ case BRCM_MESSAGE_SBA:
+ return flexrm_sba_sanity_check(msg);
+ default:
+ return false;
+ };
+}
+
+u32 flexrm_estimate_nonheader_desc_count(struct brcm_message *msg)
+{
+ if (!msg)
+ return 0;
+
+ switch (msg->type) {
+ case BRCM_MESSAGE_SPU:
+ return flexrm_spu_estimate_nonheader_desc_count(msg);
+ case BRCM_MESSAGE_SBA:
+ return flexrm_sba_estimate_nonheader_desc_count(msg);
+ default:
+ return 0;
+ };
+}
+
+int flexrm_dma_map(struct device *dev, struct brcm_message *msg)
+{
+ if (!dev || !msg)
+ return -EINVAL;
+
+ switch (msg->type) {
+ case BRCM_MESSAGE_SPU:
+ return flexrm_spu_dma_map(dev, msg);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void flexrm_dma_unmap(struct device *dev, struct brcm_message *msg)
+{
+ if (!dev || !msg)
+ return;
+
+ switch (msg->type) {
+ case BRCM_MESSAGE_SPU:
+ flexrm_spu_dma_unmap(dev, msg);
+ break;
+ default:
+ break;
+ }
+}
+
+void *flexrm_write_descs(struct brcm_message *msg, u32 nhcnt,
+ u32 reqid, void *desc_ptr, u32 toggle,
+ void *start_desc, void *end_desc)
+{
+ if (!msg || !desc_ptr || !start_desc || !end_desc)
+ return ERR_PTR(-ENOTSUPP);
+
+ if ((desc_ptr < start_desc) || (end_desc <= desc_ptr))
+ return ERR_PTR(-ERANGE);
+
+ switch (msg->type) {
+ case BRCM_MESSAGE_SPU:
+ return flexrm_spu_write_descs(msg, nhcnt, reqid,
+ desc_ptr, toggle,
+ start_desc, end_desc);
+ case BRCM_MESSAGE_SBA:
+ return flexrm_sba_write_descs(msg, nhcnt, reqid,
+ desc_ptr, toggle,
+ start_desc, end_desc);
+ default:
+ return ERR_PTR(-ENOTSUPP);
+ };
+}
diff --git a/drivers/mailbox/mailbox-flexrm/flexrm-desc.h b/drivers/mailbox/mailbox-flexrm/flexrm-desc.h
new file mode 100644
index 0000000..a95cf61
--- /dev/null
+++ b/drivers/mailbox/mailbox-flexrm/flexrm-desc.h
@@ -0,0 +1,47 @@
+/* Broadcom FlexRM Mailbox Driver
+ *
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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.
+ *
+ * FlexRM descriptor library
+ */
+
+#ifndef __FLEXRM_DESC_H__
+#define __FLEXRM_DESC_H__
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mailbox/brcm-message.h>
+
+extern u64 flexrm_read_desc(void *desc_ptr);
+
+extern void flexrm_write_desc(void *desc_ptr, u64 desc);
+
+extern u32 flexrm_cmpl_desc_to_reqid(u64 cmpl_desc);
+
+extern int flexrm_cmpl_desc_to_error(u64 cmpl_desc);
+
+extern bool flexrm_is_next_table_desc(void *desc_ptr);
+
+extern u64 flexrm_next_table_desc(u32 toggle, dma_addr_t next_addr);
+
+extern u64 flexrm_null_desc(u32 toogle);
+
+extern u32 flexrm_estimate_header_desc_count(u32 nhcnt);
+
+extern bool flexrm_sanity_check(struct brcm_message *msg);
+
+extern u32 flexrm_estimate_nonheader_desc_count(struct brcm_message *msg);
+
+extern int flexrm_dma_map(struct device *dev, struct brcm_message *msg);
+
+extern void flexrm_dma_unmap(struct device *dev, struct brcm_message *msg);
+
+extern void *flexrm_write_descs(struct brcm_message *msg, u32 nhcnt,
+ u32 reqid, void *desc_ptr, u32 toggle,
+ void *start_desc, void *end_desc);
+
+#endif /* __FLEXRM_DESC_H__ */
diff --git a/drivers/mailbox/mailbox-flexrm/flexrm-main.c b/drivers/mailbox/mailbox-flexrm/flexrm-main.c
new file mode 100644
index 0000000..c8890f1
--- /dev/null
+++ b/drivers/mailbox/mailbox-flexrm/flexrm-main.c
@@ -0,0 +1,829 @@
+/* Broadcom FlexRM Mailbox Driver
+ *
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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.
+ *
+ * Each Broadcom FlexSparx4 offload engine is implemented as an
+ * extension to Broadcom FlexRM ring manager. The FlexRM ring
+ * manager provides a set of rings which can be used to submit
+ * work to a FlexSparx4 offload engine.
+ *
+ * This driver creates a mailbox controller using a set of FlexRM
+ * rings where each mailbox channel represents a separate FlexRM ring.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/brcm-message.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include "flexrm-desc.h"
+
+/* FlexRM configuration */
+#define RING_REGS_SIZE 0x10000
+#define RING_DESC_SIZE 8
+#define RING_DESC_INDEX(offset) \
+ ((offset) / RING_DESC_SIZE)
+#define RING_DESC_OFFSET(index) \
+ ((index) * RING_DESC_SIZE)
+#define RING_MAX_REQ_COUNT 1024
+#define RING_BD_ALIGN_ORDER 12
+#define RING_BD_ALIGN_CHECK(addr) \
+ (!((addr) & ((0x1 << RING_BD_ALIGN_ORDER) - 1)))
+#define RING_BD_TOGGLE_INVALID(offset) \
+ (((offset) >> RING_BD_ALIGN_ORDER) & 0x1)
+#define RING_BD_TOGGLE_VALID(offset) \
+ (!RING_BD_TOGGLE_INVALID(offset))
+#define RING_BD_DESC_PER_REQ 32
+#define RING_BD_DESC_COUNT \
+ (RING_MAX_REQ_COUNT * RING_BD_DESC_PER_REQ)
+#define RING_BD_SIZE \
+ (RING_BD_DESC_COUNT * RING_DESC_SIZE)
+#define RING_CMPL_ALIGN_ORDER 13
+#define RING_CMPL_DESC_COUNT RING_MAX_REQ_COUNT
+#define RING_CMPL_SIZE \
+ (RING_CMPL_DESC_COUNT * RING_DESC_SIZE)
+#define RING_VER_MAGIC 0x76303031
+
+/* Per-Ring register offsets */
+#define RING_VER 0x000
+#define RING_BD_START_ADDR 0x004
+#define RING_BD_READ_PTR 0x008
+#define RING_BD_WRITE_PTR 0x00c
+#define RING_BD_READ_PTR_DDR_LS 0x010
+#define RING_BD_READ_PTR_DDR_MS 0x014
+#define RING_CMPL_START_ADDR 0x018
+#define RING_CMPL_WRITE_PTR 0x01c
+#define RING_NUM_REQ_RECV_LS 0x020
+#define RING_NUM_REQ_RECV_MS 0x024
+#define RING_NUM_REQ_TRANS_LS 0x028
+#define RING_NUM_REQ_TRANS_MS 0x02c
+#define RING_NUM_REQ_OUTSTAND 0x030
+#define RING_CONTROL 0x034
+#define RING_FLUSH_DONE 0x038
+#define RING_MSI_ADDR_LS 0x03c
+#define RING_MSI_ADDR_MS 0x040
+#define RING_MSI_CONTROL 0x048
+#define RING_BD_READ_PTR_DDR_CONTROL 0x04c
+#define RING_MSI_DATA_VALUE 0x064
+
+/* Register RING_BD_START_ADDR fields */
+#define BD_LAST_UPDATE_HW_SHIFT 28
+#define BD_LAST_UPDATE_HW_MASK 0x1
+#define BD_START_ADDR_VALUE(pa) \
+ ((u32)((((dma_addr_t)(pa)) >> RING_BD_ALIGN_ORDER) & 0x0fffffff))
+#define BD_START_ADDR_DECODE(val) \
+ ((dma_addr_t)((val) & 0x0fffffff) << RING_BD_ALIGN_ORDER)
+
+/* Register RING_CMPL_START_ADDR fields */
+#define CMPL_START_ADDR_VALUE(pa) \
+ ((u32)((((u64)(pa)) >> RING_CMPL_ALIGN_ORDER) & 0x03ffffff))
+
+/* Register RING_CONTROL fields */
+#define CONTROL_MASK_DISABLE_CONTROL 12
+#define CONTROL_FLUSH_SHIFT 5
+#define CONTROL_ACTIVE_SHIFT 4
+#define CONTROL_RATE_ADAPT_MASK 0xf
+#define CONTROL_RATE_DYNAMIC 0x0
+#define CONTROL_RATE_FAST 0x8
+#define CONTROL_RATE_MEDIUM 0x9
+#define CONTROL_RATE_SLOW 0xa
+#define CONTROL_RATE_IDLE 0xb
+
+/* Register RING_FLUSH_DONE fields */
+#define FLUSH_DONE_MASK 0x1
+
+/* Register RING_MSI_CONTROL fields */
+#define MSI_TIMER_VAL_SHIFT 16
+#define MSI_TIMER_VAL_MASK 0xffff
+#define MSI_ENABLE_SHIFT 15
+#define MSI_ENABLE_MASK 0x1
+#define MSI_COUNT_SHIFT 0
+#define MSI_COUNT_MASK 0x3ff
+
+/* Register RING_BD_READ_PTR_DDR_CONTROL fields */
+#define BD_READ_PTR_DDR_TIMER_VAL_SHIFT 16
+#define BD_READ_PTR_DDR_TIMER_VAL_MASK 0xffff
+#define BD_READ_PTR_DDR_ENABLE_SHIFT 15
+#define BD_READ_PTR_DDR_ENABLE_MASK 0x1
+
+struct flexrm_ring {
+ /* Unprotected members */
+ int num;
+ struct flexrm_mbox *mbox;
+ void __iomem *regs;
+ bool irq_requested;
+ unsigned int irq;
+ unsigned int msi_timer_val;
+ unsigned int msi_count_threshold;
+ struct ida requests_ida;
+ struct brcm_message *requests[RING_MAX_REQ_COUNT];
+ void *bd_base;
+ dma_addr_t bd_dma_base;
+ u32 bd_write_offset;
+ void *cmpl_base;
+ dma_addr_t cmpl_dma_base;
+ /* Protected members */
+ spinlock_t lock;
+ struct brcm_message *last_pending_msg;
+ u32 cmpl_read_offset;
+};
+
+struct flexrm_mbox {
+ struct device *dev;
+ void __iomem *regs;
+ u32 num_rings;
+ struct flexrm_ring *rings;
+ u64 dma_mask;
+ struct dma_pool *bd_pool;
+ struct dma_pool *cmpl_pool;
+ struct mbox_controller controller;
+};
+
+static int flexrm_new_request(struct flexrm_ring *ring,
+ struct brcm_message *batch_msg,
+ struct brcm_message *msg)
+{
+ void *next;
+ unsigned long flags;
+ u32 val, count, nhcnt;
+ u32 read_offset, write_offset;
+ bool exit_cleanup = false;
+ int ret = 0, reqid;
+
+ /* Do sanity check on message */
+ if (!flexrm_sanity_check(msg))
+ return -EIO;
+ msg->error = 0;
+
+ /* If no requests possible then save data pointer and goto done. */
+ reqid = ida_simple_get(&ring->requests_ida, 0,
+ RING_MAX_REQ_COUNT, GFP_KERNEL);
+ if (reqid < 0) {
+ spin_lock_irqsave(&ring->lock, flags);
+ if (batch_msg)
+ ring->last_pending_msg = batch_msg;
+ else
+ ring->last_pending_msg = msg;
+ spin_unlock_irqrestore(&ring->lock, flags);
+ return 0;
+ }
+ ring->requests[reqid] = msg;
+
+ /* Do DMA mappings for the message */
+ ret = flexrm_dma_map(ring->mbox->dev, msg);
+ if (ret < 0) {
+ ring->requests[reqid] = NULL;
+ ida_simple_remove(&ring->requests_ida, reqid);
+ return ret;
+ }
+
+ /* If last_pending_msg is already set then goto done with error */
+ spin_lock_irqsave(&ring->lock, flags);
+ if (ring->last_pending_msg)
+ ret = -ENOSPC;
+ spin_unlock_irqrestore(&ring->lock, flags);
+ if (ret < 0) {
+ dev_warn(ring->mbox->dev, "no space in ring %d\n", ring->num);
+ exit_cleanup = true;
+ goto exit;
+ }
+
+ /* Determine current HW BD read offset */
+ read_offset = readl_relaxed(ring->regs + RING_BD_READ_PTR);
+ val = readl_relaxed(ring->regs + RING_BD_START_ADDR);
+ read_offset *= RING_DESC_SIZE;
+ read_offset += (u32)(BD_START_ADDR_DECODE(val) - ring->bd_dma_base);
+
+ /*
+ * Number required descriptors = number of non-header descriptors +
+ * number of header descriptors +
+ * 1x null descriptor
+ */
+ nhcnt = flexrm_estimate_nonheader_desc_count(msg);
+ count = flexrm_estimate_header_desc_count(nhcnt) + nhcnt + 1;
+
+ /* Check for available descriptor space. */
+ write_offset = ring->bd_write_offset;
+ while (count) {
+ if (!flexrm_is_next_table_desc(ring->bd_base + write_offset))
+ count--;
+ write_offset += RING_DESC_SIZE;
+ if (write_offset == RING_BD_SIZE)
+ write_offset = 0x0;
+ if (write_offset == read_offset)
+ break;
+ }
+ if (count) {
+ spin_lock_irqsave(&ring->lock, flags);
+ if (batch_msg)
+ ring->last_pending_msg = batch_msg;
+ else
+ ring->last_pending_msg = msg;
+ spin_unlock_irqrestore(&ring->lock, flags);
+ ret = 0;
+ exit_cleanup = true;
+ goto exit;
+ }
+
+ /* Write descriptors to ring */
+ next = flexrm_write_descs(msg, nhcnt, reqid,
+ ring->bd_base + ring->bd_write_offset,
+ RING_BD_TOGGLE_VALID(ring->bd_write_offset),
+ ring->bd_base, ring->bd_base + RING_BD_SIZE);
+ if (IS_ERR(next)) {
+ ret = PTR_ERR(next);
+ exit_cleanup = true;
+ goto exit;
+ }
+
+ /* Save ring BD write offset */
+ ring->bd_write_offset = (unsigned long)(next - ring->bd_base);
+
+exit:
+ /* Update error status in message */
+ msg->error = ret;
+
+ /* Cleanup if we failed */
+ if (exit_cleanup) {
+ flexrm_dma_unmap(ring->mbox->dev, msg);
+ ring->requests[reqid] = NULL;
+ ida_simple_remove(&ring->requests_ida, reqid);
+ }
+
+ return ret;
+}
+
+static int flexrm_process_completions(struct flexrm_ring *ring)
+{
+ u64 desc;
+ int err, count = 0;
+ unsigned long flags;
+ struct brcm_message *msg = NULL;
+ u32 reqid, cmpl_read_offset, cmpl_write_offset;
+ struct mbox_chan *chan = &ring->mbox->controller.chans[ring->num];
+
+ spin_lock_irqsave(&ring->lock, flags);
+
+ /* Check last_pending_msg */
+ if (ring->last_pending_msg) {
+ msg = ring->last_pending_msg;
+ ring->last_pending_msg = NULL;
+ }
+
+ /*
+ * Get current completion read and write offset
+ *
+ * Note: We should read completion write pointer atleast once
+ * after we get a MSI interrupt because HW maintains internal
+ * MSI status which will allow next MSI interrupt only after
+ * completion write pointer is read.
+ */
+ cmpl_write_offset = readl_relaxed(ring->regs + RING_CMPL_WRITE_PTR);
+ cmpl_write_offset *= RING_DESC_SIZE;
+ cmpl_read_offset = ring->cmpl_read_offset;
+ ring->cmpl_read_offset = cmpl_write_offset;
+
+ spin_unlock_irqrestore(&ring->lock, flags);
+
+ /* If last_pending_msg was set then queue it back */
+ if (msg)
+ mbox_send_message(chan, msg);
+
+ /* For each completed request notify mailbox clients */
+ reqid = 0;
+ while (cmpl_read_offset != cmpl_write_offset) {
+ /* Dequeue next completion descriptor */
+ desc = *((u64 *)(ring->cmpl_base + cmpl_read_offset));
+
+ /* Next read offset */
+ cmpl_read_offset += RING_DESC_SIZE;
+ if (cmpl_read_offset == RING_CMPL_SIZE)
+ cmpl_read_offset = 0;
+
+ /* Decode error from completion descriptor */
+ err = flexrm_cmpl_desc_to_error(desc);
+ if (err < 0) {
+ dev_warn(ring->mbox->dev,
+ "got completion desc=0x%lx with error %d",
+ (unsigned long)desc, err);
+ }
+
+ /* Determine request id from completion descriptor */
+ reqid = flexrm_cmpl_desc_to_reqid(desc);
+
+ /* Determine message pointer based on reqid */
+ msg = ring->requests[reqid];
+ if (!msg) {
+ dev_warn(ring->mbox->dev,
+ "null msg pointer for completion desc=0x%lx",
+ (unsigned long)desc);
+ continue;
+ }
+
+ /* Release reqid for recycling */
+ ring->requests[reqid] = NULL;
+ ida_simple_remove(&ring->requests_ida, reqid);
+
+ /* Unmap DMA mappings */
+ flexrm_dma_unmap(ring->mbox->dev, msg);
+
+ /* Give-back message to mailbox client */
+ msg->error = err;
+ mbox_chan_received_data(chan, msg);
+
+ /* Increment number of completions processed */
+ count++;
+ }
+
+ return count;
+}
+
+static irqreturn_t flexrm_irq_event(int irq, void *dev_id)
+{
+ /* We only have MSI for completions so just wakeup IRQ thread */
+ /* Ring related errors will be informed via completion descriptors */
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t flexrm_irq_thread(int irq, void *dev_id)
+{
+ flexrm_process_completions(dev_id);
+
+ return IRQ_HANDLED;
+}
+
+static int flexrm_send_data(struct mbox_chan *chan, void *data)
+{
+ int i, rc;
+ struct flexrm_ring *ring = chan->con_priv;
+ struct brcm_message *msg = data;
+
+ if (msg->type == BRCM_MESSAGE_BATCH) {
+ for (i = msg->batch.msgs_queued;
+ i < msg->batch.msgs_count; i++) {
+ rc = flexrm_new_request(ring, msg,
+ &msg->batch.msgs[i]);
+ if (rc) {
+ msg->error = rc;
+ return rc;
+ }
+ msg->batch.msgs_queued++;
+ }
+ return 0;
+ }
+
+ return flexrm_new_request(ring, NULL, data);
+}
+
+static bool flexrm_peek_data(struct mbox_chan *chan)
+{
+ int cnt = flexrm_process_completions(chan->con_priv);
+
+ return (cnt > 0) ? true : false;
+}
+
+static int flexrm_startup(struct mbox_chan *chan)
+{
+ u64 d;
+ u32 val, off;
+ int ret = 0;
+ dma_addr_t next_addr;
+ struct flexrm_ring *ring = chan->con_priv;
+
+ /* Allocate BD memory */
+ ring->bd_base = dma_pool_alloc(ring->mbox->bd_pool,
+ GFP_KERNEL, &ring->bd_dma_base);
+ if (!ring->bd_base) {
+ dev_err(ring->mbox->dev, "can't allocate BD memory\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ /* Configure next table pointer entries in BD memory */
+ for (off = 0; off < RING_BD_SIZE; off += RING_DESC_SIZE) {
+ next_addr = off + RING_DESC_SIZE;
+ if (next_addr == RING_BD_SIZE)
+ next_addr = 0;
+ next_addr += ring->bd_dma_base;
+ if (RING_BD_ALIGN_CHECK(next_addr))
+ d = flexrm_next_table_desc(RING_BD_TOGGLE_VALID(off),
+ next_addr);
+ else
+ d = flexrm_null_desc(RING_BD_TOGGLE_INVALID(off));
+ flexrm_write_desc(ring->bd_base + off, d);
+ }
+
+ /* Allocate completion memory */
+ ring->cmpl_base = dma_pool_alloc(ring->mbox->cmpl_pool,
+ GFP_KERNEL, &ring->cmpl_dma_base);
+ if (!ring->cmpl_base) {
+ dev_err(ring->mbox->dev, "can't allocate completion memory\n");
+ ret = -ENOMEM;
+ goto fail_free_bd_memory;
+ }
+ memset(ring->cmpl_base, 0, RING_CMPL_SIZE);
+
+ /* Request IRQ */
+ if (ring->irq == UINT_MAX) {
+ dev_err(ring->mbox->dev, "ring IRQ not available\n");
+ ret = -ENODEV;
+ goto fail_free_cmpl_memory;
+ }
+ ret = request_threaded_irq(ring->irq,
+ flexrm_irq_event,
+ flexrm_irq_thread,
+ 0, dev_name(ring->mbox->dev), ring);
+ if (ret) {
+ dev_err(ring->mbox->dev, "failed to request ring IRQ\n");
+ goto fail_free_cmpl_memory;
+ }
+ ring->irq_requested = true;
+
+ /* Disable/inactivate ring */
+ writel_relaxed(0x0, ring->regs + RING_CONTROL);
+
+ /* Program BD start address */
+ val = BD_START_ADDR_VALUE(ring->bd_dma_base);
+ writel_relaxed(val, ring->regs + RING_BD_START_ADDR);
+
+ /* BD write pointer will be same as HW write pointer */
+ ring->bd_write_offset =
+ readl_relaxed(ring->regs + RING_BD_WRITE_PTR);
+ ring->bd_write_offset *= RING_DESC_SIZE;
+
+ /* Program completion start address */
+ val = CMPL_START_ADDR_VALUE(ring->cmpl_dma_base);
+ writel_relaxed(val, ring->regs + RING_CMPL_START_ADDR);
+
+ /* Ensure last pending message is cleared */
+ ring->last_pending_msg = NULL;
+
+ /* Completion read pointer will be same as HW write pointer */
+ ring->cmpl_read_offset =
+ readl_relaxed(ring->regs + RING_CMPL_WRITE_PTR);
+ ring->cmpl_read_offset *= RING_DESC_SIZE;
+
+ /* Read ring Tx, Rx, and Outstanding counts to clear */
+ readl_relaxed(ring->regs + RING_NUM_REQ_RECV_LS);
+ readl_relaxed(ring->regs + RING_NUM_REQ_RECV_MS);
+ readl_relaxed(ring->regs + RING_NUM_REQ_TRANS_LS);
+ readl_relaxed(ring->regs + RING_NUM_REQ_TRANS_MS);
+ readl_relaxed(ring->regs + RING_NUM_REQ_OUTSTAND);
+
+ /* Configure RING_MSI_CONTROL */
+ val = 0;
+ val |= (ring->msi_timer_val << MSI_TIMER_VAL_SHIFT);
+ val |= BIT(MSI_ENABLE_SHIFT);
+ val |= (ring->msi_count_threshold & MSI_COUNT_MASK) << MSI_COUNT_SHIFT;
+ writel_relaxed(val, ring->regs + RING_MSI_CONTROL);
+
+ /* Enable/activate ring */
+ val = BIT(CONTROL_ACTIVE_SHIFT);
+ writel_relaxed(val, ring->regs + RING_CONTROL);
+
+ return 0;
+
+fail_free_cmpl_memory:
+ dma_pool_free(ring->mbox->cmpl_pool,
+ ring->cmpl_base, ring->cmpl_dma_base);
+ ring->cmpl_base = NULL;
+fail_free_bd_memory:
+ dma_pool_free(ring->mbox->bd_pool,
+ ring->bd_base, ring->bd_dma_base);
+ ring->bd_base = NULL;
+fail:
+ return ret;
+}
+
+static void flexrm_shutdown(struct mbox_chan *chan)
+{
+ u32 reqid;
+ unsigned int timeout;
+ struct brcm_message *msg;
+ struct flexrm_ring *ring = chan->con_priv;
+
+ /* Disable/inactivate ring */
+ writel_relaxed(0x0, ring->regs + RING_CONTROL);
+
+ /* Flush ring with timeout of 1s */
+ timeout = 1000;
+ writel_relaxed(BIT(CONTROL_FLUSH_SHIFT),
+ ring->regs + RING_CONTROL);
+ do {
+ if (readl_relaxed(ring->regs + RING_FLUSH_DONE) &
+ FLUSH_DONE_MASK)
+ break;
+ mdelay(1);
+ } while (timeout--);
+
+ /* Abort all in-flight requests */
+ for (reqid = 0; reqid < RING_MAX_REQ_COUNT; reqid++) {
+ msg = ring->requests[reqid];
+ if (!msg)
+ continue;
+
+ /* Release reqid for recycling */
+ ring->requests[reqid] = NULL;
+ ida_simple_remove(&ring->requests_ida, reqid);
+
+ /* Unmap DMA mappings */
+ flexrm_dma_unmap(ring->mbox->dev, msg);
+
+ /* Give-back message to mailbox client */
+ msg->error = -EIO;
+ mbox_chan_received_data(chan, msg);
+ }
+
+ /* Release IRQ */
+ if (ring->irq_requested) {
+ free_irq(ring->irq, ring);
+ ring->irq_requested = false;
+ }
+
+ /* Free-up completion descriptor ring */
+ if (ring->cmpl_base) {
+ dma_pool_free(ring->mbox->cmpl_pool,
+ ring->cmpl_base, ring->cmpl_dma_base);
+ ring->cmpl_base = NULL;
+ }
+
+ /* Free-up BD descriptor ring */
+ if (ring->bd_base) {
+ dma_pool_free(ring->mbox->bd_pool,
+ ring->bd_base, ring->bd_dma_base);
+ ring->bd_base = NULL;
+ }
+}
+
+static bool flexrm_last_tx_done(struct mbox_chan *chan)
+{
+ bool ret;
+ unsigned long flags;
+ struct flexrm_ring *ring = chan->con_priv;
+
+ spin_lock_irqsave(&ring->lock, flags);
+ ret = (ring->last_pending_msg) ? false : true;
+ spin_unlock_irqrestore(&ring->lock, flags);
+
+ return ret;
+}
+
+static const struct mbox_chan_ops flexrm_mbox_chan_ops = {
+ .send_data = flexrm_send_data,
+ .startup = flexrm_startup,
+ .shutdown = flexrm_shutdown,
+ .last_tx_done = flexrm_last_tx_done,
+ .peek_data = flexrm_peek_data,
+};
+
+static void flexrm_mbox_msi_write(struct msi_desc *desc, struct msi_msg *msg)
+{
+ struct device *dev = msi_desc_to_dev(desc);
+ struct flexrm_mbox *mbox = dev_get_drvdata(dev);
+ struct flexrm_ring *ring = &mbox->rings[desc->platform.msi_index];
+
+ /* Configure per-Ring MSI registers */
+ writel_relaxed(msg->address_lo, ring->regs + RING_MSI_ADDR_LS);
+ writel_relaxed(msg->address_hi, ring->regs + RING_MSI_ADDR_MS);
+ writel_relaxed(msg->data, ring->regs + RING_MSI_DATA_VALUE);
+}
+
+static struct mbox_chan *flexrm_mbox_of_xlate(struct mbox_controller *cntlr,
+ const struct of_phandle_args *pa)
+{
+ struct mbox_chan *chan;
+ struct flexrm_ring *ring;
+
+ if (pa->args_count < 3)
+ return ERR_PTR(-EINVAL);
+
+ if (pa->args[0] >= cntlr->num_chans)
+ return ERR_PTR(-ENOENT);
+
+ if (pa->args[1] > MSI_COUNT_MASK)
+ return ERR_PTR(-EINVAL);
+
+ if (pa->args[2] > MSI_TIMER_VAL_MASK)
+ return ERR_PTR(-EINVAL);
+
+ chan = &cntlr->chans[pa->args[0]];
+ ring = chan->con_priv;
+ ring->msi_count_threshold = pa->args[1];
+ ring->msi_timer_val = pa->args[2];
+
+ return chan;
+}
+
+static int flexrm_mbox_probe(struct platform_device *pdev)
+{
+ int index, ret = 0;
+ void __iomem *regs;
+ void __iomem *regs_end;
+ struct msi_desc *desc;
+ struct resource *iomem;
+ struct flexrm_ring *ring;
+ struct flexrm_mbox *mbox;
+ struct device *dev = &pdev->dev;
+
+ /* Allocate driver mailbox struct */
+ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
+ if (!mbox) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ mbox->dev = dev;
+ platform_set_drvdata(pdev, mbox);
+
+ /* Get resource for registers */
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem || (resource_size(iomem) < RING_REGS_SIZE)) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ /* Map registers of all rings */
+ mbox->regs = devm_ioremap_resource(&pdev->dev, iomem);
+ if (IS_ERR(mbox->regs)) {
+ ret = PTR_ERR(mbox->regs);
+ dev_err(&pdev->dev, "Failed to remap mailbox regs: %d\n", ret);
+ goto fail;
+ }
+ regs_end = mbox->regs + resource_size(iomem);
+
+ /* Scan and count available rings */
+ mbox->num_rings = 0;
+ for (regs = mbox->regs; regs < regs_end; regs += RING_REGS_SIZE) {
+ if (readl_relaxed(regs + RING_VER) == RING_VER_MAGIC)
+ mbox->num_rings++;
+ }
+ if (!mbox->num_rings) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ /* Allocate driver ring structs */
+ ring = devm_kcalloc(dev, mbox->num_rings, sizeof(*ring), GFP_KERNEL);
+ if (!ring) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ mbox->rings = ring;
+
+ /* Initialize members of driver ring structs */
+ regs = mbox->regs;
+ for (index = 0; index < mbox->num_rings; index++) {
+ ring = &mbox->rings[index];
+ ring->num = index;
+ ring->mbox = mbox;
+ while ((regs < regs_end) &&
+ (readl_relaxed(regs + RING_VER) != RING_VER_MAGIC))
+ regs += RING_REGS_SIZE;
+ if (regs_end <= regs) {
+ ret = -ENODEV;
+ goto fail;
+ }
+ ring->regs = regs;
+ regs += RING_REGS_SIZE;
+ ring->irq = UINT_MAX;
+ ring->irq_requested = false;
+ ring->msi_timer_val = MSI_TIMER_VAL_MASK;
+ ring->msi_count_threshold = 0x1;
+ ida_init(&ring->requests_ida);
+ memset(ring->requests, 0, sizeof(ring->requests));
+ ring->bd_base = NULL;
+ ring->bd_dma_base = 0;
+ ring->cmpl_base = NULL;
+ ring->cmpl_dma_base = 0;
+ spin_lock_init(&ring->lock);
+ ring->last_pending_msg = NULL;
+ ring->cmpl_read_offset = 0;
+ }
+
+ /* FlexRM is capable of 40-bit physical addresses only */
+ mbox->dma_mask = DMA_BIT_MASK(40);
+ dev->dma_mask = &mbox->dma_mask;
+
+ /* Create DMA pool for ring BD memory */
+ mbox->bd_pool = dma_pool_create("bd", dev, RING_BD_SIZE,
+ 1 << RING_BD_ALIGN_ORDER, 0);
+ if (!mbox->bd_pool) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ /* Create DMA pool for ring completion memory */
+ mbox->cmpl_pool = dma_pool_create("cmpl", dev, RING_CMPL_SIZE,
+ 1 << RING_CMPL_ALIGN_ORDER, 0);
+ if (!mbox->cmpl_pool) {
+ ret = -ENOMEM;
+ goto fail_destroy_bd_pool;
+ }
+
+ /* Allocate platform MSIs for each ring */
+ ret = platform_msi_domain_alloc_irqs(dev, mbox->num_rings,
+ flexrm_mbox_msi_write);
+ if (ret)
+ goto fail_destroy_cmpl_pool;
+
+ /* Save alloced IRQ numbers for each ring */
+ for_each_msi_entry(desc, dev) {
+ ring = &mbox->rings[desc->platform.msi_index];
+ ring->irq = desc->irq;
+ }
+
+ /* Initialize mailbox controller */
+ mbox->controller.txdone_irq = false;
+ mbox->controller.txdone_poll = true;
+ mbox->controller.txpoll_period = 1;
+ mbox->controller.ops = &flexrm_mbox_chan_ops;
+ mbox->controller.dev = dev;
+ mbox->controller.num_chans = mbox->num_rings;
+ mbox->controller.of_xlate = flexrm_mbox_of_xlate;
+ mbox->controller.chans = devm_kcalloc(dev, mbox->num_rings,
+ sizeof(*mbox->controller.chans), GFP_KERNEL);
+ if (!mbox->controller.chans) {
+ ret = -ENOMEM;
+ goto fail_free_msis;
+ }
+ for (index = 0; index < mbox->num_rings; index++)
+ mbox->controller.chans[index].con_priv = &mbox->rings[index];
+
+ /* Register mailbox controller */
+ ret = mbox_controller_register(&mbox->controller);
+ if (ret)
+ goto fail_free_msis;
+
+ dev_info(dev, "registered flexrm mailbox with %d channels\n",
+ mbox->controller.num_chans);
+
+ return 0;
+
+fail_free_msis:
+ platform_msi_domain_free_irqs(dev);
+fail_destroy_cmpl_pool:
+ dma_pool_destroy(mbox->cmpl_pool);
+fail_destroy_bd_pool:
+ dma_pool_destroy(mbox->bd_pool);
+fail:
+ return ret;
+}
+
+static int flexrm_mbox_remove(struct platform_device *pdev)
+{
+ int index;
+ struct device *dev = &pdev->dev;
+ struct flexrm_ring *ring;
+ struct flexrm_mbox *mbox = platform_get_drvdata(pdev);
+
+ mbox_controller_unregister(&mbox->controller);
+
+ platform_msi_domain_free_irqs(dev);
+
+ dma_pool_destroy(mbox->cmpl_pool);
+ dma_pool_destroy(mbox->bd_pool);
+
+ for (index = 0; index < mbox->num_rings; index++) {
+ ring = &mbox->rings[index];
+ ida_destroy(&ring->requests_ida);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id flexrm_mbox_of_match[] = {
+ { .compatible = "brcm,iproc-flexrm-mbox", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, flexrm_mbox_of_match);
+
+static struct platform_driver flexrm_mbox_driver = {
+ .driver = {
+ .name = "brcm-flexrm-mbox",
+ .of_match_table = flexrm_mbox_of_match,
+ },
+ .probe = flexrm_mbox_probe,
+ .remove = flexrm_mbox_remove,
+};
+module_platform_driver(flexrm_mbox_driver);
+
+MODULE_AUTHOR("Anup Patel <anup.patel@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom FlexRM mailbox driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mailbox/brcm-message.h b/include/linux/mailbox/brcm-message.h
index 6b55c93..c20b484 100644
--- a/include/linux/mailbox/brcm-message.h
+++ b/include/linux/mailbox/brcm-message.h
@@ -16,6 +16,7 @@
enum brcm_message_type {
BRCM_MESSAGE_UNKNOWN = 0,
+ BRCM_MESSAGE_BATCH,
BRCM_MESSAGE_SPU,
BRCM_MESSAGE_SBA,
BRCM_MESSAGE_MAX,
@@ -23,24 +24,29 @@ enum brcm_message_type {
struct brcm_sba_command {
u64 cmd;
+ u64 *cmd_dma;
+ dma_addr_t cmd_dma_addr;
#define BRCM_SBA_CMD_TYPE_A BIT(0)
#define BRCM_SBA_CMD_TYPE_B BIT(1)
#define BRCM_SBA_CMD_TYPE_C BIT(2)
#define BRCM_SBA_CMD_HAS_RESP BIT(3)
#define BRCM_SBA_CMD_HAS_OUTPUT BIT(4)
u64 flags;
- dma_addr_t input;
- size_t input_len;
dma_addr_t resp;
size_t resp_len;
- dma_addr_t output;
- size_t output_len;
+ dma_addr_t data;
+ size_t data_len;
};
struct brcm_message {
enum brcm_message_type type;
union {
struct {
+ struct brcm_message *msgs;
+ unsigned int msgs_queued;
+ unsigned int msgs_count;
+ } batch;
+ struct {
struct scatterlist *src;
struct scatterlist *dst;
} spu;
--
2.7.4
^ permalink raw reply related
* [PATCH v2 0/2] Broadcom FlexRM ring manager support
From: Anup Patel @ 2016-12-02 4:38 UTC (permalink / raw)
To: Jassi Brar, Rob Herring
Cc: Mark Rutland, Ray Jui, Scott Branden, Pramod KUMAR, Rob Rice,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w, Anup Patel
The Broadcom FlexRM ring manager provides producer-consumer style
ring interface for offload engines on Broadcom iProc SoCs. We can
have one or more instances of Broadcom FlexRM ring manager in a SoC.
This patchset adds a mailbox driver for Broadcom FlexRM ring manager
which can be used by offload engine drivers as mailbox clients.
The Broadcom FlexRM mailbox driver is feature complete for RAID and
Crypto offload engines. We will have incremental patches in-future
for ring-level statistics using debugfs and minor optimizations.
This patchset is based on Linux-4.9-rc7 and it is also available
at flexrm-v2 branch of https://github.com/Broadcom/arm64-linux.git
Changes since v1:
- Use compatile string as brcm,iproc-flexrm-mbox
- Rephrase commit message and text in DT bindings patch
Anup Patel (2):
mailbox: Add driver for Broadcom FlexRM ring manager
dt-bindings: Add DT bindings info for FlexRM ring manager
.../bindings/mailbox/brcm,iproc-flexrm-mbox.txt | 60 ++
drivers/mailbox/Kconfig | 11 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/mailbox-flexrm/Makefile | 6 +
drivers/mailbox/mailbox-flexrm/flexrm-desc.c | 764 +++++++++++++++++++
drivers/mailbox/mailbox-flexrm/flexrm-desc.h | 47 ++
drivers/mailbox/mailbox-flexrm/flexrm-main.c | 829 +++++++++++++++++++++
include/linux/mailbox/brcm-message.h | 14 +-
8 files changed, 1729 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mailbox/brcm,iproc-flexrm-mbox.txt
create mode 100644 drivers/mailbox/mailbox-flexrm/Makefile
create mode 100644 drivers/mailbox/mailbox-flexrm/flexrm-desc.c
create mode 100644 drivers/mailbox/mailbox-flexrm/flexrm-desc.h
create mode 100644 drivers/mailbox/mailbox-flexrm/flexrm-main.c
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 2/2] crypto: mediatek - add DT bindings documentation
From: Ryder Lee @ 2016-12-02 3:26 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Matthias Brugger
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sean Wang,
Ryder Lee
In-Reply-To: <1480649205-52695-1-git-send-email-ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Add DT bindings documentation for the crypto driver
Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
.../devicetree/bindings/crypto/mediatek-crypto.txt | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Documentation/devicetree/bindings/crypto/mediatek-crypto.txt
diff --git a/Documentation/devicetree/bindings/crypto/mediatek-crypto.txt b/Documentation/devicetree/bindings/crypto/mediatek-crypto.txt
new file mode 100644
index 0000000..8b1db08
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/mediatek-crypto.txt
@@ -0,0 +1,32 @@
+MediaTek cryptographic accelerators
+
+Required properties:
+- compatible: Should be "mediatek,mt7623-crypto"
+- reg: Address and length of the register set for the device
+- interrupts: Should contain the five crypto engines interrupts in numeric
+ order. These are global system and four descriptor rings.
+- clocks: the clock used by the core
+- clock-names: the names of the clock listed in the clocks property. These are
+ "ethif", "cryp"
+- power-domains: Must contain a reference to the PM domain.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+ that services interrupts for this device
+
+
+Example:
+ crypto: crypto@1b240000 {
+ compatible = "mediatek,mt7623-crypto";
+ reg = <0 0x1b240000 0 0x20000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_ETHIF_SEL>,
+ <ðsys CLK_ETHSYS_CRYPTO>;
+ clock-names = "ethif","cryp";
+ power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>;
+ };
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/2] Add crypto driver support for some MediaTek chips
From: Ryder Lee @ 2016-12-02 3:26 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Matthias Brugger
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sean Wang,
Ryder Lee
In-Reply-To: <1480649205-52695-1-git-send-email-ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
This adds support for the MediaTek hardware accelerator on
mt7623/mt2701/mt8521p SoC.
This driver currently implement:
- SHA1 and SHA2 family(HMAC) hash alogrithms.
- AES block cipher in CBC/ECB mode with 128/196/256 bits keys.
Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
drivers/crypto/Kconfig | 17 +
drivers/crypto/Makefile | 1 +
drivers/crypto/mediatek/Makefile | 2 +
drivers/crypto/mediatek/mtk-aes.c | 734 +++++++++++++++++
drivers/crypto/mediatek/mtk-platform.c | 575 +++++++++++++
drivers/crypto/mediatek/mtk-platform.h | 230 ++++++
drivers/crypto/mediatek/mtk-regs.h | 194 +++++
drivers/crypto/mediatek/mtk-sha.c | 1384 ++++++++++++++++++++++++++++++++
8 files changed, 3137 insertions(+)
create mode 100644 drivers/crypto/mediatek/Makefile
create mode 100644 drivers/crypto/mediatek/mtk-aes.c
create mode 100644 drivers/crypto/mediatek/mtk-platform.c
create mode 100644 drivers/crypto/mediatek/mtk-platform.h
create mode 100644 drivers/crypto/mediatek/mtk-regs.h
create mode 100644 drivers/crypto/mediatek/mtk-sha.c
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 4d2b81f..5d9c803 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -553,6 +553,23 @@ config CRYPTO_DEV_ROCKCHIP
This driver interfaces with the hardware crypto accelerator.
Supporting cbc/ecb chainmode, and aes/des/des3_ede cipher mode.
+config CRYPTO_DEV_MEDIATEK
+ tristate "MediaTek's Cryptographic Engine driver"
+ depends on ARM && ARCH_MEDIATEK
+ select NEON
+ select KERNEL_MODE_NEON
+ select ARM_CRYPTO
+ select CRYPTO_AES
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_SHA1_ARM_NEON
+ select CRYPTO_SHA256_ARM
+ select CRYPTO_SHA512_ARM
+ select CRYPTO_HMAC
+ help
+ This driver allows you to utilize the hardware crypto accelerator
+ which can be found on the MT7623 MT2701, MT8521p, etc ....
+ Select this if you want to use it for AES/SHA1/SHA2 algorithms.
+
source "drivers/crypto/chelsio/Kconfig"
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index ad7250f..272b51a 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CRYPTO_DEV_IMGTEC_HASH) += img-hash.o
obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
obj-$(CONFIG_CRYPTO_DEV_MV_CESA) += mv_cesa.o
obj-$(CONFIG_CRYPTO_DEV_MARVELL_CESA) += marvell/
+obj-$(CONFIG_CRYPTO_DEV_MEDIATEK) += mediatek/
obj-$(CONFIG_CRYPTO_DEV_MXS_DCP) += mxs-dcp.o
obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o
n2_crypto-y := n2_core.o n2_asm.o
diff --git a/drivers/crypto/mediatek/Makefile b/drivers/crypto/mediatek/Makefile
new file mode 100644
index 0000000..187be79
--- /dev/null
+++ b/drivers/crypto/mediatek/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_MEDIATEK) += mtk-crypto.o
+mtk-crypto-objs:= mtk-platform.o mtk-aes.o mtk-sha.o
diff --git a/drivers/crypto/mediatek/mtk-aes.c b/drivers/crypto/mediatek/mtk-aes.c
new file mode 100644
index 0000000..feb0e57
--- /dev/null
+++ b/drivers/crypto/mediatek/mtk-aes.c
@@ -0,0 +1,734 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for MediaTek AES hardware accelerator.
+ *
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * 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.
+ *
+ * Some ideas are from atmel-aes.c drivers.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include "mtk-platform.h"
+#include "mtk-regs.h"
+
+#define AES_QUEUE_LENGTH 512
+#define AES_BUFFER_ORDER 2
+#define AES_BUFFER_SIZE ((PAGE_SIZE << AES_BUFFER_ORDER) \
+ & ~(AES_BLOCK_SIZE - 1))
+
+/* AES command token */
+#define AES_CT_SIZE_ECB 2
+#define AES_CT_SIZE_CBC 3
+#define AES_CT_CTRL_HDR 0x00220000
+#define AES_COMMAND0 0x05000000
+#define AES_COMMAND1 0x2d060000
+#define AES_COMMAND2 0xe4a63806
+
+/* AES transform information */
+#define AES_TFM_ECB (0x0 << 0)
+#define AES_TFM_CBC (0x1 << 0)
+#define AES_TFM_DECRYPT (0x5 << 0)
+#define AES_TFM_ENCRYPT (0x4 << 0)
+#define AES_TFM_SIZE(x) ((x) << 8)
+#define AES_TFM_128BITS (0xb << 16)
+#define AES_TFM_192BITS (0xd << 16)
+#define AES_TFM_256BITS (0xf << 16)
+#define AES_TFM_FULL_IV (0xf << 5)
+
+/* AES flags */
+#define AES_FLAGS_MODE_MSK GENMASK(2, 0)
+#define AES_FLAGS_ECB BIT(0)
+#define AES_FLAGS_CBC BIT(1)
+#define AES_FLAGS_ENCRYPT BIT(2)
+#define AES_FLAGS_BUSY BIT(3)
+
+/* AES command token */
+struct mtk_aes_ct {
+ u32 ct_ctrl0;
+ u32 ct_ctrl1;
+ u32 ct_ctrl2;
+};
+
+/* AES transform info */
+struct mtk_aes_tfm {
+ u32 tfm_ctrl0;
+ u32 tfm_ctrl1;
+
+ /* keys and IVs */
+ u8 state[AES_KEYSIZE_256 + AES_BLOCK_SIZE] __aligned(sizeof(u32));
+};
+
+struct mtk_aes_info {
+ struct mtk_aes_ct ct;
+ struct mtk_aes_tfm tfm;
+};
+
+struct mtk_aes_reqctx {
+ u64 mode;
+};
+
+struct mtk_aes_ctx {
+ struct mtk_cryp *cryp;
+ struct mtk_aes_info info;
+ u32 keylen;
+
+ unsigned long flags;
+};
+
+struct mtk_aes_drv {
+ struct list_head dev_list;
+ /* device list lock */
+ spinlock_t lock;
+};
+
+static struct mtk_aes_drv mtk_aes = {
+ .dev_list = LIST_HEAD_INIT(mtk_aes.dev_list),
+ .lock = __SPIN_LOCK_UNLOCKED(mtk_aes.lock),
+};
+
+static inline u32 mtk_aes_read(struct mtk_cryp *cryp, u32 offset)
+{
+ return readl_relaxed(cryp->base + offset);
+}
+
+static inline void mtk_aes_write(struct mtk_cryp *cryp,
+ u32 offset, u32 value)
+{
+ writel_relaxed(value, cryp->base + offset);
+}
+
+static struct mtk_cryp *mtk_aes_find_dev(struct mtk_aes_ctx *ctx)
+{
+ struct mtk_cryp *cryp = NULL;
+ struct mtk_cryp *tmp;
+
+ spin_lock_bh(&mtk_aes.lock);
+ if (!ctx->cryp) {
+ list_for_each_entry(tmp, &mtk_aes.dev_list, aes_list) {
+ cryp = tmp;
+ break;
+ }
+ ctx->cryp = cryp;
+ } else {
+ cryp = ctx->cryp;
+ }
+ spin_unlock_bh(&mtk_aes.lock);
+
+ return cryp;
+}
+
+static inline size_t mtk_aes_padlen(size_t len)
+{
+ len &= AES_BLOCK_SIZE - 1;
+ return len ? AES_BLOCK_SIZE - len : 0;
+}
+
+static bool mtk_aes_check_aligned(struct scatterlist *sg,
+ size_t len, struct mtk_aes_dma *dma)
+{
+ int nents;
+
+ if (!IS_ALIGNED(len, AES_BLOCK_SIZE))
+ return false;
+
+ for (nents = 0; sg; sg = sg_next(sg), ++nents) {
+ if (!IS_ALIGNED(sg->offset, sizeof(u32)))
+ return false;
+
+ if (len <= sg->length) {
+ if (!IS_ALIGNED(len, AES_BLOCK_SIZE))
+ return false;
+
+ dma->nents = nents + 1;
+ dma->remainder = sg->length - len;
+ sg->length = len;
+ return true;
+ }
+
+ if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE))
+ return false;
+
+ len -= sg->length;
+ }
+
+ return false;
+}
+
+static int mtk_aes_info_map(struct mtk_cryp *cryp,
+ struct mtk_aes *aes, size_t len)
+{
+ struct mtk_aes_ctx *ctx = crypto_ablkcipher_ctx(
+ crypto_ablkcipher_reqtfm(aes->req));
+ struct mtk_aes_info *info = aes->info;
+ struct mtk_aes_ct *ct = &info->ct;
+ struct mtk_aes_tfm *tfm = &info->tfm;
+ u32 keylen = ctx->keylen;
+
+ aes->ct_hdr = AES_CT_CTRL_HDR | len;
+ ct->ct_ctrl0 = AES_COMMAND0 | len;
+ ct->ct_ctrl1 = AES_COMMAND1;
+
+ if (aes->flags & AES_FLAGS_ENCRYPT)
+ tfm->tfm_ctrl0 = AES_TFM_ENCRYPT;
+ else
+ tfm->tfm_ctrl0 = AES_TFM_DECRYPT;
+
+ if (aes->flags & AES_FLAGS_CBC) {
+ aes->ct_size = AES_CT_SIZE_CBC;
+ ct->ct_ctrl2 = AES_COMMAND2;
+
+ tfm->tfm_ctrl0 |= AES_TFM_SIZE(WORD(keylen + AES_BLOCK_SIZE));
+ tfm->tfm_ctrl1 = AES_TFM_CBC;
+ tfm->tfm_ctrl1 |= AES_TFM_FULL_IV;
+
+ memcpy(tfm->state + keylen, aes->req->info, AES_BLOCK_SIZE);
+ } else if (aes->flags & AES_FLAGS_ECB) {
+ aes->ct_size = AES_CT_SIZE_ECB;
+ tfm->tfm_ctrl0 |= AES_TFM_SIZE(WORD(keylen));
+ tfm->tfm_ctrl1 = AES_TFM_ECB;
+ }
+
+ if (keylen == AES_KEYSIZE_128)
+ tfm->tfm_ctrl0 |= AES_TFM_128BITS;
+ else if (keylen == AES_KEYSIZE_256)
+ tfm->tfm_ctrl0 |= AES_TFM_256BITS;
+ else if (keylen == AES_KEYSIZE_192)
+ tfm->tfm_ctrl0 |= AES_TFM_192BITS;
+
+ aes->ct_dma = dma_map_single(cryp->dev, info, sizeof(*info),
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(cryp->dev, aes->ct_dma))) {
+ dev_err(cryp->dev, "dma %d bytes error\n", sizeof(*info));
+ return -EINVAL;
+ }
+ aes->tfm_dma = aes->ct_dma + sizeof(*ct);
+
+ return 0;
+}
+
+static int mtk_aes_xmit(struct mtk_cryp *cryp, struct mtk_aes *aes)
+{
+ struct mtk_ring *ring = cryp->ring[aes->id];
+ struct mtk_desc *cmd = NULL, *res = NULL;
+ struct scatterlist *ssg, *dsg;
+ u32 len = aes->src.sg_len;
+ int nents;
+
+ for (nents = 0; nents < len; ++nents) {
+ ssg = &aes->src.sg[nents];
+ dsg = &aes->dst.sg[nents];
+
+ cmd = ring->cmd_base + ring->pos;
+ res = ring->res_base + ring->pos;
+
+ res->hdr = MTK_DESC_BUF_LEN(dsg->length);
+ res->buf = sg_dma_address(dsg);
+
+ cmd->hdr = MTK_DESC_BUF_LEN(ssg->length);
+ cmd->buf = sg_dma_address(ssg);
+
+ if (nents == 0) {
+ res->hdr |= MTK_DESC_FIRST;
+ cmd->hdr |= MTK_DESC_FIRST;
+ cmd->hdr |= MTK_DESC_CT_LEN(aes->ct_size);
+ cmd->ct = aes->ct_dma;
+ cmd->ct_hdr = aes->ct_hdr;
+ cmd->tfm = aes->tfm_dma;
+ }
+
+ if (++ring->pos == MTK_MAX_DESC_NUM)
+ ring->pos = 0;
+ }
+
+ cmd->hdr |= MTK_DESC_LAST;
+ res->hdr |= MTK_DESC_LAST;
+
+ /* make sure all descriptor are filled done */
+ wmb();
+ mtk_aes_write(cryp, RDR_PREP_COUNT(aes->id), MTK_DESC_CNT(len));
+ mtk_aes_write(cryp, CDR_PREP_COUNT(aes->id), MTK_DESC_CNT(len));
+
+ return -EINPROGRESS;
+}
+
+static inline void mtk_aes_restore_sg(const struct mtk_aes_dma *dma)
+{
+ struct scatterlist *sg = dma->sg;
+ int nents = dma->nents;
+
+ if (!dma->remainder)
+ return;
+
+ while (--nents > 0 && sg)
+ sg = sg_next(sg);
+
+ if (!sg)
+ return;
+
+ sg->length += dma->remainder;
+}
+
+static int mtk_aes_map(struct mtk_cryp *cryp, struct mtk_aes *aes)
+{
+ struct scatterlist *src = aes->req->src;
+ struct scatterlist *dst = aes->req->dst;
+ size_t len = aes->req->nbytes;
+ size_t padlen = 0;
+ bool src_aligned, dst_aligned;
+
+ aes->total = len;
+ aes->src.sg = src;
+ aes->dst.sg = dst;
+ aes->real_dst = dst;
+
+ src_aligned = mtk_aes_check_aligned(src, len, &aes->src);
+ if (src == dst)
+ dst_aligned = src_aligned;
+ else
+ dst_aligned = mtk_aes_check_aligned(dst, len, &aes->dst);
+
+ if (!src_aligned || !dst_aligned) {
+ padlen = mtk_aes_padlen(len);
+
+ if (len + padlen > AES_BUFFER_SIZE)
+ return -ENOMEM;
+
+ if (!src_aligned) {
+ sg_copy_to_buffer(src, sg_nents(src), aes->buf, len);
+ aes->src.sg = &aes->aligned_sg;
+ aes->src.nents = 1;
+ aes->src.remainder = 0;
+ }
+
+ if (!dst_aligned) {
+ aes->dst.sg = &aes->aligned_sg;
+ aes->dst.nents = 1;
+ aes->dst.remainder = 0;
+ }
+
+ sg_init_table(&aes->aligned_sg, 1);
+ sg_set_buf(&aes->aligned_sg, aes->buf, len + padlen);
+ }
+
+ if (aes->src.sg == aes->dst.sg) {
+ aes->src.sg_len = dma_map_sg(cryp->dev, aes->src.sg,
+ aes->src.nents, DMA_BIDIRECTIONAL);
+ aes->dst.sg_len = aes->src.sg_len;
+ if (unlikely(!aes->src.sg_len))
+ return -EFAULT;
+ } else {
+ aes->src.sg_len = dma_map_sg(cryp->dev, aes->src.sg,
+ aes->src.nents, DMA_TO_DEVICE);
+ if (unlikely(!aes->src.sg_len))
+ return -EFAULT;
+
+ aes->dst.sg_len = dma_map_sg(cryp->dev, aes->dst.sg,
+ aes->dst.nents, DMA_FROM_DEVICE);
+ if (unlikely(!aes->dst.sg_len)) {
+ dma_unmap_sg(cryp->dev, aes->src.sg,
+ aes->src.nents, DMA_TO_DEVICE);
+ return -EFAULT;
+ }
+ }
+
+ return mtk_aes_info_map(cryp, aes, len + padlen);
+}
+
+static int mtk_aes_handle_queue(struct mtk_cryp *cryp, u8 id,
+ struct ablkcipher_request *req)
+{
+ struct mtk_aes *aes = cryp->aes[id];
+ struct crypto_async_request *areq, *backlog;
+ struct mtk_aes_reqctx *rctx;
+ struct mtk_aes_ctx *ctx;
+ unsigned long flags;
+ int err, ret = 0;
+
+ spin_lock_irqsave(&aes->lock, flags);
+ if (req)
+ ret = ablkcipher_enqueue_request(&aes->queue, req);
+ if (aes->flags & AES_FLAGS_BUSY) {
+ spin_unlock_irqrestore(&aes->lock, flags);
+ return ret;
+ }
+ backlog = crypto_get_backlog(&aes->queue);
+ areq = crypto_dequeue_request(&aes->queue);
+ if (areq)
+ aes->flags |= AES_FLAGS_BUSY;
+ spin_unlock_irqrestore(&aes->lock, flags);
+
+ if (!areq)
+ return ret;
+
+ if (backlog)
+ backlog->complete(backlog, -EINPROGRESS);
+
+ req = ablkcipher_request_cast(areq);
+ ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
+ rctx = ablkcipher_request_ctx(req);
+ rctx->mode &= AES_FLAGS_MODE_MSK;
+ /* assign new request to device */
+ aes->req = req;
+ aes->info = &ctx->info;
+ aes->flags = (aes->flags & ~AES_FLAGS_MODE_MSK) | rctx->mode;
+
+ err = mtk_aes_map(cryp, aes);
+ if (err)
+ return err;
+
+ return mtk_aes_xmit(cryp, aes);
+}
+
+static void mtk_aes_unmap(struct mtk_cryp *cryp, struct mtk_aes *aes)
+{
+ dma_unmap_single(cryp->dev, aes->ct_dma,
+ sizeof(struct mtk_aes_info), DMA_TO_DEVICE);
+
+ if (aes->src.sg == aes->dst.sg) {
+ dma_unmap_sg(cryp->dev, aes->src.sg,
+ aes->src.nents, DMA_BIDIRECTIONAL);
+
+ if (aes->src.sg != &aes->aligned_sg)
+ mtk_aes_restore_sg(&aes->src);
+ } else {
+ dma_unmap_sg(cryp->dev, aes->dst.sg,
+ aes->dst.nents, DMA_FROM_DEVICE);
+
+ if (aes->dst.sg != &aes->aligned_sg)
+ mtk_aes_restore_sg(&aes->dst);
+
+ dma_unmap_sg(cryp->dev, aes->src.sg,
+ aes->src.nents, DMA_TO_DEVICE);
+
+ if (aes->src.sg != &aes->aligned_sg)
+ mtk_aes_restore_sg(&aes->src);
+ }
+
+ if (aes->dst.sg == &aes->aligned_sg)
+ sg_copy_from_buffer(aes->real_dst,
+ sg_nents(aes->real_dst),
+ aes->buf, aes->total);
+}
+
+static inline void mtk_aes_complete(struct mtk_cryp *cryp,
+ struct mtk_aes *aes)
+{
+ aes->flags &= ~AES_FLAGS_BUSY;
+
+ aes->req->base.complete(&aes->req->base, 0);
+
+ mtk_aes_handle_queue(cryp, aes->id, NULL);
+}
+
+static int mtk_aes_setkey(struct crypto_ablkcipher *tfm,
+ const u8 *key, u32 keylen)
+{
+ struct mtk_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u8 *state = ctx->info.tfm.state;
+
+ if (keylen != AES_KEYSIZE_128 &&
+ keylen != AES_KEYSIZE_192 &&
+ keylen != AES_KEYSIZE_256) {
+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+
+ ctx->keylen = keylen;
+ memcpy(state, key, keylen);
+
+ return 0;
+}
+
+static int mtk_aes_crypt(struct ablkcipher_request *req, u64 mode)
+{
+ struct mtk_aes_ctx *ctx = crypto_ablkcipher_ctx(
+ crypto_ablkcipher_reqtfm(req));
+ struct mtk_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+
+ rctx->mode = mode;
+
+ return mtk_aes_handle_queue(ctx->cryp,
+ !(mode & AES_FLAGS_ENCRYPT), req);
+}
+
+static int mtk_ecb_encrypt(struct ablkcipher_request *req)
+{
+ return mtk_aes_crypt(req, AES_FLAGS_ENCRYPT | AES_FLAGS_ECB);
+}
+
+static int mtk_ecb_decrypt(struct ablkcipher_request *req)
+{
+ return mtk_aes_crypt(req, AES_FLAGS_ECB);
+}
+
+static int mtk_cbc_encrypt(struct ablkcipher_request *req)
+{
+ return mtk_aes_crypt(req, AES_FLAGS_ENCRYPT | AES_FLAGS_CBC);
+}
+
+static int mtk_cbc_decrypt(struct ablkcipher_request *req)
+{
+ return mtk_aes_crypt(req, AES_FLAGS_CBC);
+}
+
+static int mtk_aes_cra_init(struct crypto_tfm *tfm)
+{
+ struct mtk_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct mtk_cryp *cryp = NULL;
+
+ tfm->crt_ablkcipher.reqsize = sizeof(struct mtk_aes_reqctx);
+
+ cryp = mtk_aes_find_dev(ctx);
+ if (!cryp) {
+ pr_err("can't find crypto device\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static struct crypto_alg aes_algs[] = {
+{
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-mtk",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_init = mtk_aes_cra_init,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_aes_ctx),
+ .cra_alignmask = 15,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = mtk_aes_setkey,
+ .encrypt = mtk_cbc_encrypt,
+ .decrypt = mtk_cbc_decrypt,
+ .ivsize = AES_BLOCK_SIZE,
+ }
+},
+{
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-mtk",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_init = mtk_aes_cra_init,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_aes_ctx),
+ .cra_alignmask = 15,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = mtk_aes_setkey,
+ .encrypt = mtk_ecb_encrypt,
+ .decrypt = mtk_ecb_decrypt,
+ }
+},
+};
+
+static void mtk_aes_enc_task(unsigned long data)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)data;
+ struct mtk_aes *aes = cryp->aes[0];
+
+ mtk_aes_unmap(cryp, aes);
+ mtk_aes_complete(cryp, aes);
+}
+
+static void mtk_aes_dec_task(unsigned long data)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)data;
+ struct mtk_aes *aes = cryp->aes[1];
+
+ mtk_aes_unmap(cryp, aes);
+ mtk_aes_complete(cryp, aes);
+}
+
+static irqreturn_t mtk_aes_enc_irq(int irq, void *dev_id)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)dev_id;
+ struct mtk_aes *aes = cryp->aes[0];
+ u32 val = mtk_aes_read(cryp, RDR_STAT(RING0));
+
+ mtk_aes_write(cryp, RDR_STAT(RING0), val);
+
+ if (likely(AES_FLAGS_BUSY & aes->flags)) {
+ mtk_aes_write(cryp, RDR_PROC_COUNT(RING0), MTK_DESC_CNT_CLR);
+ mtk_aes_write(cryp, RDR_THRESH(RING0), MTK_RDR_THRESH_DEF);
+
+ tasklet_schedule(&aes->task);
+ } else {
+ dev_warn(cryp->dev, "AES interrupt when no active requests.\n");
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mtk_aes_dec_irq(int irq, void *dev_id)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)dev_id;
+ struct mtk_aes *aes = cryp->aes[1];
+ u32 val = mtk_aes_read(cryp, RDR_STAT(RING1));
+
+ mtk_aes_write(cryp, RDR_STAT(RING1), val);
+
+ if (likely(AES_FLAGS_BUSY & aes->flags)) {
+ mtk_aes_write(cryp, RDR_PROC_COUNT(RING1), MTK_DESC_CNT_CLR);
+ mtk_aes_write(cryp, RDR_THRESH(RING1), MTK_RDR_THRESH_DEF);
+
+ tasklet_schedule(&aes->task);
+ } else {
+ dev_warn(cryp->dev, "AES interrupt when no active requests.\n");
+ }
+ return IRQ_HANDLED;
+}
+
+/* AES encryption record and decryption record */
+static int mtk_aes_record_init(struct mtk_cryp *cryp)
+{
+ struct mtk_aes **aes = cryp->aes;
+ int i, err = -ENOMEM;
+
+ for (i = 0; i < RECORD_NUM; i++) {
+ aes[i] = kzalloc(sizeof(**aes), GFP_KERNEL);
+ if (!aes[i])
+ goto err_cleanup;
+
+ aes[i]->buf = (void *)__get_free_pages(GFP_KERNEL,
+ AES_BUFFER_ORDER);
+ if (!aes[i]->buf)
+ goto err_cleanup;
+
+ aes[i]->id = i;
+
+ spin_lock_init(&aes[i]->lock);
+ crypto_init_queue(&aes[i]->queue, AES_QUEUE_LENGTH);
+ }
+
+ tasklet_init(&aes[0]->task, mtk_aes_enc_task, (unsigned long)cryp);
+ tasklet_init(&aes[1]->task, mtk_aes_dec_task, (unsigned long)cryp);
+
+ return 0;
+
+err_cleanup:
+ for (; i--; ) {
+ free_page((unsigned long)aes[i]->buf);
+ kfree(aes[i]);
+ }
+
+ return err;
+}
+
+static void mtk_aes_record_free(struct mtk_cryp *cryp)
+{
+ int i;
+
+ for (i = 0; i < RECORD_NUM; i++) {
+ tasklet_kill(&cryp->aes[i]->task);
+ free_page((unsigned long)cryp->aes[i]->buf);
+ kfree(cryp->aes[i]);
+ }
+}
+
+static void mtk_aes_unregister_algs(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
+ crypto_unregister_alg(&aes_algs[i]);
+}
+
+static int mtk_aes_register_algs(void)
+{
+ int err, i, j;
+
+ for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
+ err = crypto_register_alg(&aes_algs[i]);
+ if (err)
+ goto err_aes_algs;
+ }
+
+ return 0;
+
+err_aes_algs:
+ for (j = 0; j < i; j++)
+ crypto_unregister_alg(&aes_algs[j]);
+
+ return err;
+}
+
+int mtk_cipher_alg_register(struct mtk_cryp *cryp)
+{
+ int ret;
+
+ INIT_LIST_HEAD(&cryp->aes_list);
+
+ ret = mtk_aes_record_init(cryp);
+ if (ret)
+ goto err_record;
+
+ ret = devm_request_irq(cryp->dev, cryp->irq[RING0], mtk_aes_enc_irq,
+ IRQF_TRIGGER_LOW, "mtk-aes", cryp);
+ if (ret) {
+ dev_err(cryp->dev, "unable to request AES encryption irq.\n");
+ goto err_res;
+ }
+
+ ret = devm_request_irq(cryp->dev, cryp->irq[RING1], mtk_aes_dec_irq,
+ IRQF_TRIGGER_LOW, "mtk-aes", cryp);
+ if (ret) {
+ dev_err(cryp->dev, "unable to request AES decryption irq.\n");
+ goto err_res;
+ }
+
+ /* enable ring0 and ring1 interrupt for cipher */
+ mtk_aes_write(cryp, AIC_ENABLE_SET(RING0), MTK_IRQ_RDR0);
+ mtk_aes_write(cryp, AIC_ENABLE_SET(RING1), MTK_IRQ_RDR1);
+
+ spin_lock(&mtk_aes.lock);
+ list_add_tail(&cryp->aes_list, &mtk_aes.dev_list);
+ spin_unlock(&mtk_aes.lock);
+
+ ret = mtk_aes_register_algs();
+ if (ret)
+ goto err_algs;
+
+ return 0;
+
+err_algs:
+ spin_lock(&mtk_aes.lock);
+ list_del(&cryp->aes_list);
+ spin_unlock(&mtk_aes.lock);
+err_res:
+ mtk_aes_record_free(cryp);
+err_record:
+
+ dev_err(cryp->dev, "mtk-aes initialization failed.\n");
+ return ret;
+}
+EXPORT_SYMBOL(mtk_cipher_alg_register);
+
+void mtk_cipher_alg_release(struct mtk_cryp *cryp)
+{
+ spin_lock(&mtk_aes.lock);
+ list_del(&cryp->aes_list);
+ spin_unlock(&mtk_aes.lock);
+
+ mtk_aes_unregister_algs();
+ mtk_aes_record_free(cryp);
+}
+EXPORT_SYMBOL(mtk_cipher_alg_release);
diff --git a/drivers/crypto/mediatek/mtk-platform.c b/drivers/crypto/mediatek/mtk-platform.c
new file mode 100644
index 0000000..d3a465f
--- /dev/null
+++ b/drivers/crypto/mediatek/mtk-platform.c
@@ -0,0 +1,575 @@
+/*
+ * Support for MediaTek cryptographic accelerator.
+ *
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include "mtk-platform.h"
+#include "mtk-regs.h"
+
+#define MTK_BURST_SIZE(x, y) (((x) & ~0xf0) | ((y) << 4))
+#define MTK_DESC_SIZE_SET(x) ((x) << 0)
+#define MTK_DESC_OFFSET_SET(x) ((x) << 16)
+#define MTK_DFSE_RING_ID(x) (((x) >> 12) & 0xf)
+#define MTK_DSE_MIN_DATA(x) ((x) << 0)
+#define MTK_DSE_MAX_DATA(x) ((x) << 8)
+#define MTK_DFE_MIN_DATA(x) ((x) << 0)
+#define MTK_DFE_MAX_DATA(x) ((x) << 8)
+#define MTK_DFE_MIN_CTRL(x) ((x) << 16)
+#define MTK_DFE_MAX_CTRL(x) ((x) << 24)
+#define MTK_FETCH_SIZE_SET(x) ((x) << 0)
+#define MTK_FETCH_THRESH_SET(x) ((x) << 16)
+#define MTK_IN_BUF_MIN_THRESH(x) ((x) << 8)
+#define MTK_IN_BUF_MAX_THRESH(x) ((x) << 12)
+#define MTK_OUT_BUF_MIN_THRESH(x) ((x) << 0)
+#define MTK_OUT_BUF_MAX_THRESH(x) ((x) << 4)
+#define MTK_CMD_FIFO_SIZE(x) (((x) >> 8) & 0xf)
+#define MTK_RES_FIFO_SIZE(x) (((x) >> 12) & 0xf)
+#define MTK_HIA_DATA_WIDTH(x) (((x) >> 25) & 0x3)
+#define MTK_HIA_DMA_LENGTH(x) (((x) >> 20) & 0x1f)
+#define MTK_IN_TBUF_SIZE(x) (((x) >> 4) & 0xf)
+#define MTK_IN_DBUF_SIZE(x) (((x) >> 8) & 0xf)
+#define MTK_OUT_DBUF_SIZE(x) (((x) >> 16) & 0xf)
+#define MTK_AIC_INT_NUM(x) ((x) & 0x3f)
+#define MTK_AIC_VER_GET(x) ((x) & 0x0ff0ffff)
+#define MTK_PE_TOKEN_CTRL_DEF 0x00014004
+#define MTK_PE_INT_CTRL_DEF 0xc00f400f
+#define MTK_PRNG_CTRL_EN BIT(0)
+#define MTK_PRNG_CTRL_AUTO BIT(1)
+#define MTK_TOKEN_TIMEOUT_EN BIT(22)
+#define MTK_OVL_IRQ_EN BIT(25)
+#define MTK_ATP_PRESENT BIT(30)
+#define MTK_DFSE_THR_CTRL_EN BIT(30)
+#define MTK_DFSE_THR_CTRL_RESET BIT(31)
+#define MTK_HIA_SIGNATURE ((u16)0x35ca)
+#define MTK_CDR_STAT_CLR 0x1f
+#define MTK_RDR_STAT_CLR 0xff
+#define MTK_AIC_VER11 0x011036C9
+#define MTK_AIC_VER12 0x012036C9
+#define MTK_AIC_GLOBAL_CLR 0x7FF00000
+#define MTK_DFSE_IDLE 0xf
+
+/* Cryptographic engine capabilities */
+struct mtk_sys_cap {
+ /* Host interface adapter */
+ u32 hia_ver;
+ u32 hia_opt;
+
+ /* Packet engine */
+ u32 pkt_eng_opt;
+
+ /* Global hardware */
+ u32 hw_opt;
+};
+
+static void mtk_prng_reseed(struct mtk_cryp *cryp)
+{
+ /* 8 words to seed the PRNG to provide IVs */
+ void __iomem *base = cryp->base;
+ const u32 prng_key[8] = {0x48c24cfd, 0x6c07f742,
+ 0xaee75681, 0x0f27c239,
+ 0x79947198, 0xe2991275,
+ 0x21ac3c7c, 0xd008c4b4};
+
+ /* Disable PRNG and set PRNG manual mode */
+ writel(0, base + PE_PRNG_CTRL);
+
+ /* Write new seed data */
+ writel(prng_key[0], base + PE_PRNG_SEED_L);
+ writel(prng_key[1], base + PE_PRNG_SEED_H);
+
+ /* Write new key data */
+ writel(prng_key[2], base + PE_PRNG_KEY_0_L);
+ writel(prng_key[3], base + PE_PRNG_KEY_0_H);
+ writel(prng_key[4], base + PE_PRNG_KEY_1_L);
+ writel(prng_key[5], base + PE_PRNG_KEY_1_H);
+
+ /* Write new LFSR data */
+ writel(prng_key[6], base + PE_PRNG_LFSR_L);
+ writel(prng_key[7], base + PE_PRNG_LFSR_H);
+
+ /* Enable PRNG and set PRNG auto mode */
+ writel(MTK_PRNG_CTRL_EN | MTK_PRNG_CTRL_AUTO, base + PE_PRNG_CTRL);
+}
+
+static void mtk_desc_ring_link(struct mtk_cryp *cryp, u32 mask)
+{
+ /* Assign rings to DFE DSE thread and enable it */
+ writel(MTK_DFSE_THR_CTRL_EN | mask, cryp->base + DFE_THR_CTRL);
+ writel(MTK_DFSE_THR_CTRL_EN | mask, cryp->base + DSE_THR_CTRL);
+}
+
+static void mtk_dfe_dse_buf_setup(struct mtk_cryp *cryp,
+ struct mtk_sys_cap *cap)
+{
+ u32 width = MTK_HIA_DATA_WIDTH(cap->hia_opt) + 2;
+ u32 len = MTK_HIA_DMA_LENGTH(cap->hia_opt) - 1;
+ u32 ipbuf = min(MTK_IN_DBUF_SIZE(cap->hw_opt) + width, len);
+ u32 opbuf = min(MTK_OUT_DBUF_SIZE(cap->hw_opt) + width, len);
+ u32 itbuf = min(MTK_IN_TBUF_SIZE(cap->hw_opt) + width, len);
+ u32 val;
+
+ val = MTK_DFE_MIN_DATA(ipbuf - 1) | MTK_DFE_MAX_DATA(ipbuf) |
+ MTK_DFE_MIN_CTRL(itbuf - 1) | MTK_DFE_MAX_CTRL(itbuf);
+ writel(val, cryp->base + DFE_CFG);
+
+ val = MTK_DFE_MIN_DATA(opbuf - 1) | MTK_DFE_MAX_DATA(opbuf);
+ writel(val, cryp->base + DSE_CFG);
+
+ val = MTK_IN_BUF_MIN_THRESH(ipbuf - 1) | MTK_IN_BUF_MAX_THRESH(ipbuf);
+ writel(val, cryp->base + PE_IN_DBUF_THRESH);
+
+ val = MTK_IN_BUF_MIN_THRESH(itbuf - 1) | MTK_IN_BUF_MAX_THRESH(itbuf);
+ writel(val, cryp->base + PE_IN_TBUF_THRESH);
+
+ val = MTK_OUT_BUF_MIN_THRESH(opbuf - 1) | MTK_OUT_BUF_MAX_THRESH(opbuf);
+ writel(val, cryp->base + PE_OUT_DBUF_THRESH);
+
+ writel(0, cryp->base + PE_OUT_TBUF_THRESH);
+ writel(0, cryp->base + PE_OUT_BUF_CTRL);
+}
+
+static int mtk_dfe_dse_state_check(struct mtk_cryp *cryp)
+{
+ int ret = -EINVAL;
+ u32 val;
+
+ /* Check for completion of all DMA transfers */
+ val = readl(cryp->base + DFE_THR_STAT);
+ if (MTK_DFSE_RING_ID(val) == MTK_DFSE_IDLE) {
+ val = readl(cryp->base + DSE_THR_STAT);
+ if (MTK_DFSE_RING_ID(val) == MTK_DFSE_IDLE)
+ ret = 0;
+ }
+
+ if (!ret) {
+ /* Take DFE and DSE thread out of reset */
+ writel(0, cryp->base + DFE_THR_CTRL);
+ writel(0, cryp->base + DSE_THR_CTRL);
+ } else {
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int mtk_dfe_dse_reset(struct mtk_cryp *cryp)
+{
+ int err;
+
+ /* Reset DSE DFE and correct system priorities for all rings. */
+ writel(MTK_DFSE_THR_CTRL_RESET, cryp->base + DFE_THR_CTRL);
+ writel(0, cryp->base + DFE_PRIO_0);
+ writel(0, cryp->base + DFE_PRIO_1);
+ writel(0, cryp->base + DFE_PRIO_2);
+ writel(0, cryp->base + DFE_PRIO_3);
+
+ writel(MTK_DFSE_THR_CTRL_RESET, cryp->base + DSE_THR_CTRL);
+ writel(0, cryp->base + DSE_PRIO_0);
+ writel(0, cryp->base + DSE_PRIO_1);
+ writel(0, cryp->base + DSE_PRIO_2);
+ writel(0, cryp->base + DSE_PRIO_3);
+
+ err = mtk_dfe_dse_state_check(cryp);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static void mtk_cmd_desc_ring_setup(struct mtk_cryp *cryp,
+ int i, struct mtk_sys_cap *cap)
+{
+ /* Full descriptor that fits FIFO minus one */
+ u32 count =
+ ((1 << MTK_CMD_FIFO_SIZE(cap->hia_opt)) / MTK_DESC_SIZE) - 1;
+ u32 size = count * MTK_DESC_OFFSET;
+ u32 thresh = count * MTK_DESC_SIZE;
+ u32 val;
+
+ /* Temporarily disable external triggering */
+ writel(0, cryp->base + CDR_CFG(i));
+
+ /* Clear CDR count */
+ writel(MTK_DESC_CNT_CLR, cryp->base + CDR_PREP_COUNT(i));
+ writel(MTK_DESC_CNT_CLR, cryp->base + CDR_PROC_COUNT(i));
+
+ writel(0, cryp->base + CDR_PREP_PNTR(i));
+ writel(0, cryp->base + CDR_PROC_PNTR(i));
+ writel(0, cryp->base + CDR_DMA_CFG(i));
+
+ /* Configure command ring host address space */
+ writel(0, cryp->base + CDR_BASE_ADDR_HI(i));
+ writel(cryp->ring[i]->cmd_dma, cryp->base + CDR_BASE_ADDR_LO(i));
+
+ writel(MTK_MAX_RING_SIZE, cryp->base + CDR_RING_SIZE(i));
+
+ /* Clear and disable all CDR interrupts */
+ writel(MTK_CDR_STAT_CLR, cryp->base + CDR_STAT(i));
+
+ /*
+ * Set command descriptor offset and enable additional
+ * token present in descriptor.
+ */
+ val = MTK_DESC_SIZE_SET(MTK_DESC_SIZE) |
+ MTK_DESC_OFFSET_SET(MTK_DESC_OFFSET) |
+ MTK_ATP_PRESENT;
+ writel(val, cryp->base + CDR_DESC_SIZE(i));
+
+ val = MTK_FETCH_SIZE_SET(size) | MTK_FETCH_THRESH_SET(thresh);
+ writel(val, cryp->base + CDR_CFG(i));
+}
+
+static void mtk_res_desc_ring_setup(struct mtk_cryp *cryp,
+ int i, struct mtk_sys_cap *cap)
+{
+ u32 rndup = 2;
+ u32 count = ((1 << MTK_RES_FIFO_SIZE(cap->hia_opt)) / rndup) - 1;
+ u32 size = count * MTK_DESC_OFFSET;
+ u32 thresh = count * rndup;
+ u32 val;
+
+ writel(0, cryp->base + RDR_CFG(i));
+
+ writel(MTK_DESC_CNT_CLR, cryp->base + RDR_PREP_COUNT(i));
+ writel(MTK_DESC_CNT_CLR, cryp->base + RDR_PROC_COUNT(i));
+
+ writel(0, cryp->base + RDR_PREP_PNTR(i));
+ writel(0, cryp->base + RDR_PROC_PNTR(i));
+ writel(0, cryp->base + RDR_DMA_CFG(i));
+
+ writel(0, cryp->base + RDR_BASE_ADDR_HI(i));
+ writel(cryp->ring[i]->res_dma, cryp->base + RDR_BASE_ADDR_LO(i));
+
+ writel(MTK_MAX_RING_SIZE, cryp->base + RDR_RING_SIZE(i));
+ writel(MTK_RDR_STAT_CLR, cryp->base + RDR_STAT(i));
+
+ /*
+ * RDR manager generates update interrupts on a per-completed-packet,
+ * and the rd_proc_thresh_irq interrupt is fired when proc_pkt_count
+ * for the RDR exceeds the number of packets.
+ */
+ writel(MTK_RDR_THRESH_DEF, cryp->base + RDR_THRESH(i));
+
+ /*
+ * Configure a threshold and time-out value for the processed
+ * result descriptors (or complete packets) that are written to
+ * the RDR.
+ */
+ val = MTK_DESC_SIZE_SET(MTK_DESC_SIZE) |
+ MTK_DESC_OFFSET_SET(MTK_DESC_OFFSET);
+ writel(val, cryp->base + RDR_DESC_SIZE(i));
+
+ /*
+ * Configure HIA fetch size and fetch threshold that are used to
+ * fetch blocks of multiple descriptors.
+ */
+ val = MTK_FETCH_SIZE_SET(size) |
+ MTK_FETCH_THRESH_SET(thresh) |
+ MTK_OVL_IRQ_EN;
+ writel(val, cryp->base + RDR_CFG(i));
+}
+
+static int mtk_packet_engine_setup(struct mtk_cryp *cryp)
+{
+ struct mtk_sys_cap cap;
+ int i, err;
+ u32 val;
+
+ cap.hia_ver = readl(cryp->base + HIA_VERSION);
+ cap.hia_opt = readl(cryp->base + HIA_OPTIONS);
+ cap.hw_opt = readl(cryp->base + EIP97_OPTIONS);
+
+ if (!(((u16)cap.hia_ver) == MTK_HIA_SIGNATURE))
+ return -EINVAL;
+
+ /* Configure endianness conversion method for master (DMA) interface */
+ writel(0, cryp->base + EIP97_MST_CTRL);
+
+ /* Set HIA burst size */
+ val = readl(cryp->base + HIA_MST_CTRL);
+ writel(MTK_BURST_SIZE(val, 5), cryp->base + HIA_MST_CTRL);
+
+ err = mtk_dfe_dse_reset(cryp);
+ if (err) {
+ dev_err(cryp->dev, "Failed to reset DFE and DSE.\n");
+ return err;
+ }
+
+ mtk_dfe_dse_buf_setup(cryp, &cap);
+
+ /* Enable the 4 rings for the packet engines. */
+ mtk_desc_ring_link(cryp, 0xf);
+
+ for (i = 0; i < RING_MAX; i++) {
+ mtk_cmd_desc_ring_setup(cryp, i, &cap);
+ mtk_res_desc_ring_setup(cryp, i, &cap);
+ }
+
+ val = MTK_PE_TOKEN_CTRL_DEF | MTK_TOKEN_TIMEOUT_EN;
+ writel(val, cryp->base + PE_TOKEN_CTRL_STAT);
+
+ /* Clear all pending interrupts */
+ writel(MTK_AIC_GLOBAL_CLR, cryp->base + AIC_G_ACK);
+ writel(MTK_PE_INT_CTRL_DEF, cryp->base + PE_INTERRUPT_CTRL_STAT);
+
+ return 0;
+}
+
+static int mtk_aic_cap_check(struct mtk_cryp *cryp, int hw)
+{
+ u32 val;
+
+ if (hw == RING_MAX)
+ val = readl(cryp->base + AIC_G_VERSION);
+ else
+ val = readl(cryp->base + AIC_VERSION(hw));
+
+ val = MTK_AIC_VER_GET(val);
+ if (val != MTK_AIC_VER11 && val != MTK_AIC_VER12)
+ return -ENXIO;
+
+ if (hw == RING_MAX)
+ val = readl(cryp->base + AIC_G_OPTIONS);
+ else
+ val = readl(cryp->base + AIC_OPTIONS(hw));
+
+ val = MTK_AIC_INT_NUM(val);
+ if (!val || val > 32)
+ return -ENXIO;
+
+ return 0;
+}
+
+static int mtk_aic_init(struct mtk_cryp *cryp, int hw)
+{
+ int err;
+
+ err = mtk_aic_cap_check(cryp, hw);
+ if (err)
+ return err;
+
+ /* Disable all interrupts and set initial configuration */
+ if (hw == RING_MAX) {
+ writel(0, cryp->base + AIC_G_ENABLE_CTRL);
+ writel(0, cryp->base + AIC_G_POL_CTRL);
+ writel(0, cryp->base + AIC_G_TYPE_CTRL);
+ writel(0, cryp->base + AIC_G_ENABLE_SET);
+ } else {
+ writel(0, cryp->base + AIC_ENABLE_CTRL(hw));
+ writel(0, cryp->base + AIC_POL_CTRL(hw));
+ writel(0, cryp->base + AIC_TYPE_CTRL(hw));
+ writel(0, cryp->base + AIC_ENABLE_SET(hw));
+ }
+
+ return 0;
+}
+
+static int mtk_accelerator_init(struct mtk_cryp *cryp)
+{
+ int i, err;
+
+ /* Initialize advanced interrupt controller(AIC) */
+ for (i = 0; i < 5; i++) {
+ err = mtk_aic_init(cryp, i);
+ if (err) {
+ dev_err(cryp->dev, "Failed to initialize AIC.\n");
+ return err;
+ }
+ }
+
+ /* Initialize packet engine */
+ err = mtk_packet_engine_setup(cryp);
+ if (err) {
+ dev_err(cryp->dev, "Failed to configure packet engine.\n");
+ return err;
+ }
+
+ mtk_prng_reseed(cryp);
+ return 0;
+}
+
+static void mtk_desc_dma_free(struct mtk_cryp *cryp)
+{
+ int i;
+
+ for (i = 0; i < RING_MAX; i++) {
+ dma_free_coherent(cryp->dev, MTK_MAX_RING_SIZE,
+ cryp->ring[i]->res_base,
+ cryp->ring[i]->res_dma);
+ dma_free_coherent(cryp->dev, MTK_MAX_RING_SIZE,
+ cryp->ring[i]->cmd_base,
+ cryp->ring[i]->cmd_dma);
+ kfree(cryp->ring[i]);
+ }
+}
+
+static int mtk_desc_ring_alloc(struct mtk_cryp *cryp)
+{
+ struct mtk_ring **ring = cryp->ring;
+ int i, err = ENOMEM;
+
+ for (i = 0; i < RING_MAX; i++) {
+ ring[i] = kzalloc(sizeof(**ring), GFP_KERNEL);
+ if (!ring[i])
+ goto err_cleanup;
+
+ ring[i]->cmd_base = dma_zalloc_coherent(cryp->dev,
+ MTK_MAX_RING_SIZE, &ring[i]->cmd_dma,
+ GFP_KERNEL);
+ if (!ring[i]->cmd_base)
+ goto err_cleanup;
+
+ ring[i]->res_base = dma_zalloc_coherent(cryp->dev,
+ MTK_MAX_RING_SIZE, &ring[i]->res_dma,
+ GFP_KERNEL);
+ if (!ring[i]->res_base)
+ goto err_cleanup;
+ }
+ return 0;
+
+err_cleanup:
+ for (; i--; ) {
+ dma_free_coherent(cryp->dev, MTK_MAX_RING_SIZE,
+ ring[i]->res_base, ring[i]->res_dma);
+ dma_free_coherent(cryp->dev, MTK_MAX_RING_SIZE,
+ ring[i]->cmd_base, ring[i]->cmd_dma);
+ kfree(ring[i]);
+ }
+ return err;
+}
+
+static int mtk_crypto_probe(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct mtk_cryp *cryp;
+ int i, err;
+
+ cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL);
+ if (!cryp)
+ return -ENOMEM;
+
+ cryp->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(cryp->base))
+ return PTR_ERR(cryp->base);
+
+ for (i = 0; i < 5; i++) {
+ cryp->irq[i] = platform_get_irq(pdev, i);
+ if (cryp->irq[i] < 0) {
+ dev_err(cryp->dev, "no IRQ:%d resource info\n", i);
+ return -ENXIO;
+ }
+ }
+
+ cryp->clk_ethif = devm_clk_get(&pdev->dev, "ethif");
+ cryp->clk_cryp = devm_clk_get(&pdev->dev, "cryp");
+ if (IS_ERR(cryp->clk_ethif) || IS_ERR(cryp->clk_cryp))
+ return -EPROBE_DEFER;
+
+ cryp->dev = &pdev->dev;
+ pm_runtime_enable(cryp->dev);
+ pm_runtime_get_sync(cryp->dev);
+
+ err = clk_prepare_enable(cryp->clk_ethif);
+ if (err)
+ goto err_clk_ethif;
+
+ err = clk_prepare_enable(cryp->clk_cryp);
+ if (err)
+ goto err_clk_cryp;
+
+ err = mtk_desc_ring_alloc(cryp);
+ if (err) {
+ dev_err(cryp->dev, "Unable to allocate descriptor rings.\n");
+ goto err_resource;
+ }
+
+ err = mtk_accelerator_init(cryp);
+ if (err) {
+ dev_err(cryp->dev, "Failed to initialize cryptographic engine.\n");
+ goto err_engine;
+ }
+
+ err = mtk_cipher_alg_register(cryp);
+ if (err) {
+ dev_err(cryp->dev, "Unable to register MTK-AES.\n");
+ goto err_cipher;
+ }
+
+ err = mtk_hash_alg_register(cryp);
+ if (err) {
+ dev_err(cryp->dev, "Unable to register MTK-SHA.\n");
+ goto err_hash;
+ }
+
+ platform_set_drvdata(pdev, cryp);
+ return 0;
+
+err_hash:
+ mtk_cipher_alg_release(cryp);
+err_cipher:
+ mtk_dfe_dse_reset(cryp);
+err_engine:
+ mtk_desc_dma_free(cryp);
+err_resource:
+ clk_disable_unprepare(cryp->clk_cryp);
+err_clk_cryp:
+ clk_disable_unprepare(cryp->clk_ethif);
+err_clk_ethif:
+ pm_runtime_put_sync(cryp->dev);
+ pm_runtime_disable(cryp->dev);
+
+ return err;
+}
+
+static int mtk_crypto_remove(struct platform_device *pdev)
+{
+ struct mtk_cryp *cryp = platform_get_drvdata(pdev);
+
+ mtk_hash_alg_release(cryp);
+ mtk_cipher_alg_release(cryp);
+ mtk_desc_dma_free(cryp);
+
+ clk_disable_unprepare(cryp->clk_cryp);
+ clk_disable_unprepare(cryp->clk_ethif);
+
+ pm_runtime_put_sync(cryp->dev);
+ pm_runtime_disable(cryp->dev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+const struct of_device_id of_crypto_id[] = {
+ { .compatible = "mediatek,mt7623-crypto" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_crypto_id);
+
+static struct platform_driver mtk_crypto_driver = {
+ .probe = mtk_crypto_probe,
+ .remove = mtk_crypto_remove,
+ .driver = {
+ .name = "mtk-crypto",
+ .owner = THIS_MODULE,
+ .of_match_table = of_crypto_id,
+ },
+};
+module_platform_driver(mtk_crypto_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>");
+MODULE_DESCRIPTION("Cryptographic accelerator driver for MediaTek SoC");
diff --git a/drivers/crypto/mediatek/mtk-platform.h b/drivers/crypto/mediatek/mtk-platform.h
new file mode 100644
index 0000000..5390ef4
--- /dev/null
+++ b/drivers/crypto/mediatek/mtk-platform.h
@@ -0,0 +1,230 @@
+/*
+ * Support for MediaTek cryptographic accelerator.
+ *
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ */
+
+#ifndef __MTK_PLATFORM_H_
+#define __MTK_PLATFORM_H_
+
+#include <linux/crypto.h>
+#include <crypto/internal/hash.h>
+#include <linux/interrupt.h>
+
+#define MTK_RDR_THRESH_DEF 0x800001
+
+#define MTK_IRQ_RDR0 BIT(1)
+#define MTK_IRQ_RDR1 BIT(3)
+#define MTK_IRQ_RDR2 BIT(5)
+#define MTK_IRQ_RDR3 BIT(7)
+
+#define MTK_DESC_CNT_CLR BIT(31)
+#define MTK_DESC_LAST BIT(22)
+#define MTK_DESC_FIRST BIT(23)
+#define MTK_DESC_BUF_LEN(x) ((x) & 0x1ffff)
+#define MTK_DESC_CT_LEN(x) (((x) & 0xff) << 24)
+
+#define WORD(x) ((x) >> 2)
+
+/**
+ * Ring 0/1 are used by AES encrypt and decrypt.
+ * Ring 2/3 are used by SHA.
+ */
+enum {
+ RING0 = 0,
+ RING1,
+ RING2,
+ RING3,
+ RING_MAX,
+};
+
+#define RECORD_NUM (RING_MAX / 2)
+
+/**
+ * struct mtk_desc - DMA descriptor
+ * @hdr: the descriptor control header
+ * @buf: DMA address of input buffer
+ * @ct: the command token that control operation flow
+ * @ct_hdr: the command token control header
+ * @tag: the user-defined field
+ * @tfm: DMA address of transform state
+ * @bound: align descriptors offset boundary
+ *
+ * Structure passed to the crypto engine to describe the crypto
+ * operation to be executed.
+ */
+struct mtk_desc {
+ u32 hdr;
+ u32 buf;
+ u32 ct;
+ u32 ct_hdr;
+ u32 tag;
+ u32 tfm;
+ u32 bound[2];
+};
+
+/**
+ * struct mtk_ring - Descriptor ring
+ * @cmd_base: pointer to command descriptor ring base
+ * @cmd_dma: DMA address of command descriptor ring
+ * @res_base: pointer to result descriptor ring base
+ * @res_dma: DMA address of result descriptor ring
+ * @pos: current position in the ring
+ */
+struct mtk_ring {
+ struct mtk_desc *cmd_base;
+ dma_addr_t cmd_dma;
+ struct mtk_desc *res_base;
+ dma_addr_t res_dma;
+ u32 pos;
+};
+
+#define MTK_MAX_DESC_NUM 512
+#define MTK_DESC_OFFSET WORD(sizeof(struct mtk_desc))
+#define MTK_DESC_SIZE (MTK_DESC_OFFSET - 2)
+#define MTK_MAX_RING_SIZE ((sizeof(struct mtk_desc) * MTK_MAX_DESC_NUM))
+#define MTK_DESC_CNT(x) ((MTK_DESC_OFFSET * (x)) << 2)
+
+/**
+ * struct mtk_aes_dma - Structure that holds sg list info
+ * @sg: pointer to scatter-gather list
+ * @nents: number of entries in the sg list
+ * @remainder: remainder of sg list
+ * @sg_len: number of entries in the sg mapped list
+ */
+struct mtk_aes_dma {
+ struct scatterlist *sg;
+ int nents;
+ u32 remainder;
+ u32 sg_len;
+};
+
+/**
+ * struct mtk_aes - AES operation record
+ * @queue: crypto request queue
+ * @req: pointer to ablkcipher request
+ * @task: the tasklet is use in AES interrupt
+ * @src: the structure that holds source sg list info
+ * @dst: the structure that holds destination sg list info
+ * @aligned_sg: the scatter list is use to alignment
+ * @real_dst: pointer to the destination sg list
+ * @total: request buffer length
+ * @buf: pointer to page buffer
+ * @info: pointer to AES transform state and command token
+ * @ct_hdr: AES command token control field
+ * @ct_size: size of AES command token
+ * @ct_dma: DMA address of AES command token
+ * @tfm_dma: DMA address of AES transform state
+ * @id: record identification
+ * @flags: it's describing AES operation state
+ * @lock: the ablkcipher queue lock
+ *
+ * Structure used to record AES execution state
+ */
+struct mtk_aes {
+ struct crypto_queue queue;
+ struct ablkcipher_request *req;
+ struct tasklet_struct task;
+ struct mtk_aes_dma src;
+ struct mtk_aes_dma dst;
+
+ struct scatterlist aligned_sg;
+ struct scatterlist *real_dst;
+
+ size_t total;
+ void *buf;
+
+ void *info;
+ u32 ct_hdr;
+ u32 ct_size;
+ dma_addr_t ct_dma;
+ dma_addr_t tfm_dma;
+
+ u8 id;
+ unsigned long flags;
+ /* queue lock */
+ spinlock_t lock;
+};
+
+/**
+ * struct mtk_sha - SHA operation record
+ * @queue: crypto request queue
+ * @req: pointer to ahash request
+ * @task: the tasklet is use in SHA interrupt
+ * @info: pointer to SHA transform state and command token
+ * @ct_hdr: SHA command token control field
+ * @ct_size: size of SHA command token
+ * @ct_dma: DMA address of SHA command token
+ * @tfm_dma: DMA address of SHA transform state
+ * @id: record identification
+ * @flags: it's describing SHA operation state
+ * @lock: the ablkcipher queue lock
+ *
+ * Structure used to record SHA execution state.
+ */
+struct mtk_sha {
+ struct crypto_queue queue;
+ struct ahash_request *req;
+ struct tasklet_struct task;
+
+ void *info;
+ u32 ct_hdr;
+ u32 ct_size;
+ dma_addr_t ct_dma;
+ dma_addr_t tfm_dma;
+
+ u8 id;
+ unsigned long flags;
+ /* queue lock */
+ spinlock_t lock;
+};
+
+/**
+ * struct mtk_cryp - Cryptographic device
+ * @base: pointer to mapped register I/O base
+ * @dev: pointer to device
+ * @clk_ethif: pointer to ethif clock
+ * @clk_cryp: pointer to crypto clock
+ * @irq: global system and rings IRQ
+ * @ring: pointer to execution state of AES
+ * @aes: pointer to execution state of SHA
+ * @sha: each execution record map to a ring
+ * @aes_list: device list of AES
+ * @sha_list: device list of SHA
+ * @tmp: pointer to temporary buffer for internal use
+ * @tmp_dma: DMA address of temporary buffer
+ * @rec: it's used to select SHA record for tfm
+ *
+ * Structure storing cryptographic device information.
+ */
+struct mtk_cryp {
+ void __iomem *base;
+ struct device *dev;
+ struct clk *clk_ethif;
+ struct clk *clk_cryp;
+ int irq[5];
+
+ struct mtk_ring *ring[RING_MAX];
+ struct mtk_aes *aes[RECORD_NUM];
+ struct mtk_sha *sha[RECORD_NUM];
+
+ struct list_head aes_list;
+ struct list_head sha_list;
+
+ void *tmp;
+ dma_addr_t tmp_dma;
+ bool rec;
+};
+
+int mtk_cipher_alg_register(struct mtk_cryp *cryp);
+void mtk_cipher_alg_release(struct mtk_cryp *cryp);
+int mtk_hash_alg_register(struct mtk_cryp *cryp);
+void mtk_hash_alg_release(struct mtk_cryp *cryp);
+
+#endif /* __MTK_PLATFORM_H_ */
diff --git a/drivers/crypto/mediatek/mtk-regs.h b/drivers/crypto/mediatek/mtk-regs.h
new file mode 100644
index 0000000..94f4eb8
--- /dev/null
+++ b/drivers/crypto/mediatek/mtk-regs.h
@@ -0,0 +1,194 @@
+/*
+ * Support for MediaTek cryptographic accelerator.
+ *
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ */
+
+#ifndef __MTK_REGS_H__
+#define __MTK_REGS_H__
+
+/* HIA, Command Descriptor Ring Manager */
+#define CDR_BASE_ADDR_LO(x) (0x0 + ((x) << 12))
+#define CDR_BASE_ADDR_HI(x) (0x4 + ((x) << 12))
+#define CDR_DATA_BASE_ADDR_LO(x) (0x8 + ((x) << 12))
+#define CDR_DATA_BASE_ADDR_HI(x) (0xC + ((x) << 12))
+#define CDR_ACD_BASE_ADDR_LO(x) (0x10 + ((x) << 12))
+#define CDR_ACD_BASE_ADDR_HI(x) (0x14 + ((x) << 12))
+#define CDR_RING_SIZE(x) (0x18 + ((x) << 12))
+#define CDR_DESC_SIZE(x) (0x1C + ((x) << 12))
+#define CDR_CFG(x) (0x20 + ((x) << 12))
+#define CDR_DMA_CFG(x) (0x24 + ((x) << 12))
+#define CDR_THRESH(x) (0x28 + ((x) << 12))
+#define CDR_PREP_COUNT(x) (0x2C + ((x) << 12))
+#define CDR_PROC_COUNT(x) (0x30 + ((x) << 12))
+#define CDR_PREP_PNTR(x) (0x34 + ((x) << 12))
+#define CDR_PROC_PNTR(x) (0x38 + ((x) << 12))
+#define CDR_STAT(x) (0x3C + ((x) << 12))
+
+/* HIA, Result Descriptor Ring Manager */
+#define RDR_BASE_ADDR_LO(x) (0x800 + ((x) << 12))
+#define RDR_BASE_ADDR_HI(x) (0x804 + ((x) << 12))
+#define RDR_DATA_BASE_ADDR_LO(x) (0x808 + ((x) << 12))
+#define RDR_DATA_BASE_ADDR_HI(x) (0x80C + ((x) << 12))
+#define RDR_ACD_BASE_ADDR_LO(x) (0x810 + ((x) << 12))
+#define RDR_ACD_BASE_ADDR_HI(x) (0x814 + ((x) << 12))
+#define RDR_RING_SIZE(x) (0x818 + ((x) << 12))
+#define RDR_DESC_SIZE(x) (0x81C + ((x) << 12))
+#define RDR_CFG(x) (0x820 + ((x) << 12))
+#define RDR_DMA_CFG(x) (0x824 + ((x) << 12))
+#define RDR_THRESH(x) (0x828 + ((x) << 12))
+#define RDR_PREP_COUNT(x) (0x82C + ((x) << 12))
+#define RDR_PROC_COUNT(x) (0x830 + ((x) << 12))
+#define RDR_PREP_PNTR(x) (0x834 + ((x) << 12))
+#define RDR_PROC_PNTR(x) (0x838 + ((x) << 12))
+#define RDR_STAT(x) (0x83C + ((x) << 12))
+
+/* HIA, Ring AIC */
+#define AIC_POL_CTRL(x) (0xE000 - ((x) << 12))
+#define AIC_TYPE_CTRL(x) (0xE004 - ((x) << 12))
+#define AIC_ENABLE_CTRL(x) (0xE008 - ((x) << 12))
+#define AIC_RAW_STAL(x) (0xE00C - ((x) << 12))
+#define AIC_ENABLE_SET(x) (0xE00C - ((x) << 12))
+#define AIC_ENABLED_STAT(x) (0xE010 - ((x) << 12))
+#define AIC_ACK(x) (0xE010 - ((x) << 12))
+#define AIC_ENABLE_CLR(x) (0xE014 - ((x) << 12))
+#define AIC_OPTIONS(x) (0xE018 - ((x) << 12))
+#define AIC_VERSION(x) (0xE01C - ((x) << 12))
+
+/* HIA, Global AIC */
+#define AIC_G_POL_CTRL 0xF800
+#define AIC_G_TYPE_CTRL 0xF804
+#define AIC_G_ENABLE_CTRL 0xF808
+#define AIC_G_RAW_STAT 0xF80C
+#define AIC_G_ENABLE_SET 0xF80C
+#define AIC_G_ENABLED_STAT 0xF810
+#define AIC_G_ACK 0xF810
+#define AIC_G_ENABLE_CLR 0xF814
+#define AIC_G_OPTIONS 0xF818
+#define AIC_G_VERSION 0xF81C
+
+/* HIA, Data Fetch Engine */
+#define DFE_CFG 0xF000
+#define DFE_PRIO_0 0xF010
+#define DFE_PRIO_1 0xF014
+#define DFE_PRIO_2 0xF018
+#define DFE_PRIO_3 0xF01C
+
+/* HIA, Data Fetch Engine access monitoring for CDR */
+#define DFE_RING_REGION_LO(x) (0xF080 + ((x) << 3))
+#define DFE_RING_REGION_HI(x) (0xF084 + ((x) << 3))
+
+/* HIA, Data Fetch Engine thread control and status for thread */
+#define DFE_THR_CTRL 0xF200
+#define DFE_THR_STAT 0xF204
+#define DFE_THR_DESC_CTRL 0xF208
+#define DFE_THR_DESC_DPTR_LO 0xF210
+#define DFE_THR_DESC_DPTR_HI 0xF214
+#define DFE_THR_DESC_ACDPTR_LO 0xF218
+#define DFE_THR_DESC_ACDPTR_HI 0xF21C
+
+/* HIA, Data Store Engine */
+#define DSE_CFG 0xF400
+#define DSE_PRIO_0 0xF410
+#define DSE_PRIO_1 0xF414
+#define DSE_PRIO_2 0xF418
+#define DSE_PRIO_3 0xF41C
+
+/* HIA, Data Store Engine access monitoring for RDR */
+#define DSE_RING_REGION_LO(x) (0xF480 + ((x) << 3))
+#define DSE_RING_REGION_HI(x) (0xF484 + ((x) << 3))
+
+/* HIA, Data Store Engine thread control and status for thread */
+#define DSE_THR_CTRL 0xF600
+#define DSE_THR_STAT 0xF604
+#define DSE_THR_DESC_CTRL 0xF608
+#define DSE_THR_DESC_DPTR_LO 0xF610
+#define DSE_THR_DESC_DPTR_HI 0xF614
+#define DSE_THR_DESC_S_DPTR_LO 0xF618
+#define DSE_THR_DESC_S_DPTR_HI 0xF61C
+#define DSE_THR_ERROR_STAT 0xF620
+
+/* HIA Global */
+#define HIA_MST_CTRL 0xFFF4
+#define HIA_OPTIONS 0xFFF8
+#define HIA_VERSION 0xFFFC
+
+/* Processing Engine Input Side, Processing Engine */
+#define PE_IN_DBUF_THRESH 0x10000
+#define PE_IN_TBUF_THRESH 0x10100
+
+/* Packet Engine Configuration / Status Registers */
+#define PE_TOKEN_CTRL_STAT 0x11000
+#define PE_FUNCTION_EN 0x11004
+#define PE_CONTEXT_CTRL 0x11008
+#define PE_INTERRUPT_CTRL_STAT 0x11010
+#define PE_CONTEXT_STAT 0x1100C
+#define PE_OUT_TRANS_CTRL_STAT 0x11018
+#define PE_OUT_BUF_CTRL 0x1101C
+
+/* Packet Engine PRNG Registers */
+#define PE_PRNG_STAT 0x11040
+#define PE_PRNG_CTRL 0x11044
+#define PE_PRNG_SEED_L 0x11048
+#define PE_PRNG_SEED_H 0x1104C
+#define PE_PRNG_KEY_0_L 0x11050
+#define PE_PRNG_KEY_0_H 0x11054
+#define PE_PRNG_KEY_1_L 0x11058
+#define PE_PRNG_KEY_1_H 0x1105C
+#define PE_PRNG_RES_0 0x11060
+#define PE_PRNG_RES_1 0x11064
+#define PE_PRNG_RES_2 0x11068
+#define PE_PRNG_RES_3 0x1106C
+#define PE_PRNG_LFSR_L 0x11070
+#define PE_PRNG_LFSR_H 0x11074
+
+/* Packet Engine AIC */
+#define PE_EIP96_AIC_POL_CTRL 0x113C0
+#define PE_EIP96_AIC_TYPE_CTRL 0x113C4
+#define PE_EIP96_AIC_ENABLE_CTRL 0x113C8
+#define PE_EIP96_AIC_RAW_STAT 0x113CC
+#define PE_EIP96_AIC_ENABLE_SET 0x113CC
+#define PE_EIP96_AIC_ENABLED_STAT 0x113D0
+#define PE_EIP96_AIC_ACK 0x113D0
+#define PE_EIP96_AIC_ENABLE_CLR 0x113D4
+#define PE_EIP96_AIC_OPTIONS 0x113D8
+#define PE_EIP96_AIC_VERSION 0x113DC
+
+/* Packet Engine Options & Version Registers */
+#define PE_EIP96_OPTIONS 0x113F8
+#define PE_EIP96_VERSION 0x113FC
+
+/* Processing Engine Output Side */
+#define PE_OUT_DBUF_THRESH 0x11C00
+#define PE_OUT_TBUF_THRESH 0x11D00
+
+/* Processing Engine Local AIC */
+#define PE_AIC_POL_CTRL 0x11F00
+#define PE_AIC_TYPE_CTRL 0x11F04
+#define PE_AIC_ENABLE_CTRL 0x11F08
+#define PE_AIC_RAW_STAT 0x11F0C
+#define PE_AIC_ENABLE_SET 0x11F0C
+#define PE_AIC_ENABLED_STAT 0x11F10
+#define PE_AIC_ENABLE_CLR 0x11F14
+#define PE_AIC_OPTIONS 0x11F18
+#define PE_AIC_VERSION 0x11F1C
+
+/* Processing Engine General Configuration and Version */
+#define PE_IN_FLIGHT 0x11FF0
+#define PE_OPTIONS 0x11FF8
+#define PE_VERSION 0x11FFC
+
+/* EIP-97 - Global */
+#define EIP97_CLOCK_STATE 0x1FFE4
+#define EIP97_FORCE_CLOCK_ON 0x1FFE8
+#define EIP97_FORCE_CLOCK_OFF 0x1FFEC
+#define EIP97_MST_CTRL 0x1FFF4
+#define EIP97_OPTIONS 0x1FFF8
+#define EIP97_VERSION 0x1FFFC
+#endif /* __MTK_REGS_H__ */
diff --git a/drivers/crypto/mediatek/mtk-sha.c b/drivers/crypto/mediatek/mtk-sha.c
new file mode 100644
index 0000000..45479bb
--- /dev/null
+++ b/drivers/crypto/mediatek/mtk-sha.c
@@ -0,0 +1,1384 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for MediaTek SHA1/SHA2 hardware accelerator.
+ *
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+ *
+ * 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.
+ *
+ * Some ideas are from atmel-sha.c and omap-sham.c drivers.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/algapi.h>
+#include <crypto/sha.h>
+#include <crypto/internal/hash.h>
+#include "mtk-platform.h"
+#include "mtk-regs.h"
+
+#define SHA_ALIGN_MSK (sizeof(u32) - 1)
+#define SHA_QUEUE_SIZE 512
+#define SHA_TMP_STATE_SIZE 512
+
+#define SHA_DATA_LEN_MSK GENMASK(16, 0)
+#define SHA_BUFFER_LEN ((u32)PAGE_SIZE)
+
+#define SHA_OP_UPDATE 1
+#define SHA_OP_FINAL 2
+
+/* SHA command token */
+#define SHA_CT_SIZE 5
+#define SHA_CT_CTRL_HDR 0x02220000
+#define SHA_COMMAND0 0x03020000
+#define SHA_COMMAND1 0x21060000
+#define SHA_COMMAND2 0xe0e63802
+
+/* SHA transform information */
+#define SHA_TFM_HASH (0x2 << 0)
+#define SHA_TFM_DIG_TYPE (0x1 << 21)
+#define SHA_TFM_SIZE(x) ((x) << 8)
+#define SHA_TFM_START (0x1 << 4)
+#define SHA_TFM_CONTINUE (0x1 << 5)
+#define SHA_TFM_HASH_STORE (0x1 << 19)
+#define SHA_TFM_SHA1 (0x2 << 23)
+#define SHA_TFM_SHA256 (0x3 << 23)
+#define SHA_TFM_SHA224 (0x4 << 23)
+#define SHA_TFM_SHA512 (0x5 << 23)
+#define SHA_TFM_SHA384 (0x6 << 23)
+#define SHA_TFM_DIGEST(x) (((x) & 0xf) << 24)
+
+/* SHA flags */
+#define SHA_FLAGS_BUSY BIT(0)
+#define SHA_FLAGS_FINAL BIT(1)
+#define SHA_FLAGS_FINUP BIT(2)
+#define SHA_FLAGS_SG BIT(3)
+#define SHA_FLAGS_ALGO_MASK GENMASK(8, 4)
+#define SHA_FLAGS_SHA1 BIT(4)
+#define SHA_FLAGS_SHA224 BIT(5)
+#define SHA_FLAGS_SHA256 BIT(6)
+#define SHA_FLAGS_SHA384 BIT(7)
+#define SHA_FLAGS_SHA512 BIT(8)
+#define SHA_FLAGS_HMAC BIT(9)
+#define SHA_FLAGS_PAD BIT(10)
+
+/* SHA command token */
+struct mtk_sha_ct {
+ u32 tfm_ctrl0;
+ u32 tfm_ctrl1;
+ u32 ct_ctrl0;
+ u32 ct_ctrl1;
+ u32 ct_ctrl2;
+};
+
+/* SHA transform state */
+struct mtk_sha_tfm {
+ u32 tfm_ctrl0;
+ u32 tfm_ctrl1;
+ u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32));
+};
+
+struct mtk_sha_info {
+ struct mtk_sha_ct ct;
+ struct mtk_sha_tfm tfm;
+};
+
+struct mtk_sha_reqctx {
+ struct mtk_sha_info info;
+ unsigned long flags;
+ unsigned long op;
+
+ u64 digcnt;
+ bool start;
+ size_t bufcnt;
+ dma_addr_t dma_addr;
+
+ /* walk state */
+ struct scatterlist *sg;
+ u32 offset; /* offset in current sg */
+ u32 total; /* total request */
+ size_t ds;
+ size_t bs;
+
+ u8 *buffer;
+};
+
+struct mtk_sha_hmac_ctx {
+ struct crypto_shash *shash;
+ u8 ipad[SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
+ u8 opad[SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
+};
+
+struct mtk_sha_ctx {
+ struct mtk_cryp *cryp;
+ unsigned long flags;
+ u8 id;
+ u8 buf[SHA_BUFFER_LEN] __aligned(sizeof(u32));
+
+ struct mtk_sha_hmac_ctx base[0];
+};
+
+struct mtk_sha_drv {
+ struct list_head dev_list;
+ /* device list lock */
+ spinlock_t lock;
+};
+
+static struct mtk_sha_drv mtk_sha = {
+ .dev_list = LIST_HEAD_INIT(mtk_sha.dev_list),
+ .lock = __SPIN_LOCK_UNLOCKED(mtk_sha.lock),
+};
+
+static int mtk_sha_handle_queue(struct mtk_cryp *cryp, u8 id,
+ struct ahash_request *req);
+
+static inline u32 mtk_sha_read(struct mtk_cryp *cryp, u32 offset)
+{
+ return readl_relaxed(cryp->base + offset);
+}
+
+static inline void mtk_sha_write(struct mtk_cryp *cryp,
+ u32 offset, u32 value)
+{
+ writel_relaxed(value, cryp->base + offset);
+}
+
+static struct mtk_cryp *mtk_sha_find_dev(struct mtk_sha_ctx *tctx)
+{
+ struct mtk_cryp *cryp = NULL;
+ struct mtk_cryp *tmp;
+
+ spin_lock_bh(&mtk_sha.lock);
+ if (!tctx->cryp) {
+ list_for_each_entry(tmp, &mtk_sha.dev_list, sha_list) {
+ cryp = tmp;
+ break;
+ }
+ tctx->cryp = cryp;
+ } else {
+ cryp = tctx->cryp;
+ }
+
+ /*
+ * Assign record id to tfm in round-robin fashion, and this
+ * help us to link to descriptor ring and record.
+ */
+ tctx->id = cryp->rec;
+ cryp->rec = !cryp->rec;
+
+ spin_unlock_bh(&mtk_sha.lock);
+
+ return cryp;
+}
+
+static int mtk_sha_append_sg(struct mtk_sha_reqctx *ctx)
+{
+ size_t count;
+
+ while ((ctx->bufcnt < SHA_BUFFER_LEN) && ctx->total) {
+ count = min(ctx->sg->length - ctx->offset, ctx->total);
+ count = min(count, SHA_BUFFER_LEN - ctx->bufcnt);
+
+ if (count <= 0) {
+ /*
+ * Check if count <= 0 because the buffer is full or
+ * because the sg length is 0. In the latest case,
+ * check if there is another sg in the list, a 0 length
+ * sg doesn't necessarily mean the end of the sg list.
+ */
+ if ((ctx->sg->length == 0) && !sg_is_last(ctx->sg)) {
+ ctx->sg = sg_next(ctx->sg);
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ scatterwalk_map_and_copy(ctx->buffer + ctx->bufcnt, ctx->sg,
+ ctx->offset, count, 0);
+
+ ctx->bufcnt += count;
+ ctx->offset += count;
+ ctx->total -= count;
+
+ if (ctx->offset == ctx->sg->length) {
+ ctx->sg = sg_next(ctx->sg);
+ if (ctx->sg)
+ ctx->offset = 0;
+ else
+ ctx->total = 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * The purpose of this padding is to ensure that the padded message is a
+ * multiple of 512 bits (SHA1/SHA224/SHA256) or 1024 bits (SHA384/SHA512).
+ * The bit "1" is appended at the end of the message followed by
+ * "padlen-1" zero bits. Then a 64 bits block (SHA1/SHA224/SHA256) or
+ * 128 bits block (SHA384/SHA512) equals to the message length in bits
+ * is appended.
+ *
+ * For SHA1/SHA224/SHA256, padlen is calculated as followed:
+ * - if message length < 56 bytes then padlen = 56 - message length
+ * - else padlen = 64 + 56 - message length
+ *
+ * For SHA384/SHA512, padlen is calculated as followed:
+ * - if message length < 112 bytes then padlen = 112 - message length
+ * - else padlen = 128 + 112 - message length
+ */
+static void mtk_sha_fill_padding(struct mtk_sha_reqctx *ctx, u32 len)
+{
+ u32 index, padlen;
+ u64 bits[2];
+ u64 size = ctx->digcnt;
+
+ size += ctx->bufcnt;
+ size += len;
+
+ bits[1] = cpu_to_be64(size << 3);
+ bits[0] = cpu_to_be64(size >> 61);
+
+ if (ctx->flags & (SHA_FLAGS_SHA384 | SHA_FLAGS_SHA512)) {
+ index = ctx->bufcnt & 0x7f;
+ padlen = (index < 112) ? (112 - index) : ((128 + 112) - index);
+ *(ctx->buffer + ctx->bufcnt) = 0x80;
+ memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
+ memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
+ ctx->bufcnt += padlen + 16;
+ ctx->flags |= SHA_FLAGS_PAD;
+ } else {
+ index = ctx->bufcnt & 0x3f;
+ padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
+ *(ctx->buffer + ctx->bufcnt) = 0x80;
+ memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
+ memcpy(ctx->buffer + ctx->bufcnt + padlen, &bits[1], 8);
+ ctx->bufcnt += padlen + 8;
+ ctx->flags |= SHA_FLAGS_PAD;
+ }
+}
+
+static void mtk_sha_info_init(struct mtk_sha *sha,
+ struct mtk_sha_reqctx *ctx)
+{
+ struct mtk_sha_info *info = sha->info;
+ struct mtk_sha_ct *ct = &info->ct;
+ struct mtk_sha_tfm *tfm = &info->tfm;
+
+ sha->ct_hdr = SHA_CT_CTRL_HDR;
+ sha->ct_size = SHA_CT_SIZE;
+
+ tfm->tfm_ctrl0 = SHA_TFM_HASH | SHA_TFM_DIG_TYPE |
+ SHA_TFM_SIZE(WORD(ctx->ds));
+
+ switch (ctx->flags & SHA_FLAGS_ALGO_MASK) {
+ case SHA_FLAGS_SHA1:
+ tfm->tfm_ctrl0 |= SHA_TFM_SHA1;
+ break;
+ case SHA_FLAGS_SHA224:
+ tfm->tfm_ctrl0 |= SHA_TFM_SHA224;
+ break;
+ case SHA_FLAGS_SHA256:
+ tfm->tfm_ctrl0 |= SHA_TFM_SHA256;
+ break;
+ case SHA_FLAGS_SHA384:
+ tfm->tfm_ctrl0 |= SHA_TFM_SHA384;
+ break;
+ case SHA_FLAGS_SHA512:
+ tfm->tfm_ctrl0 |= SHA_TFM_SHA512;
+ break;
+
+ default:
+ /* Should not happen... */
+ return;
+ }
+
+ tfm->tfm_ctrl1 = SHA_TFM_HASH_STORE;
+ ct->tfm_ctrl0 = tfm->tfm_ctrl0 | SHA_TFM_CONTINUE | SHA_TFM_START;
+ ct->tfm_ctrl1 = tfm->tfm_ctrl1;
+
+ ct->ct_ctrl0 = SHA_COMMAND0;
+ ct->ct_ctrl1 = SHA_COMMAND1;
+ ct->ct_ctrl2 = SHA_COMMAND2 | SHA_TFM_DIGEST(WORD(ctx->ds));
+}
+
+static int mtk_sha_info_map(struct mtk_cryp *cryp,
+ struct mtk_sha *sha, size_t len)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
+ struct mtk_sha_info *info = sha->info;
+ struct mtk_sha_ct *ct = &info->ct;
+
+ if (ctx->start)
+ ctx->start = false;
+ else
+ ct->tfm_ctrl0 &= ~SHA_TFM_START;
+
+ sha->ct_hdr = (sha->ct_hdr & ~SHA_DATA_LEN_MSK) | len;
+ ct->ct_ctrl0 = (ct->ct_ctrl0 & ~SHA_DATA_LEN_MSK) | len;
+
+ ctx->digcnt += len;
+
+ sha->ct_dma = dma_map_single(cryp->dev, info, sizeof(*info),
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(cryp->dev, sha->ct_dma))) {
+ dev_err(cryp->dev, "dma %d bytes error\n", sizeof(*info));
+ return -EINVAL;
+ }
+ sha->tfm_dma = sha->ct_dma + sizeof(*ct);
+
+ return 0;
+}
+
+static int mtk_sha_finish_hmac(struct ahash_request *req)
+{
+ struct mtk_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
+ struct mtk_sha_hmac_ctx *bctx = tctx->base;
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+
+ SHASH_DESC_ON_STACK(shash, bctx->shash);
+
+ shash->tfm = bctx->shash;
+ shash->flags = 0; /* not CRYPTO_TFM_REQ_MAY_SLEEP */
+
+ return crypto_shash_init(shash) ?:
+ crypto_shash_update(shash, bctx->opad, ctx->bs) ?:
+ crypto_shash_finup(shash, req->result, ctx->ds, req->result);
+}
+
+static int mtk_sha_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct mtk_sha_ctx *tctx = crypto_ahash_ctx(tfm);
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+
+ ctx->flags = 0;
+ ctx->ds = crypto_ahash_digestsize(tfm);
+
+ switch (ctx->ds) {
+ case SHA1_DIGEST_SIZE:
+ ctx->flags |= SHA_FLAGS_SHA1;
+ ctx->bs = SHA1_BLOCK_SIZE;
+ break;
+ case SHA224_DIGEST_SIZE:
+ ctx->flags |= SHA_FLAGS_SHA224;
+ ctx->bs = SHA224_BLOCK_SIZE;
+ break;
+ case SHA256_DIGEST_SIZE:
+ ctx->flags |= SHA_FLAGS_SHA256;
+ ctx->bs = SHA256_BLOCK_SIZE;
+ break;
+ case SHA384_DIGEST_SIZE:
+ ctx->flags |= SHA_FLAGS_SHA384;
+ ctx->bs = SHA384_BLOCK_SIZE;
+ break;
+ case SHA512_DIGEST_SIZE:
+ ctx->flags |= SHA_FLAGS_SHA512;
+ ctx->bs = SHA512_BLOCK_SIZE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ctx->bufcnt = 0;
+ ctx->digcnt = 0;
+ ctx->buffer = tctx->buf;
+ ctx->start = true;
+
+ if (tctx->flags & SHA_FLAGS_HMAC) {
+ struct mtk_sha_hmac_ctx *bctx = tctx->base;
+
+ memcpy(ctx->buffer, bctx->ipad, ctx->bs);
+ ctx->bufcnt = ctx->bs;
+ ctx->flags |= SHA_FLAGS_HMAC;
+ }
+
+ return 0;
+}
+
+static int mtk_sha_xmit(struct mtk_cryp *cryp, struct mtk_sha *sha,
+ dma_addr_t addr, size_t len)
+{
+ struct mtk_ring *ring = cryp->ring[sha->id];
+ struct mtk_desc *cmd = ring->cmd_base + ring->pos;
+ struct mtk_desc *res = ring->res_base + ring->pos;
+ int err;
+
+ err = mtk_sha_info_map(cryp, sha, len);
+ if (err)
+ return err;
+
+ res->hdr = MTK_DESC_FIRST | MTK_DESC_LAST |
+ MTK_DESC_BUF_LEN(len);
+
+ res->buf = cryp->tmp_dma;
+
+ cmd->hdr = MTK_DESC_FIRST | MTK_DESC_LAST |
+ MTK_DESC_BUF_LEN(len) |
+ MTK_DESC_CT_LEN(sha->ct_size);
+
+ cmd->buf = addr;
+ cmd->ct = sha->ct_dma;
+ cmd->ct_hdr = sha->ct_hdr;
+ cmd->tfm = sha->tfm_dma;
+
+ if (++ring->pos == MTK_MAX_DESC_NUM)
+ ring->pos = 0;
+
+ /* make sure all descriptor are filled done */
+ wmb();
+ mtk_sha_write(cryp, RDR_PREP_COUNT(sha->id), MTK_DESC_CNT(1));
+ mtk_sha_write(cryp, CDR_PREP_COUNT(sha->id), MTK_DESC_CNT(1));
+
+ return -EINPROGRESS;
+}
+
+static int mtk_sha_xmit2(struct mtk_cryp *cryp, struct mtk_sha *sha,
+ struct mtk_sha_reqctx *ctx, size_t len1, size_t len2)
+{
+ struct mtk_ring *ring = cryp->ring[sha->id];
+ struct mtk_desc *cmd = ring->cmd_base + ring->pos;
+ struct mtk_desc *res = ring->res_base + ring->pos;
+ int err;
+
+ err = mtk_sha_info_map(cryp, sha, len1 + len2);
+ if (err)
+ return err;
+
+ res->hdr = MTK_DESC_BUF_LEN(len1) | MTK_DESC_FIRST;
+ res->buf = cryp->tmp_dma;
+
+ cmd->hdr = MTK_DESC_BUF_LEN(len1) | MTK_DESC_FIRST |
+ MTK_DESC_CT_LEN(sha->ct_size);
+ cmd->buf = sg_dma_address(ctx->sg);
+ cmd->ct = sha->ct_dma;
+ cmd->ct_hdr = sha->ct_hdr;
+ cmd->tfm = sha->tfm_dma;
+
+ if (++ring->pos == MTK_MAX_DESC_NUM)
+ ring->pos = 0;
+
+ cmd = ring->cmd_base + ring->pos;
+ res = ring->res_base + ring->pos;
+
+ res->hdr = MTK_DESC_BUF_LEN(len2) | MTK_DESC_LAST;
+ res->buf = cryp->tmp_dma;
+
+ cmd->hdr = MTK_DESC_BUF_LEN(len2) | MTK_DESC_LAST;
+ cmd->buf = ctx->dma_addr;
+
+ if (++ring->pos == MTK_MAX_DESC_NUM)
+ ring->pos = 0;
+
+ /* make sure all descriptor are filled done */
+ wmb();
+ mtk_sha_write(cryp, RDR_PREP_COUNT(sha->id), MTK_DESC_CNT(2));
+ mtk_sha_write(cryp, CDR_PREP_COUNT(sha->id), MTK_DESC_CNT(2));
+
+ return -EINPROGRESS;
+}
+
+static int mtk_sha_dma_map(struct mtk_cryp *cryp, struct mtk_sha *sha,
+ struct mtk_sha_reqctx *ctx, size_t count)
+{
+ ctx->dma_addr = dma_map_single(cryp->dev, ctx->buffer,
+ SHA_BUFFER_LEN, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(cryp->dev, ctx->dma_addr))) {
+ dev_err(cryp->dev, "dma map error\n");
+ return -EINVAL;
+ }
+
+ ctx->flags &= ~SHA_FLAGS_SG;
+
+ return mtk_sha_xmit(cryp, sha, ctx->dma_addr, count);
+}
+
+static int mtk_sha_update_slow(struct mtk_cryp *cryp, struct mtk_sha *sha)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
+ size_t count;
+ u32 final;
+
+ mtk_sha_append_sg(ctx);
+
+ final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
+
+ dev_dbg(cryp->dev, "slow: bufcnt: %u\n", ctx->bufcnt);
+
+ if (final) {
+ sha->flags |= SHA_FLAGS_FINAL;
+ mtk_sha_fill_padding(ctx, 0);
+ }
+
+ if (final || (ctx->bufcnt == SHA_BUFFER_LEN && ctx->total)) {
+ count = ctx->bufcnt;
+ ctx->bufcnt = 0;
+
+ return mtk_sha_dma_map(cryp, sha, ctx, count);
+ }
+ return 0;
+}
+
+static int mtk_sha_update_req(struct mtk_cryp *cryp, struct mtk_sha *sha)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
+ u32 len, final, tail;
+ struct scatterlist *sg;
+
+ if (!ctx->total)
+ return 0;
+
+ if (ctx->bufcnt || ctx->offset)
+ return mtk_sha_update_slow(cryp, sha);
+
+ sg = ctx->sg;
+
+ if (!IS_ALIGNED(sg->offset, sizeof(u32)))
+ return mtk_sha_update_slow(cryp, sha);
+
+ if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, ctx->bs))
+ /* size is not bs aligned */
+ return mtk_sha_update_slow(cryp, sha);
+
+ len = min(ctx->total, sg->length);
+
+ if (sg_is_last(sg)) {
+ if (!(ctx->flags & SHA_FLAGS_FINUP)) {
+ /* not last sg must be bs aligned */
+ tail = len & (ctx->bs - 1);
+ len -= tail;
+ }
+ }
+
+ ctx->total -= len;
+ ctx->offset = len; /* offset where to start slow */
+
+ final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
+
+ /* Add padding */
+ if (final) {
+ size_t count;
+
+ tail = len & (ctx->bs - 1);
+ len -= tail;
+ ctx->total += tail;
+ ctx->offset = len; /* offset where to start slow */
+
+ sg = ctx->sg;
+ mtk_sha_append_sg(ctx);
+ mtk_sha_fill_padding(ctx, len);
+
+ ctx->dma_addr = dma_map_single(cryp->dev, ctx->buffer,
+ SHA_BUFFER_LEN, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(cryp->dev, ctx->dma_addr))) {
+ dev_err(cryp->dev, "dma map bytes error\n");
+ return -EINVAL;
+ }
+
+ sha->flags |= SHA_FLAGS_FINAL;
+ count = ctx->bufcnt;
+ ctx->bufcnt = 0;
+
+ if (len == 0) {
+ ctx->flags &= ~SHA_FLAGS_SG;
+ return mtk_sha_xmit(cryp, sha, ctx->dma_addr, count);
+
+ } else {
+ ctx->sg = sg;
+ if (!dma_map_sg(cryp->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
+ dev_err(cryp->dev, "dma_map_sg error\n");
+ return -EINVAL;
+ }
+
+ ctx->flags |= SHA_FLAGS_SG;
+ return mtk_sha_xmit2(cryp, sha, ctx, len, count);
+ }
+ }
+
+ if (!dma_map_sg(cryp->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
+ dev_err(cryp->dev, "dma_map_sg error\n");
+ return -EINVAL;
+ }
+
+ ctx->flags |= SHA_FLAGS_SG;
+
+ return mtk_sha_xmit(cryp, sha, sg_dma_address(ctx->sg), len);
+}
+
+static int mtk_sha_final_req(struct mtk_cryp *cryp, struct mtk_sha *sha)
+{
+ struct ahash_request *req = sha->req;
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+ size_t count;
+
+ mtk_sha_fill_padding(ctx, 0);
+
+ sha->flags |= SHA_FLAGS_FINAL;
+ count = ctx->bufcnt;
+ ctx->bufcnt = 0;
+
+ return mtk_sha_dma_map(cryp, sha, ctx, count);
+}
+
+static int mtk_sha_finish(struct ahash_request *req)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+ u8 *digest = ctx->info.tfm.digest;
+
+ memcpy(req->result, digest, ctx->ds);
+
+ if (ctx->flags & SHA_FLAGS_HMAC)
+ return mtk_sha_finish_hmac(req);
+
+ return 0;
+}
+
+static void mtk_sha_finish_req(struct mtk_cryp *cryp,
+ struct mtk_sha *sha, int err)
+{
+ if (likely(!err && (SHA_FLAGS_FINAL & sha->flags)))
+ err = mtk_sha_finish(sha->req);
+
+ sha->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL);
+
+ sha->req->base.complete(&sha->req->base, err);
+ mtk_sha_handle_queue(cryp, sha->id - RING2, NULL);
+}
+
+static int mtk_sha_handle_queue(struct mtk_cryp *cryp, u8 id,
+ struct ahash_request *req)
+{
+ struct mtk_sha *sha = cryp->sha[id];
+ struct crypto_async_request *async_req, *backlog;
+ struct mtk_sha_reqctx *ctx;
+ unsigned long flags;
+ int err = 0, ret = 0;
+
+ spin_lock_irqsave(&sha->lock, flags);
+ if (req)
+ ret = ahash_enqueue_request(&sha->queue, req);
+
+ if (SHA_FLAGS_BUSY & sha->flags) {
+ spin_unlock_irqrestore(&sha->lock, flags);
+ return ret;
+ }
+
+ backlog = crypto_get_backlog(&sha->queue);
+ async_req = crypto_dequeue_request(&sha->queue);
+ if (async_req)
+ sha->flags |= SHA_FLAGS_BUSY;
+ spin_unlock_irqrestore(&sha->lock, flags);
+
+ if (!async_req)
+ return ret;
+
+ if (backlog)
+ backlog->complete(backlog, -EINPROGRESS);
+
+ req = ahash_request_cast(async_req);
+ ctx = ahash_request_ctx(req);
+
+ sha->req = req;
+ sha->info = &ctx->info;
+
+ mtk_sha_info_init(sha, ctx);
+
+ if (ctx->op == SHA_OP_UPDATE) {
+ err = mtk_sha_update_req(cryp, sha);
+ if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
+ /* no final() after finup() */
+ err = mtk_sha_final_req(cryp, sha);
+ } else if (ctx->op == SHA_OP_FINAL) {
+ err = mtk_sha_final_req(cryp, sha);
+ }
+
+ if (unlikely(err != -EINPROGRESS))
+ /* task will not finish it, so do it here */
+ mtk_sha_finish_req(cryp, sha, err);
+
+ return ret;
+}
+
+static int mtk_sha_enqueue(struct ahash_request *req, u32 op)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+ struct mtk_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
+
+ ctx->op = op;
+
+ return mtk_sha_handle_queue(tctx->cryp, tctx->id, req);
+}
+
+static void mtk_sha_unmap(struct mtk_cryp *cryp, struct mtk_sha *sha)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
+
+ dma_unmap_single(cryp->dev, sha->ct_dma,
+ sizeof(struct mtk_sha_info), DMA_BIDIRECTIONAL);
+
+ if (ctx->flags & SHA_FLAGS_SG) {
+ dma_unmap_sg(cryp->dev, ctx->sg, 1, DMA_TO_DEVICE);
+ if (ctx->sg->length == ctx->offset) {
+ ctx->sg = sg_next(ctx->sg);
+ if (ctx->sg)
+ ctx->offset = 0;
+ }
+ if (ctx->flags & SHA_FLAGS_PAD) {
+ dma_unmap_single(cryp->dev, ctx->dma_addr,
+ SHA_BUFFER_LEN, DMA_TO_DEVICE);
+ }
+ } else
+ dma_unmap_single(cryp->dev, ctx->dma_addr,
+ SHA_BUFFER_LEN, DMA_TO_DEVICE);
+}
+
+static void mtk_sha_complete(struct mtk_cryp *cryp, struct mtk_sha *sha)
+{
+ int err = 0;
+
+ err = mtk_sha_update_req(cryp, sha);
+ if (err != -EINPROGRESS)
+ mtk_sha_finish_req(cryp, sha, err);
+}
+
+static int mtk_sha_update(struct ahash_request *req)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+
+ ctx->total = req->nbytes;
+ ctx->sg = req->src;
+ ctx->offset = 0;
+
+ if ((ctx->bufcnt + ctx->total < SHA_BUFFER_LEN) &&
+ !(ctx->flags & SHA_FLAGS_FINUP))
+ return mtk_sha_append_sg(ctx);
+
+ return mtk_sha_enqueue(req, SHA_OP_UPDATE);
+}
+
+static int mtk_sha_final(struct ahash_request *req)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+
+ ctx->flags |= SHA_FLAGS_FINUP;
+
+ if (ctx->flags & SHA_FLAGS_PAD)
+ return mtk_sha_finish(req);
+
+ return mtk_sha_enqueue(req, SHA_OP_FINAL);
+}
+
+static int mtk_sha_finup(struct ahash_request *req)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+ int err1, err2;
+
+ ctx->flags |= SHA_FLAGS_FINUP;
+
+ err1 = mtk_sha_update(req);
+ if (err1 == -EINPROGRESS || err1 == -EBUSY)
+ return err1;
+ /*
+ * final() has to be always called to cleanup resources
+ * even if update() failed
+ */
+ err2 = mtk_sha_final(req);
+
+ return err1 ?: err2;
+}
+
+static int mtk_sha_digest(struct ahash_request *req)
+{
+ return mtk_sha_init(req) ?: mtk_sha_finup(req);
+}
+
+static int mtk_sha_setkey(struct crypto_ahash *tfm,
+ const unsigned char *key, u32 keylen)
+{
+ struct mtk_sha_ctx *tctx = crypto_ahash_ctx(tfm);
+ struct mtk_sha_hmac_ctx *bctx = tctx->base;
+ size_t bs = crypto_shash_blocksize(bctx->shash);
+ size_t ds = crypto_shash_digestsize(bctx->shash);
+ int err, i;
+
+ SHASH_DESC_ON_STACK(shash, bctx->shash);
+
+ shash->tfm = bctx->shash;
+ shash->flags = crypto_shash_get_flags(bctx->shash) &
+ CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ if (keylen > bs) {
+ err = crypto_shash_digest(shash, key, keylen, bctx->ipad);
+ if (err)
+ return err;
+ keylen = ds;
+ } else {
+ memcpy(bctx->ipad, key, keylen);
+ }
+
+ memset(bctx->ipad + keylen, 0, bs - keylen);
+ memcpy(bctx->opad, bctx->ipad, bs);
+
+ for (i = 0; i < bs; i++) {
+ bctx->ipad[i] ^= 0x36;
+ bctx->opad[i] ^= 0x5c;
+ }
+
+ return err;
+}
+
+static int mtk_sha_export(struct ahash_request *req, void *out)
+{
+ const struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+
+ memcpy(out, ctx, sizeof(*ctx));
+ return 0;
+}
+
+static int mtk_sha_import(struct ahash_request *req, const void *in)
+{
+ struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
+
+ memcpy(ctx, in, sizeof(*ctx));
+ return 0;
+}
+
+static int mtk_sha_cra_init_alg(struct crypto_tfm *tfm,
+ const char *alg_base)
+{
+ struct mtk_sha_ctx *tctx = crypto_tfm_ctx(tfm);
+ struct mtk_cryp *cryp = NULL;
+
+ cryp = mtk_sha_find_dev(tctx);
+ if (!cryp)
+ return -ENODEV;
+
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct mtk_sha_reqctx));
+
+ if (alg_base) {
+ struct mtk_sha_hmac_ctx *bctx = tctx->base;
+
+ tctx->flags |= SHA_FLAGS_HMAC;
+ bctx->shash = crypto_alloc_shash(alg_base, 0,
+ CRYPTO_ALG_NEED_FALLBACK);
+ if (IS_ERR(bctx->shash)) {
+ pr_err("base driver %s could not be loaded.\n",
+ alg_base);
+
+ return PTR_ERR(bctx->shash);
+ }
+ }
+ return 0;
+}
+
+static int mtk_sha_cra_init(struct crypto_tfm *tfm)
+{
+ return mtk_sha_cra_init_alg(tfm, NULL);
+}
+
+static int mtk_sha_cra_sha1_init(struct crypto_tfm *tfm)
+{
+ return mtk_sha_cra_init_alg(tfm, "sha1");
+}
+
+static int mtk_sha_cra_sha224_init(struct crypto_tfm *tfm)
+{
+ return mtk_sha_cra_init_alg(tfm, "sha224");
+}
+
+static int mtk_sha_cra_sha256_init(struct crypto_tfm *tfm)
+{
+ return mtk_sha_cra_init_alg(tfm, "sha256");
+}
+
+static int mtk_sha_cra_sha384_init(struct crypto_tfm *tfm)
+{
+ return mtk_sha_cra_init_alg(tfm, "sha384");
+}
+
+static int mtk_sha_cra_sha512_init(struct crypto_tfm *tfm)
+{
+ return mtk_sha_cra_init_alg(tfm, "sha512");
+}
+
+static void mtk_sha_cra_exit(struct crypto_tfm *tfm)
+{
+ struct mtk_sha_ctx *tctx = crypto_tfm_ctx(tfm);
+
+ if (tctx->flags & SHA_FLAGS_HMAC) {
+ struct mtk_sha_hmac_ctx *bctx = tctx->base;
+
+ crypto_free_shash(bctx->shash);
+ }
+}
+
+static struct ahash_alg algs_sha1_sha224_sha256[] = {
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "sha1",
+ .cra_driver_name = "mtk-sha1",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .halg.digestsize = SHA224_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "sha224",
+ .cra_driver_name = "mtk-sha224",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "sha256",
+ .cra_driver_name = "mtk-sha256",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .setkey = mtk_sha_setkey,
+ .halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "mtk-hmac-sha1",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx) +
+ sizeof(struct mtk_sha_hmac_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_sha1_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .setkey = mtk_sha_setkey,
+ .halg.digestsize = SHA224_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "hmac(sha224)",
+ .cra_driver_name = "mtk-hmac-sha224",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx) +
+ sizeof(struct mtk_sha_hmac_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_sha224_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .setkey = mtk_sha_setkey,
+ .halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "mtk-hmac-sha256",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx) +
+ sizeof(struct mtk_sha_hmac_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_sha256_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+};
+
+static struct ahash_alg algs_sha384_sha512[] = {
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .halg.digestsize = SHA384_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "sha384",
+ .cra_driver_name = "mtk-sha384",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .halg.digestsize = SHA512_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "sha512",
+ .cra_driver_name = "mtk-sha512",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .setkey = mtk_sha_setkey,
+ .halg.digestsize = SHA384_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "mtk-hmac-sha384",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx) +
+ sizeof(struct mtk_sha_hmac_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_sha384_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+{
+ .init = mtk_sha_init,
+ .update = mtk_sha_update,
+ .final = mtk_sha_final,
+ .finup = mtk_sha_finup,
+ .digest = mtk_sha_digest,
+ .export = mtk_sha_export,
+ .import = mtk_sha_import,
+ .setkey = mtk_sha_setkey,
+ .halg.digestsize = SHA512_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct mtk_sha_reqctx),
+ .halg.base = {
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "mtk-hmac-sha512",
+ .cra_priority = 400,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct mtk_sha_ctx) +
+ sizeof(struct mtk_sha_hmac_ctx),
+ .cra_alignmask = SHA_ALIGN_MSK,
+ .cra_module = THIS_MODULE,
+ .cra_init = mtk_sha_cra_sha512_init,
+ .cra_exit = mtk_sha_cra_exit,
+ }
+},
+};
+
+static void mtk_sha_task0(unsigned long data)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)data;
+ struct mtk_sha *sha = cryp->sha[0];
+
+ mtk_sha_unmap(cryp, sha);
+ mtk_sha_complete(cryp, sha);
+}
+
+static void mtk_sha_task1(unsigned long data)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)data;
+ struct mtk_sha *sha = cryp->sha[1];
+
+ mtk_sha_unmap(cryp, sha);
+ mtk_sha_complete(cryp, sha);
+}
+
+static irqreturn_t mtk_sha_ring2_irq(int irq, void *dev_id)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)dev_id;
+ struct mtk_sha *sha = cryp->sha[0];
+ u32 val = mtk_sha_read(cryp, RDR_STAT(RING2));
+
+ mtk_sha_write(cryp, RDR_STAT(RING2), val);
+
+ if (likely((SHA_FLAGS_BUSY & sha->flags))) {
+ mtk_sha_write(cryp, RDR_PROC_COUNT(RING2), MTK_DESC_CNT_CLR);
+ mtk_sha_write(cryp, RDR_THRESH(RING2), MTK_RDR_THRESH_DEF);
+
+ tasklet_schedule(&sha->task);
+ } else {
+ dev_warn(cryp->dev, "AES interrupt when no active requests.\n");
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mtk_sha_ring3_irq(int irq, void *dev_id)
+{
+ struct mtk_cryp *cryp = (struct mtk_cryp *)dev_id;
+ struct mtk_sha *sha = cryp->sha[1];
+ u32 val = mtk_sha_read(cryp, RDR_STAT(RING3));
+
+ mtk_sha_write(cryp, RDR_STAT(RING3), val);
+
+ if (likely((SHA_FLAGS_BUSY & sha->flags))) {
+ mtk_sha_write(cryp, RDR_PROC_COUNT(RING3), MTK_DESC_CNT_CLR);
+ mtk_sha_write(cryp, RDR_THRESH(RING3), MTK_RDR_THRESH_DEF);
+
+ tasklet_schedule(&sha->task);
+ } else {
+ dev_warn(cryp->dev, "AES interrupt when no active requests.\n");
+ }
+ return IRQ_HANDLED;
+}
+
+static int mtk_sha_record_init(struct mtk_cryp *cryp)
+{
+ struct mtk_sha **sha = cryp->sha;
+ int i, err = -ENOMEM;
+
+ for (i = 0; i < RECORD_NUM; i++) {
+ sha[i] = kzalloc(sizeof(**sha), GFP_KERNEL);
+ if (!sha[i])
+ goto err_cleanup;
+
+ sha[i]->id = i + RING2;
+
+ spin_lock_init(&sha[i]->lock);
+ crypto_init_queue(&sha[i]->queue, SHA_QUEUE_SIZE);
+ }
+
+ tasklet_init(&sha[0]->task, mtk_sha_task0, (unsigned long)cryp);
+ tasklet_init(&sha[1]->task, mtk_sha_task1, (unsigned long)cryp);
+
+ cryp->rec = 1;
+
+ return 0;
+
+err_cleanup:
+ for (; i--; )
+ kfree(sha[i]);
+ return err;
+}
+
+static void mtk_sha_record_free(struct mtk_cryp *cryp)
+{
+ int i;
+
+ for (i = 0; i < RECORD_NUM; i++) {
+ tasklet_kill(&cryp->sha[i]->task);
+ kfree(cryp->sha[i]);
+ }
+}
+
+static void mtk_sha_unregister_algs(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(algs_sha1_sha224_sha256); i++)
+ crypto_unregister_ahash(&algs_sha1_sha224_sha256[i]);
+
+ for (i = 0; i < ARRAY_SIZE(algs_sha384_sha512); i++)
+ crypto_unregister_ahash(&algs_sha384_sha512[i]);
+}
+
+static int mtk_sha_register_algs(void)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(algs_sha1_sha224_sha256); i++) {
+ err = crypto_register_ahash(&algs_sha1_sha224_sha256[i]);
+ if (err)
+ goto err_sha_224_256_algs;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(algs_sha384_sha512); i++) {
+ err = crypto_register_ahash(&algs_sha384_sha512[i]);
+ if (err)
+ goto err_sha_384_512_algs;
+ }
+
+ return 0;
+
+err_sha_384_512_algs:
+ for (; i--; )
+ crypto_unregister_ahash(&algs_sha384_sha512[i]);
+ i = ARRAY_SIZE(algs_sha1_sha224_sha256);
+err_sha_224_256_algs:
+ for (; i--; )
+ crypto_unregister_ahash(&algs_sha1_sha224_sha256[i]);
+
+ return err;
+}
+
+int mtk_hash_alg_register(struct mtk_cryp *cryp)
+{
+ int err;
+
+ INIT_LIST_HEAD(&cryp->sha_list);
+
+ err = mtk_sha_record_init(cryp);
+ if (err)
+ goto err_record;
+
+ err = devm_request_irq(cryp->dev, cryp->irq[RING2],
+ mtk_sha_ring2_irq, IRQF_TRIGGER_LOW,
+ "mtk-sha", cryp);
+ if (err) {
+ dev_err(cryp->dev, "unable to request sha irq0.\n");
+ goto err_res;
+ }
+
+ err = devm_request_irq(cryp->dev, cryp->irq[RING3],
+ mtk_sha_ring3_irq, IRQF_TRIGGER_LOW,
+ "mtk-sha", cryp);
+ if (err) {
+ dev_err(cryp->dev, "unable to request sha irq1.\n");
+ goto err_res;
+ }
+
+ /* enable ring2 and ring3 interrupt for hash */
+ mtk_sha_write(cryp, AIC_ENABLE_SET(RING2), MTK_IRQ_RDR2);
+ mtk_sha_write(cryp, AIC_ENABLE_SET(RING3), MTK_IRQ_RDR3);
+
+ cryp->tmp = dma_alloc_coherent(cryp->dev, SHA_TMP_STATE_SIZE,
+ &cryp->tmp_dma, GFP_KERNEL);
+ if (!cryp->tmp) {
+ dev_err(cryp->dev, "unable to allocate tmp buffer.\n");
+ err = -EINVAL;
+ goto err_res;
+ }
+
+ spin_lock(&mtk_sha.lock);
+ list_add_tail(&cryp->sha_list, &mtk_sha.dev_list);
+ spin_unlock(&mtk_sha.lock);
+
+ err = mtk_sha_register_algs();
+ if (err)
+ goto err_algs;
+
+ return 0;
+
+err_algs:
+ spin_lock(&mtk_sha.lock);
+ list_del(&cryp->sha_list);
+ spin_unlock(&mtk_sha.lock);
+ dma_free_coherent(cryp->dev, SHA_TMP_STATE_SIZE,
+ cryp->tmp, cryp->tmp_dma);
+err_res:
+ mtk_sha_record_free(cryp);
+err_record:
+
+ dev_err(cryp->dev, "mtk-sha initialization failed.\n");
+ return err;
+}
+EXPORT_SYMBOL(mtk_hash_alg_register);
+
+void mtk_hash_alg_release(struct mtk_cryp *cryp)
+{
+ spin_lock(&mtk_sha.lock);
+ list_del(&cryp->sha_list);
+ spin_unlock(&mtk_sha.lock);
+
+ mtk_sha_unregister_algs();
+ dma_free_coherent(cryp->dev, SHA_TMP_STATE_SIZE,
+ cryp->tmp, cryp->tmp_dma);
+ mtk_sha_record_free(cryp);
+}
+EXPORT_SYMBOL(mtk_hash_alg_release);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox