* [PATCH v7 5/6] arm: dts: mt2712: Add clock controller device nodes
From: Weiyi Lu @ 2017-11-28 7:28 UTC (permalink / raw)
To: Matthias Brugger, Stephen Boyd, Mike Turquette, Rob Herring
Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu
In-Reply-To: <1511854102-23195-1-git-send-email-weiyi.lu@mediatek.com>
Add clock controller nodes for MT2712, include topckgen, infracfg,
pericfg, mcucfg and apmixedsys. This patch also add six oscillators that
provide clocks for MT2712.
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 115 ++++++++++++++++++++++++++++++
1 file changed, 115 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
index 5d4e406..5703793 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: (GPL-2.0 OR MIT)
*/
+#include <dt-bindings/clock/mt2712-clk.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -98,6 +99,48 @@
#clock-cells = <0>;
};
+ clk26m: oscillator@0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "clk26m";
+ };
+
+ clk32k: oscillator@1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "clk32k";
+ };
+
+ clkfpc: oscillator@2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ clock-output-names = "clkfpc";
+ };
+
+ clkaud_ext_i_0: oscillator@3 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <6500000>;
+ clock-output-names = "clkaud_ext_i_0";
+ };
+
+ clkaud_ext_i_1: oscillator@4 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <196608000>;
+ clock-output-names = "clkaud_ext_i_1";
+ };
+
+ clkaud_ext_i_2: oscillator@5 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <180633600>;
+ clock-output-names = "clkaud_ext_i_2";
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupt-parent = <&gic>;
@@ -111,6 +154,24 @@
(GIC_CPU_MASK_RAW(0x13) | IRQ_TYPE_LEVEL_LOW)>;
};
+ topckgen: syscon@10000000 {
+ compatible = "mediatek,mt2712-topckgen", "syscon";
+ reg = <0 0x10000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ infracfg: syscon@10001000 {
+ compatible = "mediatek,mt2712-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ pericfg: syscon@10003000 {
+ compatible = "mediatek,mt2712-pericfg", "syscon";
+ reg = <0 0x10003000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
uart5: serial@1000f000 {
compatible = "mediatek,mt2712-uart",
"mediatek,mt6577-uart";
@@ -121,6 +182,18 @@
status = "disabled";
};
+ apmixedsys: syscon@10209000 {
+ compatible = "mediatek,mt2712-apmixedsys", "syscon";
+ reg = <0 0x10209000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ mcucfg: syscon@10220000 {
+ compatible = "mediatek,mt2712-mcucfg", "syscon";
+ reg = <0 0x10220000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
sysirq: interrupt-controller@10220a80 {
compatible = "mediatek,mt2712-sysirq",
"mediatek,mt6577-sysirq";
@@ -192,5 +265,47 @@
clock-names = "baud", "bus";
status = "disabled";
};
+
+ mfgcfg: syscon@13000000 {
+ compatible = "mediatek,mt2712-mfgcfg", "syscon";
+ reg = <0 0x13000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ mmsys: syscon@14000000 {
+ compatible = "mediatek,mt2712-mmsys", "syscon";
+ reg = <0 0x14000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ imgsys: syscon@15000000 {
+ compatible = "mediatek,mt2712-imgsys", "syscon";
+ reg = <0 0x15000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ bdpsys: syscon@15010000 {
+ compatible = "mediatek,mt2712-bdpsys", "syscon";
+ reg = <0 0x15010000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ vdecsys: syscon@16000000 {
+ compatible = "mediatek,mt2712-vdecsys", "syscon";
+ reg = <0 0x16000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ vencsys: syscon@18000000 {
+ compatible = "mediatek,mt2712-vencsys", "syscon";
+ reg = <0 0x18000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ jpgdecsys: syscon@19000000 {
+ compatible = "mediatek,mt2712-jpgdecsys", "syscon";
+ reg = <0 0x19000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
};
--
1.9.1
^ permalink raw reply related
* [PATCH v7 4/6] soc: mediatek: add MT2712 scpsys support
From: Weiyi Lu @ 2017-11-28 7:28 UTC (permalink / raw)
To: Matthias Brugger, Stephen Boyd, Mike Turquette, Rob Herring
Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu
In-Reply-To: <1511854102-23195-1-git-send-email-weiyi.lu@mediatek.com>
add scpsys driver for MT2712
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
drivers/soc/mediatek/mtk-scpsys.c | 106 +++++++++++++++++++++++++++++++++++---
1 file changed, 100 insertions(+), 6 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index c0f3219..435ce5e 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -21,6 +21,7 @@
#include <linux/soc/mediatek/infracfg.h>
#include <dt-bindings/power/mt2701-power.h>
+#include <dt-bindings/power/mt2712-power.h>
#include <dt-bindings/power/mt6797-power.h>
#include <dt-bindings/power/mt7622-power.h>
#include <dt-bindings/power/mt8173-power.h>
@@ -32,7 +33,7 @@
#define SPM_DIS_PWR_CON 0x023c
#define SPM_CONN_PWR_CON 0x0280
#define SPM_VEN2_PWR_CON 0x0298
-#define SPM_AUDIO_PWR_CON 0x029c /* MT8173 */
+#define SPM_AUDIO_PWR_CON 0x029c /* MT8173, MT2712 */
#define SPM_BDP_PWR_CON 0x029c /* MT2701 */
#define SPM_ETH_PWR_CON 0x02a0
#define SPM_HIF_PWR_CON 0x02a4
@@ -40,12 +41,12 @@
#define SPM_MFG_2D_PWR_CON 0x02c0
#define SPM_MFG_ASYNC_PWR_CON 0x02c4
#define SPM_USB_PWR_CON 0x02cc
+#define SPM_USB2_PWR_CON 0x02d4 /* MT2712 */
#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */
#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */
#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */
#define SPM_WB_PWR_CON 0x02ec /* MT7622 */
-
#define SPM_PWR_STATUS 0x060c
#define SPM_PWR_STATUS_2ND 0x0610
@@ -64,12 +65,13 @@
#define PWR_STATUS_ETH BIT(15)
#define PWR_STATUS_HIF BIT(16)
#define PWR_STATUS_IFR_MSC BIT(17)
+#define PWR_STATUS_USB2 BIT(19) /* MT2712 */
#define PWR_STATUS_VENC_LT BIT(20)
#define PWR_STATUS_VENC BIT(21)
-#define PWR_STATUS_MFG_2D BIT(22)
-#define PWR_STATUS_MFG_ASYNC BIT(23)
-#define PWR_STATUS_AUDIO BIT(24)
-#define PWR_STATUS_USB BIT(25)
+#define PWR_STATUS_MFG_2D BIT(22) /* MT8173 */
+#define PWR_STATUS_MFG_ASYNC BIT(23) /* MT8173 */
+#define PWR_STATUS_AUDIO BIT(24) /* MT8173, MT2712 */
+#define PWR_STATUS_USB BIT(25) /* MT8173, MT2712 */
#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */
#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */
#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */
@@ -592,6 +594,85 @@ static void mtk_register_power_domains(struct platform_device *pdev,
};
/*
+ * MT2712 power domain support
+ */
+static const struct scp_domain_data scp_domain_data_mt2712[] = {
+ [MT2712_POWER_DOMAIN_MM] = {
+ .name = "mm",
+ .sta_mask = PWR_STATUS_DISP,
+ .ctl_offs = SPM_DIS_PWR_CON,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM},
+ .active_wakeup = true,
+ },
+ [MT2712_POWER_DOMAIN_VDEC] = {
+ .name = "vdec",
+ .sta_mask = PWR_STATUS_VDEC,
+ .ctl_offs = SPM_VDE_PWR_CON,
+ .sram_pdn_bits = GENMASK(8, 8),
+ .sram_pdn_ack_bits = GENMASK(12, 12),
+ .clk_id = {CLK_MM, CLK_VDEC},
+ .active_wakeup = true,
+ },
+ [MT2712_POWER_DOMAIN_VENC] = {
+ .name = "venc",
+ .sta_mask = PWR_STATUS_VENC,
+ .ctl_offs = SPM_VEN_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
+ .active_wakeup = true,
+ },
+ [MT2712_POWER_DOMAIN_ISP] = {
+ .name = "isp",
+ .sta_mask = PWR_STATUS_ISP,
+ .ctl_offs = SPM_ISP_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(13, 12),
+ .clk_id = {CLK_MM},
+ .active_wakeup = true,
+ },
+ [MT2712_POWER_DOMAIN_AUDIO] = {
+ .name = "audio",
+ .sta_mask = PWR_STATUS_AUDIO,
+ .ctl_offs = SPM_AUDIO_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(15, 12),
+ .clk_id = {CLK_AUDIO},
+ .active_wakeup = true,
+ },
+ [MT2712_POWER_DOMAIN_USB] = {
+ .name = "usb",
+ .sta_mask = PWR_STATUS_USB,
+ .ctl_offs = SPM_USB_PWR_CON,
+ .sram_pdn_bits = GENMASK(10, 8),
+ .sram_pdn_ack_bits = GENMASK(14, 12),
+ .clk_id = {CLK_NONE},
+ .active_wakeup = true,
+ },
+ [MT2712_POWER_DOMAIN_USB2] = {
+ .name = "usb2",
+ .sta_mask = PWR_STATUS_USB2,
+ .ctl_offs = SPM_USB2_PWR_CON,
+ .sram_pdn_bits = GENMASK(10, 8),
+ .sram_pdn_ack_bits = GENMASK(14, 12),
+ .clk_id = {CLK_NONE},
+ .active_wakeup = true,
+ },
+ [MT2712_POWER_DOMAIN_MFG] = {
+ .name = "mfg",
+ .sta_mask = PWR_STATUS_MFG,
+ .ctl_offs = SPM_MFG_PWR_CON,
+ .sram_pdn_bits = GENMASK(11, 8),
+ .sram_pdn_ack_bits = GENMASK(19, 16),
+ .clk_id = {CLK_MFG},
+ .bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
+ .active_wakeup = true,
+ },
+};
+
+/*
* MT6797 power domain support
*/
@@ -821,6 +902,16 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.bus_prot_reg_update = true,
};
+static const struct scp_soc_data mt2712_data = {
+ .domains = scp_domain_data_mt2712,
+ .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
+ .regs = {
+ .pwr_sta_offs = SPM_PWR_STATUS,
+ .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+ },
+ .bus_prot_reg_update = false,
+};
+
static const struct scp_soc_data mt6797_data = {
.domains = scp_domain_data_mt6797,
.num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
@@ -864,6 +955,9 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.compatible = "mediatek,mt2701-scpsys",
.data = &mt2701_data,
}, {
+ .compatible = "mediatek,mt2712-scpsys",
+ .data = &mt2712_data,
+ }, {
.compatible = "mediatek,mt6797-scpsys",
.data = &mt6797_data,
}, {
--
1.9.1
^ permalink raw reply related
* [PATCH v7 3/6] soc: mediatek: add dependent clock jpgdec/audio for scpsys
From: Weiyi Lu @ 2017-11-28 7:28 UTC (permalink / raw)
To: Matthias Brugger, Stephen Boyd, Mike Turquette, Rob Herring
Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu
In-Reply-To: <1511854102-23195-1-git-send-email-weiyi.lu@mediatek.com>
There are dependent clock jpgdec/audio in scpsys on MT2712,
and will exist three dependent clocks on MT2712 VDEC.
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
drivers/soc/mediatek/mtk-scpsys.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 4c484b1..c0f3219 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -84,6 +84,8 @@ enum clk_id {
CLK_ETHIF,
CLK_VDEC,
CLK_HIFSEL,
+ CLK_JPGDEC,
+ CLK_AUDIO,
CLK_MAX,
};
@@ -96,10 +98,12 @@ enum clk_id {
"ethif",
"vdec",
"hif_sel",
+ "jpgdec",
+ "audio",
NULL,
};
-#define MAX_CLKS 2
+#define MAX_CLKS 3
struct scp_domain_data {
const char *name;
--
1.9.1
^ permalink raw reply related
* [PATCH v7 2/6] soc: mediatek: extend bus protection API
From: Weiyi Lu @ 2017-11-28 7:28 UTC (permalink / raw)
To: Matthias Brugger, Stephen Boyd, Mike Turquette, Rob Herring
Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu
In-Reply-To: <1511854102-23195-1-git-send-email-weiyi.lu@mediatek.com>
MT2712 add "set/clear" bus control register to each control register set
instead of providing only one "enable" control register, we could avoid
the read-modify-write racing by declaring "bus_prot_reg_update" as "false"
in scp_soc_data or declaring as "true" to use the legacy update method.
By improving the mtk-infracfg bus protection implementation to
support set/clear bus protection control method by IC configuration.
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
drivers/soc/mediatek/mtk-infracfg.c | 26 ++++++++++++++++++++++----
drivers/soc/mediatek/mtk-scpsys.c | 28 ++++++++++++++++++++--------
include/linux/soc/mediatek/infracfg.h | 7 ++++---
3 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
index dba3055..8c310de 100644
--- a/drivers/soc/mediatek/mtk-infracfg.c
+++ b/drivers/soc/mediatek/mtk-infracfg.c
@@ -19,23 +19,33 @@
#define INFRA_TOPAXI_PROTECTEN 0x0220
#define INFRA_TOPAXI_PROTECTSTA1 0x0228
+#define INFRA_TOPAXI_PROTECTEN_SET 0x0260
+#define INFRA_TOPAXI_PROTECTEN_CLR 0x0264
/**
* mtk_infracfg_set_bus_protection - enable bus protection
* @regmap: The infracfg regmap
* @mask: The mask containing the protection bits to be enabled.
+ * @reg_update: The boolean flag determines to set the protection bits
+ * by regmap_update_bits with enable register(PROTECTEN) or
+ * by regmap_write with set register(PROTECTEN_SET).
*
* This function enables the bus protection bits for disabled power
* domains so that the system does not hang when some unit accesses the
* bus while in power down.
*/
-int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
+int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
+ bool reg_update)
{
unsigned long expired;
u32 val;
int ret;
- regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
+ if (reg_update)
+ regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask,
+ mask);
+ else
+ regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);
expired = jiffies + HZ;
@@ -59,16 +69,24 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
* mtk_infracfg_clear_bus_protection - disable bus protection
* @regmap: The infracfg regmap
* @mask: The mask containing the protection bits to be disabled.
+ * @reg_update: The boolean flag determines to clear the protection bits
+ * by regmap_update_bits with enable register(PROTECTEN) or
+ * by regmap_write with clear register(PROTECTEN_CLR).
*
* This function disables the bus protection bits previously enabled with
* mtk_infracfg_set_bus_protection.
*/
-int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
+
+int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
+ bool reg_update)
{
unsigned long expired;
int ret;
- regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
+ if (reg_update)
+ regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
+ else
+ regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask);
expired = jiffies + HZ;
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index e570b6a..4c484b1 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -134,6 +134,7 @@ struct scp {
void __iomem *base;
struct regmap *infracfg;
struct scp_ctrl_reg ctrl_reg;
+ bool bus_prot_reg_update;
};
struct scp_subdomain {
@@ -147,6 +148,7 @@ struct scp_soc_data {
const struct scp_subdomain *subdomains;
int num_subdomains;
const struct scp_ctrl_reg regs;
+ bool bus_prot_reg_update;
};
static int scpsys_domain_is_on(struct scp_domain *scpd)
@@ -254,7 +256,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
if (scpd->data->bus_prot_mask) {
ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
- scpd->data->bus_prot_mask);
+ scpd->data->bus_prot_mask,
+ scp->bus_prot_reg_update);
if (ret)
goto err_pwr_ack;
}
@@ -289,7 +292,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
if (scpd->data->bus_prot_mask) {
ret = mtk_infracfg_set_bus_protection(scp->infracfg,
- scpd->data->bus_prot_mask);
+ scpd->data->bus_prot_mask,
+ scp->bus_prot_reg_update);
if (ret)
goto out;
}
@@ -371,7 +375,8 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
static struct scp *init_scp(struct platform_device *pdev,
const struct scp_domain_data *scp_domain_data, int num,
- const struct scp_ctrl_reg *scp_ctrl_reg)
+ const struct scp_ctrl_reg *scp_ctrl_reg,
+ bool bus_prot_reg_update)
{
struct genpd_onecell_data *pd_data;
struct resource *res;
@@ -386,6 +391,8 @@ static struct scp *init_scp(struct platform_device *pdev,
scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
+ scp->bus_prot_reg_update = bus_prot_reg_update;
+
scp->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -806,7 +813,8 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
- }
+ },
+ .bus_prot_reg_update = true,
};
static const struct scp_soc_data mt6797_data = {
@@ -817,7 +825,8 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
- }
+ },
+ .bus_prot_reg_update = true,
};
static const struct scp_soc_data mt7622_data = {
@@ -826,7 +835,8 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
- }
+ },
+ .bus_prot_reg_update = true,
};
static const struct scp_soc_data mt8173_data = {
@@ -837,7 +847,8 @@ static void mtk_register_power_domains(struct platform_device *pdev,
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
- }
+ },
+ .bus_prot_reg_update = true,
};
/*
@@ -874,7 +885,8 @@ static int scpsys_probe(struct platform_device *pdev)
match = of_match_device(of_scpsys_match_tbl, &pdev->dev);
soc = (const struct scp_soc_data *)match->data;
- scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs);
+ scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
+ soc->bus_prot_reg_update);
if (IS_ERR(scp))
return PTR_ERR(scp);
diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
index e8d9f0d..b0a507d 100644
--- a/include/linux/soc/mediatek/infracfg.h
+++ b/include/linux/soc/mediatek/infracfg.h
@@ -28,7 +28,8 @@
#define MT7622_TOP_AXI_PROT_EN_WB (BIT(2) | BIT(6) | \
BIT(7) | BIT(8))
-int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
-int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
-
+int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
+ bool reg_update);
+int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
+ bool reg_update);
#endif /* __SOC_MEDIATEK_INFRACFG_H */
--
1.9.1
^ permalink raw reply related
* [PATCH v7 1/6] dt-bindings: soc: add MT2712 power dt-bindings
From: Weiyi Lu @ 2017-11-28 7:28 UTC (permalink / raw)
To: Matthias Brugger, Stephen Boyd, Mike Turquette, Rob Herring
Cc: James Liao, Weiyi Lu, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Fan Chen,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1511854102-23195-1-git-send-email-weiyi.lu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Add power dt-bindings for MT2712.
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Weiyi Lu <weiyi.lu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
.../devicetree/bindings/soc/mediatek/scpsys.txt | 3 +++
include/dt-bindings/power/mt2712-power.h | 26 ++++++++++++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 include/dt-bindings/power/mt2712-power.h
diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index 40056f7..76bf45b 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -12,11 +12,13 @@ power/power_domain.txt. It provides the power domains defined in
- include/dt-bindings/power/mt8173-power.h
- include/dt-bindings/power/mt6797-power.h
- include/dt-bindings/power/mt2701-power.h
+- include/dt-bindings/power/mt2712-power.h
- include/dt-bindings/power/mt7622-power.h
Required properties:
- compatible: Should be one of:
- "mediatek,mt2701-scpsys"
+ - "mediatek,mt2712-scpsys"
- "mediatek,mt6797-scpsys"
- "mediatek,mt7622-scpsys"
- "mediatek,mt8173-scpsys"
@@ -27,6 +29,7 @@ Required properties:
These are clocks which hardware needs to be
enabled before enabling certain power domains.
Required clocks for MT2701: "mm", "mfg", "ethif"
+ Required clocks for MT2712: "mm", "mfg", "venc", "jpgdec", "audio", "vdec"
Required clocks for MT6797: "mm", "mfg", "vdec"
Required clocks for MT7622: "hif_sel"
Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
diff --git a/include/dt-bindings/power/mt2712-power.h b/include/dt-bindings/power/mt2712-power.h
new file mode 100644
index 0000000..92b46d7
--- /dev/null
+++ b/include/dt-bindings/power/mt2712-power.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 MediaTek 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.
+ *
+ * This program 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 http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+
+#ifndef _DT_BINDINGS_POWER_MT2712_POWER_H
+#define _DT_BINDINGS_POWER_MT2712_POWER_H
+
+#define MT2712_POWER_DOMAIN_MM 0
+#define MT2712_POWER_DOMAIN_VDEC 1
+#define MT2712_POWER_DOMAIN_VENC 2
+#define MT2712_POWER_DOMAIN_ISP 3
+#define MT2712_POWER_DOMAIN_AUDIO 4
+#define MT2712_POWER_DOMAIN_USB 5
+#define MT2712_POWER_DOMAIN_USB2 6
+#define MT2712_POWER_DOMAIN_MFG 7
+
+#endif /* _DT_BINDINGS_POWER_MT2712_POWER_H */
--
1.9.1
^ permalink raw reply related
* [PATCH v7 0/6] Mediatek MT2712 clock and scpsys support
From: Weiyi Lu @ 2017-11-28 7:28 UTC (permalink / raw)
To: Matthias Brugger, Stephen Boyd, Mike Turquette, Rob Herring
Cc: James Liao, Weiyi Lu, srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Fan Chen,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1511854102-23195-1-git-send-email-weiyi.lu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
This series is based on v4.15-rc1 and composed of
scpsys control (PATCH 1-4) and device tree (PATCH 5-6)
changes since v6:
- Rebase to v4.15-rc1.
changes since v5:
- Refine bus protection with proper variable name
and better implementation for the if statement.
changes since v4:
- Refine scpsys and infracfg for bus protection by passing
a boolean flag to determine the register update method
changes since v3:
- Rebase to v4.14-rc1.
changes since v2:
- ensure the clocks used by clocksource driver are registered
before clocksource init() by using CLK_OF_DECLARE()
- correct the frequency of clk32k/clkrtc_ext/clkrtc_int
changes since v1:
- Rebase to v4.13-next-soc.
- Refine scpsys and infracfg for bus protection.
*** BLURB HERE ***
Weiyi Lu (6):
dt-bindings: soc: add MT2712 power dt-bindings
soc: mediatek: extend bus protection API
soc: mediatek: add dependent clock jpgdec/audio for scpsys
soc: mediatek: add MT2712 scpsys support
arm: dts: mt2712: Add clock controller device nodes
arm: dts: Add power controller device node of MT2712
.../devicetree/bindings/soc/mediatek/scpsys.txt | 3 +
arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 131 +++++++++++++++++++
drivers/soc/mediatek/mtk-infracfg.c | 26 +++-
drivers/soc/mediatek/mtk-scpsys.c | 140 ++++++++++++++++++---
include/dt-bindings/power/mt2712-power.h | 26 ++++
include/linux/soc/mediatek/infracfg.h | 7 +-
6 files changed, 311 insertions(+), 22 deletions(-)
create mode 100644 include/dt-bindings/power/mt2712-power.h
--
1.9.1
^ permalink raw reply
* [PATCH v7 0/6] Mediatek MT2712 clock and scpsys support
From: Weiyi Lu @ 2017-11-28 7:28 UTC (permalink / raw)
To: Matthias Brugger, Stephen Boyd, Mike Turquette, Rob Herring
Cc: James Liao, Fan Chen, devicetree, linux-arm-kernel, linux-kernel,
linux-mediatek, linux-clk, srv_heupstream, Weiyi Lu
This series is based on v4.15-rc1 and composed of
scpsys control (PATCH 1-4) and device tree (PATCH 5-6)
changes since v6:
- Rebase to v4.15-rc1.
changes since v5:
- Refine bus protection with proper variable name
and better implementation for the if statement.
changes since v4:
- Refine scpsys and infracfg for bus protection by passing
a boolean flag to determine the register update method
changes since v3:
- Rebase to v4.14-rc1.
changes since v2:
- ensure the clocks used by clocksource driver are registered
before clocksource init() by using CLK_OF_DECLARE()
- correct the frequency of clk32k/clkrtc_ext/clkrtc_int
changes since v1:
- Rebase to v4.13-next-soc.
- Refine scpsys and infracfg for bus protection.
^ permalink raw reply
* Re: [PATCH v7 06/13] slimbus: Add messaging APIs to slimbus framework
From: Srinivas Kandagatla @ 2017-11-28 7:18 UTC (permalink / raw)
To: Vinod Koul
Cc: mark.rutland, alsa-devel, michael.opdenacker, poeschel,
andreas.noever, arnd, treding, devicetree, james.hogan,
pawel.moll, linux-arm-msm, sharon.dvir1, robh+dt, sdharia, alan,
bp, mathieu.poirier, gregkh, linux-kernel, broonie, daniel,
jkosina, joe, davem
In-Reply-To: <20171127055606.GR3187@localhost>
On 27/11/17 05:56, Vinod Koul wrote:
> On Mon, Nov 20, 2017 at 06:47:52AM +0000, Srinivas Kandagatla wrote:
>
>>>> + * -ENOTCONN: If the transmitted message was not ACKed by destination
>>>> + * device.
>>>
>>> I am preferring ENODATA in SDW for this case, as Slaves didnt respond or
>>> ACK.
>> Isn't that a timeout error then.
>>
>> ENODATA is for "No data available", reporting ENODATA would be misleading.
>
> Do you get a explict NACK or no response for this
There is no response for the request, currently code waits for it arrive
and then timesout on completion.
^ permalink raw reply
* Re: [PATCH] irqchip/gic-v3: Support MSIs via aliases and distributor
From: Srinivas Kandagatla @ 2017-11-28 7:16 UTC (permalink / raw)
To: Stephen Boyd, Thomas Gleixner, Jason Cooper, Marc Zyngier
Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, devicetree
In-Reply-To: <20171127102408.6631-1-sboyd@codeaurora.org>
Hi Stephen,
Thanks for the patch.
On 27/11/17 10:24, Stephen Boyd wrote:
> Some GIC configurations don't have an accessible ITS, but they
> want to support MSIs through the distributor's SETSPI registers
> or through the IMPLEMENTATION DEFINED message-based interrupt
> request register region. This mode of operation is similar to the
> v2m support on gic-400, but we don't necessarily know what
> particular SPIs are supported as MSIs so we need some help from
> firmware to know what to do.
>
> Introduce an "arm,spi-ranges" property for this, similar to the
> "marvell,spi-ranges" property, that indicates the base and size
> of each MSI range. This property applies equally to the
> distributor and alias registers. In either case, we detect this
> mode of operation by looking for a node with the "msi-controller"
> property and then probe the v2m frame code on top of it. Assume
> these nodes will have the "arm,spi-ranges" property in them so
> that the v2m code works mostly unmodified.
>
> Cc: <devicetree@vger.kernel.org>
> Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Tested it on DB820c board.
Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
^ permalink raw reply
* Re: [PATCH v2 22/35] nds32: Device tree support
From: Greentime Hu @ 2017-11-28 6:54 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greentime, Linux Kernel Mailing List, linux-arch, Thomas Gleixner,
Jason Cooper, Marc Zyngier, Rob Herring, Networking, Vincent Chen,
DTML, Al Viro, David Howells, Will Deacon, Daniel Lezcano,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Vincent Chen
In-Reply-To: <CAK8P3a3nczwuuna8BGRQU11hhOFZMqGQqn9i_7D=Tzrc1PizFQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-11-27 22:30 GMT+08:00 Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>:
> On Mon, Nov 27, 2017 at 1:28 PM, Greentime Hu <green.hu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> @@ -0,0 +1,55 @@
>> +/dts-v1/;
>> +/ {
>> + compatible = "nds32 ae3xx";
>
> The compatible string doesn't seem to match the binding, it should always have
> vendor prefix.
Sorry I forgot to check this.
I will provide a document in bindings like
"Documentation/devicetree/bindings/nds32/andestech-boards".
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> + interrupt-parent = <&intc>;
>> +
>> + chosen {
>> + bootargs = "earlycon console=ttyS0,38400n8 debug loglevel=7";
>> + stdout-path = &serial0;
>> + };
>
> I would drop the bootargs here, this is something that should be set by the
> bootloader and is up to the user.
Thanks
I will drop it in the next version patch.
--
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
* Re: [PATCH v7 1/1] pwm: mediatek: add MT2712/MT7622 support
From: Sean Wang @ 2017-11-28 6:39 UTC (permalink / raw)
To: Zhi Mao
Cc: john-Pj+rj9U5foFAfugRpC6u6w, Thierry Reding,
claudiu.beznea-UWL1GkI3JZL3oGB3hsPCZA, Rob Herring, Mark Rutland,
Matthias Brugger, linux-pwm-u79uwXL29TY76Z2rM5mHXA,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w,
yt.shen-NuS5LvNUpcJWk0Htik3J/w,
zhenbao.liu-NuS5LvNUpcJWk0Htik3J/w
In-Reply-To: <1510576744.12324.23.camel@mhfsdcap03>
Hi, Zhi
The patch have already got merged in 4.15 rc1 as
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=424268c7494c2ae24c95565b9047bbf30309e88a
Sean
On Mon, 2017-11-13 at 20:39 +0800, Zhi Mao wrote:
> Hi Thierry,
>
> Just have a ping for this patch.
>
> Regards
> Zhi
>
>
> On Wed, 2017-10-25 at 18:11 +0800, Zhi Mao wrote:
> > Add support to MT2712 and MT7622.
> > Due to register offset address of pwm7 for MT2712 is not fixed 0x40,
> > add mtk_pwm_reg_offset array for pwm register offset.
> >
> > Reviewed-by: Claudiu Beznea <claudiu.beznea-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> > Reviewed-by: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > Signed-off-by: Zhi Mao <zhi.mao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > ---
> > changee in v7:
> > - adjust the commit message
> >
> > Changes in v6:
> > - remove "struct mtk_pwm_platform_data" member from "mtk_pwm_chip".
> >
> > Changes in v5:
> > - Add NULL pointer checking for "data"
> >
> > drivers/pwm/pwm-mediatek.c | 53 ++++++++++++++++++++++++++++++++++++--------
> > 1 file changed, 44 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
> > index 1d78ab1..cdd4d31 100644
> > --- a/drivers/pwm/pwm-mediatek.c
> > +++ b/drivers/pwm/pwm-mediatek.c
> > @@ -16,6 +16,7 @@
> > #include <linux/module.h>
> > #include <linux/clk.h>
> > #include <linux/of.h>
> > +#include <linux/of_device.h>
> > #include <linux/platform_device.h>
> > #include <linux/pwm.h>
> > #include <linux/slab.h>
> > @@ -40,11 +41,19 @@ enum {
> > MTK_CLK_PWM3,
> > MTK_CLK_PWM4,
> > MTK_CLK_PWM5,
> > + MTK_CLK_PWM6,
> > + MTK_CLK_PWM7,
> > + MTK_CLK_PWM8,
> > MTK_CLK_MAX,
> > };
> >
> > -static const char * const mtk_pwm_clk_name[] = {
> > - "main", "top", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5"
> > +static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = {
> > + "main", "top", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7",
> > + "pwm8"
> > +};
> > +
> > +struct mtk_pwm_platform_data {
> > + unsigned int num_pwms;
> > };
> >
> > /**
> > @@ -59,6 +68,10 @@ struct mtk_pwm_chip {
> > struct clk *clks[MTK_CLK_MAX];
> > };
> >
> > +static const unsigned int mtk_pwm_reg_offset[] = {
> > + 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220
> > +};
> > +
> > static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip)
> > {
> > return container_of(chip, struct mtk_pwm_chip, chip);
> > @@ -103,14 +116,14 @@ static void mtk_pwm_clk_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> > static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num,
> > unsigned int offset)
> > {
> > - return readl(chip->regs + 0x10 + (num * 0x40) + offset);
> > + return readl(chip->regs + mtk_pwm_reg_offset[num] + offset);
> > }
> >
> > static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip,
> > unsigned int num, unsigned int offset,
> > u32 value)
> > {
> > - writel(value, chip->regs + 0x10 + (num * 0x40) + offset);
> > + writel(value, chip->regs + mtk_pwm_reg_offset[num] + offset);
> > }
> >
> > static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> > @@ -185,6 +198,7 @@ static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> >
> > static int mtk_pwm_probe(struct platform_device *pdev)
> > {
> > + const struct mtk_pwm_platform_data *data;
> > struct mtk_pwm_chip *pc;
> > struct resource *res;
> > unsigned int i;
> > @@ -194,15 +208,22 @@ static int mtk_pwm_probe(struct platform_device *pdev)
> > if (!pc)
> > return -ENOMEM;
> >
> > + data = of_device_get_match_data(&pdev->dev);
> > + if (data == NULL)
> > + return -EINVAL;
> > +
> > res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > pc->regs = devm_ioremap_resource(&pdev->dev, res);
> > if (IS_ERR(pc->regs))
> > return PTR_ERR(pc->regs);
> >
> > - for (i = 0; i < MTK_CLK_MAX; i++) {
> > + for (i = 0; i < data->num_pwms + 2; i++) {
> > pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]);
> > - if (IS_ERR(pc->clks[i]))
> > + if (IS_ERR(pc->clks[i])) {
> > + dev_err(&pdev->dev, "clock: %s fail: %ld\n",
> > + mtk_pwm_clk_name[i], PTR_ERR(pc->clks[i]));
> > return PTR_ERR(pc->clks[i]);
> > + }
> > }
> >
> > platform_set_drvdata(pdev, pc);
> > @@ -210,7 +231,7 @@ static int mtk_pwm_probe(struct platform_device *pdev)
> > pc->chip.dev = &pdev->dev;
> > pc->chip.ops = &mtk_pwm_ops;
> > pc->chip.base = -1;
> > - pc->chip.npwm = 5;
> > + pc->chip.npwm = data->num_pwms;
> >
> > ret = pwmchip_add(&pc->chip);
> > if (ret < 0) {
> > @@ -228,9 +249,23 @@ static int mtk_pwm_remove(struct platform_device *pdev)
> > return pwmchip_remove(&pc->chip);
> > }
> >
> > +static const struct mtk_pwm_platform_data mt2712_pwm_data = {
> > + .num_pwms = 8,
> > +};
> > +
> > +static const struct mtk_pwm_platform_data mt7622_pwm_data = {
> > + .num_pwms = 6,
> > +};
> > +
> > +static const struct mtk_pwm_platform_data mt7623_pwm_data = {
> > + .num_pwms = 5,
> > +};
> > +
> > static const struct of_device_id mtk_pwm_of_match[] = {
> > - { .compatible = "mediatek,mt7623-pwm" },
> > - { }
> > + { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
> > + { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
> > + { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
> > + { },
> > };
> > MODULE_DEVICE_TABLE(of, mtk_pwm_of_match);
> >
>
>
--
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
* Re: [PATCH v7 1/2] dt-bindings: watchdog: Add Spreadtrum watchdog documentation
From: Eric Long @ 2017-11-28 6:13 UTC (permalink / raw)
To: Guenter Roeck, eric.long
Cc: Rob Herring, Mark Rutland, baolin.wang, linux-watchdog,
devicetree, linux-kernel, huitao.yue
In-Reply-To: <445d1641-de20-860c-5448-4b1533426441@roeck-us.net>
Hi Guenter,
Thanks again for you review.
I am very glad that this patch has been accepted.
Best Regards,
Eric Long
On Mon, Nov 27, 2017 at 08:09:18PM -0800, Guenter Roeck wrote:
> On 11/27/2017 06:18 PM, Eric Long wrote:
> >This patch adds the documentation for Spreadtrum watchdog driver.
> >
> >Signed-off-by: Eric Long <eric.long@spreadtrum.com>
> >Acked-by: Rob Herring <robh@kernel.org>
>
> The patch series is in my tree, and will ultimately find its way into Wim's tree.
> No need to resend it anymore.
>
> In general, if a patch is available in
> git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git watchdog-next
> there is no need to resend it.
>
> Thanks,
> Guenter
>
> >---
> >Changes since v6:
> >- No updates.
> >
> >Changes since v5:
> >- No updates.
> >
> >Changes since v4:
> >- No updates.
> >
> >Changes since v3:
> >- No updates.
> >
> >Changes since v2:
> >- Add acked tag from Rob.
> >
> >Changes since v1:
> >- No updates.
> >---
> > .../devicetree/bindings/watchdog/sprd-wdt.txt | 19 +++++++++++++++++++
> > 1 file changed, 19 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/watchdog/sprd-wdt.txt
> >
> >diff --git a/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt b/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt
> >new file mode 100644
> >index 0000000..aeaf3e0
> >--- /dev/null
> >+++ b/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt
> >@@ -0,0 +1,19 @@
> >+Spreadtrum SoCs Watchdog timer
> >+
> >+Required properties:
> >+- compatible : Should be "sprd,sp9860-wdt".
> >+- reg : Specifies base physical address and size of the registers.
> >+- interrupts : Exactly one interrupt specifier.
> >+- timeout-sec : Contain the default watchdog timeout in seconds.
> >+- clock-names : Contain the input clock names.
> >+- clocks : Phandles to input clocks.
> >+
> >+Example:
> >+ watchdog: watchdog@40310000 {
> >+ compatible = "sprd,sp9860-wdt";
> >+ reg = <0 0x40310000 0 0x1000>;
> >+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
> >+ timeout-sec = <12>;
> >+ clock-names = "enable", "rtc_enable";
> >+ clocks = <&clk_aon_apb_gates1 8>, <&clk_aon_apb_rtc_gates 9>;
> >+ };
> >
>
^ permalink raw reply
* Re: [PATCH v2 02/11] media: rkisp1: Add user space ABI definitions
From: Jacob Chen @ 2017-11-28 5:58 UTC (permalink / raw)
To: Hans Verkuil
Cc: open list:ARM/Rockchip SoC..., linux-kernel, linux-arm-kernel,
Mauro Carvalho Chehab, Linux Media Mailing List, Sakari Ailus,
Hans Verkuil, Tomasz Figa, Shunqian Zheng, Laurent Pinchart,
钟以崇, Eddie Cai, Jeffy Chen, Allon Huang,
devicetree, Heiko Stuebner, robh+dt
In-Reply-To: <7e1afc00-f9f4-3455-7a8a-5173d764be1a@xs4all.nl>
Hi Hans,
2017-11-27 18:26 GMT+08:00 Hans Verkuil <hverkuil@xs4all.nl>:
> On 11/24/2017 03:36 AM, Jacob Chen wrote:
>> From: Jeffy Chen <jeffy.chen@rock-chips.com>
>>
>> Add the header for userspace
>
> I gather that this effectively documents the metadata?
>
> I recommend using kernel-doc formatting here.
>
> One thing I immediately noticed is that these structures will have a
> different layout for 32 or 64 architectures. Which is a problem if you compile
> for 32 bit on a 64 bit kernel on the rk3399.
>
Thanks.....We didn't even notice that.
I will add "__attribute__ ((packed))" to each sturct.
> I think you need to be very careful how you define these structures.
>
> Are these parameters documented in a datasheet? If so, then add a reference
> to that datasheet. Is it publicly available or do you need an NDA to get it?
>
It can't be published, but i will try to add document for each parameters.
>>
>> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
>> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
>> ---
>> include/uapi/linux/rkisp1-config.h | 554 +++++++++++++++++++++++++++++++++++++
>> 1 file changed, 554 insertions(+)
>> create mode 100644 include/uapi/linux/rkisp1-config.h
>>
>> diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h
>> new file mode 100644
>> index 000000000000..a801fbc9ef47
>> --- /dev/null
>> +++ b/include/uapi/linux/rkisp1-config.h
>> @@ -0,0 +1,554 @@
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + *
>> + * This software is available to you under a choice of one of two
>> + * licenses. You may choose to be licensed under the terms of the GNU
>> + * General Public License (GPL) Version 2, available from the file
>> + * COPYING in the main directory of this source tree, or the
>> + * OpenIB.org BSD license below:
>> + *
>> + * Redistribution and use in source and binary forms, with or
>> + * without modification, are permitted provided that the following
>> + * conditions are met:
>> + *
>> + * - Redistributions of source code must retain the above
>> + * copyright notice, this list of conditions and the following
>> + * disclaimer.
>> + *
>> + * - Redistributions in binary form must reproduce the above
>> + * copyright notice, this list of conditions and the following
>> + * disclaimer in the documentation and/or other materials
>> + * provided with the distribution.
>> + *
>> + * 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.
>> + */
>> +
>> +#ifndef _UAPI_RKISP1_CONFIG_H
>> +#define _UAPI_RKISP1_CONFIG_H
>> +
>> +#include <linux/types.h>
>> +#include <linux/v4l2-controls.h>
>> +
>> +#define CIFISP_MODULE_DPCC (1 << 0)
>> +#define CIFISP_MODULE_BLS (1 << 1)
>> +#define CIFISP_MODULE_SDG (1 << 2)
>> +#define CIFISP_MODULE_HST (1 << 3)
>> +#define CIFISP_MODULE_LSC (1 << 4)
>> +#define CIFISP_MODULE_AWB_GAIN (1 << 5)
>> +#define CIFISP_MODULE_FLT (1 << 6)
>> +#define CIFISP_MODULE_BDM (1 << 7)
>> +#define CIFISP_MODULE_CTK (1 << 8)
>> +#define CIFISP_MODULE_GOC (1 << 9)
>> +#define CIFISP_MODULE_CPROC (1 << 10)
>> +#define CIFISP_MODULE_AFC (1 << 11)
>> +#define CIFISP_MODULE_AWB (1 << 12)
>> +#define CIFISP_MODULE_IE (1 << 13)
>> +#define CIFISP_MODULE_AEC (1 << 14)
>> +#define CIFISP_MODULE_WDR (1 << 15)
>> +#define CIFISP_MODULE_DPF (1 << 16)
>> +#define CIFISP_MODULE_DPF_STRENGTH (1 << 17)
>> +
>> +#define CIFISP_CTK_COEFF_MAX 0x100
>> +#define CIFISP_CTK_OFFSET_MAX 0x800
>> +
>> +#define CIFISP_AE_MEAN_MAX 25
>> +#define CIFISP_HIST_BIN_N_MAX 16
>> +#define CIFISP_AFM_MAX_WINDOWS 3
>> +#define CIFISP_DEGAMMA_CURVE_SIZE 17
>> +
>> +#define CIFISP_BDM_MAX_TH 0xFF
>> +
>> +/* maximum value for horizontal start address */
>> +#define CIFISP_BLS_START_H_MAX 0x00000FFF
>> +/* maximum value for horizontal stop address */
>> +#define CIFISP_BLS_STOP_H_MAX 0x00000FFF
>> +/* maximum value for vertical start address */
>> +#define CIFISP_BLS_START_V_MAX 0x00000FFF
>> +/* maximum value for vertical stop address */
>> +#define CIFISP_BLS_STOP_V_MAX 0x00000FFF
>> +/* maximum is 2^18 = 262144*/
>> +#define CIFISP_BLS_SAMPLES_MAX 0x00000012
>> +/* maximum value for fixed black level */
>> +#define CIFISP_BLS_FIX_SUB_MAX 0x00000FFF
>> +/* minimum value for fixed black level */
>> +#define CIFISP_BLS_FIX_SUB_MIN 0xFFFFF000
>> +/* 13 bit range (signed)*/
>> +#define CIFISP_BLS_FIX_MASK 0x00001FFF
>> +/* AWB */
>> +#define CIFISP_AWB_MAX_GRID 1
>> +#define CIFISP_AWB_MAX_FRAMES 7
>> +
>> +/* Gamma out*/
>> +/* Maximum number of color samples supported */
>> +#define CIFISP_GAMMA_OUT_MAX_SAMPLES 17
>> +
>> +/* LSC */
>> +#define CIFISP_LSC_GRAD_TBL_SIZE 8
>> +#define CIFISP_LSC_SIZE_TBL_SIZE 8
>> +/*
>> + * The following matches the tuning process,
>> + * not the max capabilities of the chip.
>> + * Last value unused.
>> + */
>> +#define CIFISP_LSC_DATA_TBL_SIZE 290
>> +/* HIST */
>> +/* Last 3 values unused. */
>> +#define CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 28
>> +
>> +/* DPCC */
>> +#define CIFISP_DPCC_METHODS_MAX 3
>> +
>> +/* DPF */
>> +#define CIFISP_DPF_MAX_NLF_COEFFS 17
>> +#define CIFISP_DPF_MAX_SPATIAL_COEFFS 6
>> +
>> +/* measurement types */
>> +#define CIFISP_STAT_AWB (1 << 0)
>> +#define CIFISP_STAT_AUTOEXP (1 << 1)
>> +#define CIFISP_STAT_AFM_FIN (1 << 2)
>> +#define CIFISP_STAT_HIST (1 << 3)
>> +
>> +enum cifisp_histogram_mode {
>> + CIFISP_HISTOGRAM_MODE_DISABLE,
>> + CIFISP_HISTOGRAM_MODE_RGB_COMBINED,
>> + CIFISP_HISTOGRAM_MODE_R_HISTOGRAM,
>> + CIFISP_HISTOGRAM_MODE_G_HISTOGRAM,
>> + CIFISP_HISTOGRAM_MODE_B_HISTOGRAM,
>> + CIFISP_HISTOGRAM_MODE_Y_HISTOGRAM
>> +};
>> +
>> +enum cifisp_exp_meas_mode {
>> +/* < Y = 16 + 0.25R + 0.5G + 0.1094B */
>> + CIFISP_EXP_MEASURING_MODE_0,
>> +/* < Y = (R + G + B) x (85/256) */
>> + CIFISP_EXP_MEASURING_MODE_1,
>> +};
>> +
>> +enum cifisp_exp_ctrl_auotostop {
>> + CIFISP_EXP_CTRL_AUTOSTOP_0 = 0,
>> + CIFISP_EXP_CTRL_AUTOSTOP_1 = 1,
>> +};
>> +
>> +struct cifisp_window {
>> + unsigned short h_offs;
>> + unsigned short v_offs;
>> + unsigned short h_size;
>> + unsigned short v_size;
>> +};
>> +
>> +enum cifisp_awb_mode_type {
>> + CIFISP_AWB_MODE_MANUAL,
>> + CIFISP_AWB_MODE_RGB,
>> + CIFISP_AWB_MODE_YCBCR
>> +};
>> +
>> +enum cifisp_flt_mode {
>> + CIFISP_FLT_STATIC_MODE,
>> + CIFISP_FLT_DYNAMIC_MODE
>> +};
>> +
>> +/*
>> + * BLS fixed subtraction values. The values will be subtracted from the sensor
>> + * values. Therefore a negative value means addition instead of subtraction!
>> + */
>> +struct cifisp_bls_fixed_val {
>> + /*! Fixed (signed!) subtraction value for Bayer pattern R. */
>
> What's the exact fixed point format used here?
>
>> + signed short r;
>> + /*! Fixed (signed!) subtraction value for Bayer pattern Gr. */
>> + signed short gr;
>> + /*! Fixed (signed!) subtraction value for Bayer pattern Gb. */
>> + signed short gb;
>> + /*! Fixed (signed!) subtraction value for Bayer pattern B. */
>> + signed short b;
>> +};
>> +
>> +/* Configuration used by black level subtraction */
>> +struct cifisp_bls_config {
>> + /*
>> + * Automatic mode activated means that the measured values
>> + * are subtracted.Otherwise the fixed subtraction
>> + * values will be subtracted.
>> + */
>> + bool enable_auto;
>> + unsigned char en_windows;
>> + struct cifisp_window bls_window1; /* < Measurement window 1. */
>> + struct cifisp_window bls_window2; /* !< Measurement window 2 */
>> + /*
>> + * Set amount of measured pixels for each Bayer position
>> + * (A, B,C and D) to 2^bls_samples.
>> + */
>> + unsigned char bls_samples;
>> + /* !< Fixed subtraction values. */
>> + struct cifisp_bls_fixed_val fixed_val;
>> +};
>> +
>> +struct cifisp_dpcc_methods_config {
>> + unsigned int method;
>> + unsigned int line_thresh;
>> + unsigned int line_mad_fac;
>> + unsigned int pg_fac;
>> + unsigned int rnd_thresh;
>> + unsigned int rg_fac;
>> +};
>> +
>> +struct cifisp_dpcc_config {
>> + unsigned int mode;
>> + unsigned int output_mode;
>> + unsigned int set_use;
>> + struct cifisp_dpcc_methods_config methods[CIFISP_DPCC_METHODS_MAX];
>> + unsigned int ro_limits;
>> + unsigned int rnd_offs;
>> +};
>> +
>> +struct cifisp_gamma_corr_curve {
>> + unsigned short gamma_y[CIFISP_DEGAMMA_CURVE_SIZE];
>> +};
>> +
>> +struct cifisp_gamma_curve_x_axis_pnts {
>> + unsigned int gamma_dx0;
>> + unsigned int gamma_dx1;
>> +};
>> +
>> +/* Configuration used by sensor degamma */
>> +struct cifisp_sdg_config {
>> + struct cifisp_gamma_corr_curve curve_r;
>> + struct cifisp_gamma_corr_curve curve_g;
>> + struct cifisp_gamma_corr_curve curve_b;
>> + struct cifisp_gamma_curve_x_axis_pnts xa_pnts;
>> +};
>> +
>> +/* Configuration used by Lens shading correction */
>> +struct cifisp_lsc_config {
>> + unsigned int r_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
>> + unsigned int gr_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
>> + unsigned int gb_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
>> + unsigned int b_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
>> +
>> + unsigned int x_grad_tbl[CIFISP_LSC_GRAD_TBL_SIZE];
>> + unsigned int y_grad_tbl[CIFISP_LSC_GRAD_TBL_SIZE];
>> +
>> + unsigned int x_size_tbl[CIFISP_LSC_SIZE_TBL_SIZE];
>> + unsigned int y_size_tbl[CIFISP_LSC_SIZE_TBL_SIZE];
>> + unsigned short config_width;
>> + unsigned short config_height;
>> +};
>> +
>> +struct cifisp_ie_config {
>> + enum v4l2_colorfx effect;
>> + unsigned short color_sel;
>> + /* 3x3 Matrix Coefficients for Emboss Effect 1 */
>> + unsigned short eff_mat_1;
>> + /* 3x3 Matrix Coefficients for Emboss Effect 2 */
>> + unsigned short eff_mat_2;
>> + /* 3x3 Matrix Coefficients for Emboss 3/Sketch 1 */
>> + unsigned short eff_mat_3;
>> + /* 3x3 Matrix Coefficients for Sketch Effect 2 */
>> + unsigned short eff_mat_4;
>> + /* 3x3 Matrix Coefficients for Sketch Effect 3 */
>> + unsigned short eff_mat_5;
>> + /* Chrominance increment values of tint (used for sepia effect) */
>> + unsigned short eff_tint;
>> +};
>> +
>> +struct cifisp_cproc_config {
>> + unsigned char c_out_range;
>> + unsigned char y_in_range;
>> + unsigned char y_out_range;
>> + unsigned char contrast;
>> + unsigned char brightness;
>> + unsigned char sat;
>> + unsigned char hue;
>> +};
>> +
>> +/* Configuration used by auto white balance */
>> +struct cifisp_awb_meas_config {
>> + /*
>> + * white balance measurement window (in pixels)
>> + * Note: currently the h and v offsets are mapped to grid offsets
>> + */
>> + struct cifisp_window awb_wnd;
>> + enum cifisp_awb_mode_type awb_mode;
>> + /*
>> + * only pixels values < max_y contribute to awb measurement
>> + * (set to 0 to disable this feature)
>> + */
>> + unsigned char max_y;
>> + /* only pixels values > min_y contribute to awb measurement */
>> + unsigned char min_y;
>> + /*
>> + * Chrominance sum maximum value, only consider pixels with Cb+Cr
>> + * smaller than threshold for awb measurements
>> + */
>> + unsigned char max_csum;
>> + /*
>> + * Chrominance minimum value, only consider pixels with Cb/Cr
>> + * each greater than threshold value for awb measurements
>> + */
>> + unsigned char min_c;
>> + /*
>> + * number of frames - 1 used for mean value calculation
>> + * (ucFrames=0 means 1 Frame)
>> + */
>> + unsigned char frames;
>> + /* reference Cr value for AWB regulation, target for AWB */
>> + unsigned char awb_ref_cr;
>> + /* reference Cb value for AWB regulation, target for AWB */
>> + unsigned char awb_ref_cb;
>> + bool enable_ymax_cmp;
>> +};
>> +
>> +struct cifisp_awb_gain_config {
>> + unsigned short gain_red;
>> + unsigned short gain_green_r;
>> + unsigned short gain_blue;
>> + unsigned short gain_green_b;
>> +};
>> +
>> +/* Configuration used by ISP filtering */
>> +struct cifisp_flt_config {
>> + enum cifisp_flt_mode mode; /* ISP_FILT_MODE register fields */
>> + unsigned char grn_stage1; /* ISP_FILT_MODE register fields */
>> + unsigned char chr_h_mode; /* ISP_FILT_MODE register fields */
>> + unsigned char chr_v_mode; /* ISP_FILT_MODE register fields */
>> + unsigned int thresh_bl0;
>> + unsigned int thresh_bl1;
>> + unsigned int thresh_sh0;
>> + unsigned int thresh_sh1;
>> + unsigned int lum_weight;
>> + unsigned int fac_sh1;
>> + unsigned int fac_sh0;
>> + unsigned int fac_mid;
>> + unsigned int fac_bl0;
>> + unsigned int fac_bl1;
>> +};
>> +
>> +/* Configuration used by Bayer DeMosaic */
>> +struct cifisp_bdm_config {
>> + unsigned char demosaic_th;
>> +};
>> +
>> +/* Configuration used by Cross Talk correction */
>> +struct cifisp_ctk_config {
>> + unsigned short coeff0;
>> + unsigned short coeff1;
>> + unsigned short coeff2;
>> + unsigned short coeff3;
>> + unsigned short coeff4;
>> + unsigned short coeff5;
>> + unsigned short coeff6;
>> + unsigned short coeff7;
>> + unsigned short coeff8;
>> + /* offset for the crosstalk correction matrix */
>> + unsigned short ct_offset_r;
>> + unsigned short ct_offset_g;
>> + unsigned short ct_offset_b;
>> +};
>> +
>> +enum cifisp_goc_mode {
>> + CIFISP_GOC_MODE_LOGARITHMIC,
>> + CIFISP_GOC_MODE_EQUIDISTANT
>> +};
>> +
>> +/* Configuration used by Gamma Out correction */
>> +struct cifisp_goc_config {
>> + enum cifisp_goc_mode mode;
>> + unsigned short gamma_y[CIFISP_GAMMA_OUT_MAX_SAMPLES];
>> +};
>> +
>> +/* Configuration used by Histogram */
>> +struct cifisp_hst_config {
>> + enum cifisp_histogram_mode mode;
>> + unsigned char histogram_predivider;
>> + struct cifisp_window meas_window;
>> + unsigned char hist_weight[CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE];
>> +};
>> +
>> +/* Configuration used by Auto Exposure Control */
>> +struct cifisp_aec_config {
>> + enum cifisp_exp_meas_mode mode;
>> + __u32 autostop;
>> + struct cifisp_window meas_window;
>> +};
>> +
>> +struct cifisp_afc_config {
>> + unsigned char num_afm_win; /* max CIFISP_AFM_MAX_WINDOWS */
>> + struct cifisp_window afm_win[CIFISP_AFM_MAX_WINDOWS];
>> + unsigned int thres;
>> + unsigned int var_shift;
>> +};
>> +
>> +enum cifisp_dpf_gain_usage {
>> +/* don't use any gains in preprocessing stage */
>> + CIFISP_DPF_GAIN_USAGE_DISABLED,
>> +/* use only the noise function gains from registers DPF_NF_GAIN_R, ... */
>> + CIFISP_DPF_GAIN_USAGE_NF_GAINS,
>> +/* use only the gains from LSC module */
>> + CIFISP_DPF_GAIN_USAGE_LSC_GAINS,
>> +/* use the moise function gains and the gains from LSC module */
>> + CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS,
>> +/* use only the gains from AWB module */
>> + CIFISP_DPF_GAIN_USAGE_AWB_GAINS,
>> +/* use the gains from AWB and LSC module */
>> + CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS,
>> +/* upper border (only for an internal evaluation) */
>> + CIFISP_DPF_GAIN_USAGE_MAX
>> +};
>> +
>> +enum cifisp_dpf_rb_filtersize {
>> +/* red and blue filter kernel size 13x9 (means 7x5 active pixel) */
>> + CIFISP_DPF_RB_FILTERSIZE_13x9,
>> +/* red and blue filter kernel size 9x9 (means 5x5 active pixel) */
>> + CIFISP_DPF_RB_FILTERSIZE_9x9,
>> +};
>> +
>> +enum cifisp_dpf_nll_scale_mode {
>> +/* use a linear scaling */
>> + CIFISP_NLL_SCALE_LINEAR,
>> +/* use a logarithmic scaling */
>> + CIFISP_NLL_SCALE_LOGARITHMIC,
>> +};
>> +
>> +struct cifisp_dpf_nll {
>> + unsigned short coeff[CIFISP_DPF_MAX_NLF_COEFFS];
>> + enum cifisp_dpf_nll_scale_mode scale_mode;
>> +};
>> +
>> +struct cifisp_dpf_rb_flt {
>> + enum cifisp_dpf_rb_filtersize fltsize;
>> + unsigned char spatial_coeff[CIFISP_DPF_MAX_SPATIAL_COEFFS];
>> + bool r_enable;
>> + bool b_enable;
>> +};
>> +
>> +struct cifisp_dpf_g_flt {
>> + unsigned char spatial_coeff[CIFISP_DPF_MAX_SPATIAL_COEFFS];
>> + bool gr_enable;
>> + bool gb_enable;
>> +};
>> +
>> +struct cifisp_dpf_gain {
>> + enum cifisp_dpf_gain_usage mode;
>> + unsigned short nf_r_gain;
>> + unsigned short nf_b_gain;
>> + unsigned short nf_gr_gain;
>> + unsigned short nf_gb_gain;
>> +};
>> +
>> +struct cifisp_dpf_config {
>> + struct cifisp_dpf_gain gain;
>> + struct cifisp_dpf_g_flt g_flt;
>> + struct cifisp_dpf_rb_flt rb_flt;
>> + struct cifisp_dpf_nll nll;
>> +};
>> +
>> +struct cifisp_dpf_strength_config {
>> + unsigned char r;
>> + unsigned char g;
>> + unsigned char b;
>> +};
>> +
>> +struct cifisp_isp_other_cfg {
>> + struct cifisp_dpcc_config dpcc_config;
>> + struct cifisp_bls_config bls_config;
>> + struct cifisp_sdg_config sdg_config;
>> + struct cifisp_lsc_config lsc_config;
>> + struct cifisp_awb_gain_config awb_gain_config;
>> + struct cifisp_flt_config flt_config;
>> + struct cifisp_bdm_config bdm_config;
>> + struct cifisp_ctk_config ctk_config;
>> + struct cifisp_goc_config goc_config;
>> + struct cifisp_dpf_config dpf_config;
>> + struct cifisp_dpf_strength_config dpf_strength_config;
>> + /* post process configs, including hue, sharpness, brightness, contrast, color effect */
>> + /* TODO: removed from here ? set by standard v4l2 controls ? */
>> + struct cifisp_cproc_config cproc_config;
>> + struct cifisp_ie_config ie_config;
>> +};
>> +
>> +struct cifisp_isp_meas_cfg {
>> + struct cifisp_awb_meas_config awb_meas_config;
>> + struct cifisp_hst_config hst_config;
>> + struct cifisp_aec_config aec_config;
>> + struct cifisp_afc_config afc_config;
>> +};
>> +
>> +struct rkisp1_isp_params_cfg {
>> + /* mask the enable bits of which module should be updated */
>> + unsigned int module_en_update;
>> + /* mask the enable value of each module, only update the module which correspond
>> + * bit was set in module_en_update
>> + */
>> + unsigned int module_ens;
>> + /* mask the config bits of which module should be updated */
>> + unsigned int module_cfg_update;
>> +
>> + struct cifisp_isp_meas_cfg meas;
>> + struct cifisp_isp_other_cfg others;
>> +};
>> +
>> +/* measurement statistics */
>> +
>> +struct cifisp_awb_meas {
>> + unsigned int cnt;
>> + unsigned char mean_y_or_g;
>> + unsigned char mean_cb_or_b;
>> + unsigned char mean_cr_or_r;
>> +};
>> +
>> +struct cifisp_awb_stat {
>> + struct cifisp_awb_meas awb_mean[CIFISP_AWB_MAX_GRID];
>> +};
>> +
>> +struct cifisp_hist_stat {
>> + unsigned short hist_bins[CIFISP_HIST_BIN_N_MAX];
>> +};
>> +
>> +/*! BLS mean measured values */
>> +struct cifisp_bls_meas_val {
>> + /*! Mean measured value for Bayer pattern R. */
>> + unsigned short meas_r;
>> + /*! Mean measured value for Bayer pattern Gr. */
>> + unsigned short meas_gr;
>> + /*! Mean measured value for Bayer pattern Gb. */
>> + unsigned short meas_gb;
>> + /*! Mean measured value for Bayer pattern B. */
>> + unsigned short meas_b;
>> +};
>> +
>> +struct cifisp_ae_stat {
>> + unsigned char exp_mean[CIFISP_AE_MEAN_MAX];
>> + struct cifisp_bls_meas_val bls_val; /* available wit exposure results */
>> +};
>> +
>> +struct cifisp_af_meas_val {
>> + unsigned int sum;
>> + unsigned int lum;
>> +};
>> +
>> +struct cifisp_af_stat {
>> + struct cifisp_af_meas_val window[CIFISP_AFM_MAX_WINDOWS];
>> +};
>> +
>> +struct cifisp_stat {
>> + struct cifisp_awb_stat awb;
>> + struct cifisp_ae_stat ae;
>> + struct cifisp_af_stat af;
>> + struct cifisp_hist_stat hist;
>> +};
>> +
>> +struct rkisp1_stat_buffer {
>> + unsigned int meas_type;
>> + unsigned int frame_id;
>> + struct cifisp_stat params;
>> +};
>> +
>> +#endif /* _UAPI_RKISP1_CONFIG_H */
>>
>
> You do need to document more of this. If the datasheet is publicly available
> you can get away with referring to the relevant sections of that datasheet.
>
> Regards,
>
> Hans
^ permalink raw reply
* [PATCH v5 2/2] media: i2c: Add the ov7740 image sensor driver
From: Wenyou Yang @ 2017-11-28 5:22 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Rob Herring, Mark Rutland
Cc: linux-kernel, Nicolas Ferre, devicetree, Sakari Ailus,
Jonathan Corbet, Hans Verkuil, linux-arm-kernel,
Linux Media Mailing List, Wenyou Yang, Songjun Wu
In-Reply-To: <20171128052259.4957-1-wenyou.yang@microchip.com>
The ov7740 (color) image sensor is a high performance VGA CMOS
image snesor, which supports for output formats: RAW RGB and YUV
and image sizes: VGA, and QVGA, CIF and any size smaller.
Signed-off-by: Songjun Wu <songjun.wu@microchip.com>
Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
---
Changes in v5:
- Squash the driver and MAINTAINERS entry patches to one.
- Precede the driver patch with the bindings patch.
Changes in v4:
- Assign 'val' a initial value to avoid warning: 'val' may be
used uninitialized.
- Rename REG_REG15 to avoid warning: "REG_REG15" redefined.
Changes in v3:
- Put the MAINTAINERS change to a separate patch.
Changes in v2:
- Split off the bindings into a separate patch.
- Add a new entry to the MAINTAINERS file.
MAINTAINERS | 8 +
drivers/media/i2c/Kconfig | 8 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/ov7740.c | 1220 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1237 insertions(+)
create mode 100644 drivers/media/i2c/ov7740.c
diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52fd76..19086a073ae9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10053,6 +10053,14 @@ S: Maintained
F: drivers/media/i2c/ov7670.c
F: Documentation/devicetree/bindings/media/i2c/ov7670.txt
+OMNIVISION OV7740 SENSOR DRIVER
+M: Wenyou Yang <wenyou.yang@microchip.com>
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/i2c/ov7740.c
+F: Documentation/devicetree/bindings/media/i2c/ov7740.txt
+
ONENAND FLASH DRIVER
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-mtd@lists.infradead.org
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 3c6d6428f525..ac484bb82fae 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -665,6 +665,14 @@ config VIDEO_OV7670
OV7670 VGA camera. It currently only works with the M88ALP01
controller.
+config VIDEO_OV7740
+ tristate "OmniVision OV7740 sensor support"
+ depends on I2C && VIDEO_V4L2
+ depends on MEDIA_CAMERA_SUPPORT
+ ---help---
+ This is a Video4Linux2 sensor-level driver for the OmniVision
+ OV7740 VGA camera sensor.
+
config VIDEO_OV9650
tristate "OmniVision OV9650/OV9652 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 548a9efce966..9b19ec7fcaf4 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c
new file mode 100644
index 000000000000..b2ec015bf3f6
--- /dev/null
+++ b/drivers/media/i2c/ov7740.c
@@ -0,0 +1,1220 @@
+/*
+ * Copyright (c) 2017 Microchip Corporation.
+ *
+ * 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.
+ *
+ * This program 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.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-image-sizes.h>
+#include <media/v4l2-subdev.h>
+
+#define REG_OUTSIZE_LSB 0x34
+
+/* OV7740 register tables */
+#define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
+#define REG_BGAIN 0x01 /* blue gain */
+#define REG_RGAIN 0x02 /* red gain */
+#define REG_GGAIN 0x03 /* green gain */
+#define REG_REG04 0x04 /* analog setting, dont change*/
+#define REG_BAVG 0x05 /* b channel average */
+#define REG_GAVG 0x06 /* g channel average */
+#define REG_RAVG 0x07 /* r channel average */
+
+#define REG_REG0C 0x0C /* filp enable */
+#define REG0C_IMG_FLIP 0x80
+#define REG0C_IMG_MIRROR 0x40
+
+#define REG_REG0E 0x0E /* blc line */
+#define REG_HAEC 0x0F /* auto exposure cntrl */
+#define REG_AEC 0x10 /* auto exposure cntrl */
+
+#define REG_CLK 0x11 /* Clock control */
+#define REG_REG55 0x55 /* Clock PLL DIV/PreDiv */
+
+#define REG_REG12 0x12
+
+#define REG_REG13 0x13 /* auto/manual AGC, AEC, Write Balance*/
+#define REG13_AEC_EN 0x01
+#define REG13_AGC_EN 0x04
+
+#define REG_REG14 0x14
+#define REG_CTRL15 0x15
+#define REG15_GAIN_MSB 0x03
+
+#define REG_REG16 0x16
+
+#define REG_MIDH 0x1C /* manufacture id byte */
+#define REG_MIDL 0x1D /* manufacture id byre */
+#define REG_PIDH 0x0A /* Product ID MSB */
+#define REG_PIDL 0x0B /* Product ID LSB */
+
+#define REG_84 0x84 /* lots of stuff */
+#define REG_REG38 0x38 /* sub-addr */
+
+#define REG_AHSTART 0x17 /* Horiz start high bits */
+#define REG_AHSIZE 0x18
+#define REG_AVSTART 0x19 /* Vert start high bits */
+#define REG_AVSIZE 0x1A
+#define REG_PSHFT 0x1b /* Pixel delay after HREF */
+
+#define REG_HOUTSIZE 0x31
+#define REG_VOUTSIZE 0x32
+#define REG_HVSIZEOFF 0x33
+#define REG_REG34 0x34 /* DSP output size H/V LSB*/
+
+#define REG_ISP_CTRL00 0x80
+#define ISPCTRL00_AWB_EN 0x10
+#define ISPCTRL00_AWB_GAIN_EN 0x04
+
+#define REG_YGAIN 0xE2 /* ygain for contrast control */
+
+#define REG_YBRIGHT 0xE3
+#define REG_SGNSET 0xE4
+#define SGNSET_YBRIGHT_MASK 0x08
+
+#define REG_USAT 0xDD
+#define REG_VSAT 0xDE
+
+
+struct ov7740 {
+ struct v4l2_subdev subdev;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ struct media_pad pad;
+#endif
+ struct v4l2_mbus_framefmt format;
+ struct ov7740_pixfmt *fmt; /* Current format */
+ struct ov7740_framesize *frmsize;
+ struct regmap *regmap;
+ struct clk *xvclk;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct {
+ /* gain cluster */
+ struct v4l2_ctrl *auto_gain;
+ struct v4l2_ctrl *gain;
+ };
+ struct {
+ struct v4l2_ctrl *auto_wb;
+ struct v4l2_ctrl *blue_balance;
+ struct v4l2_ctrl *red_balance;
+ };
+ struct {
+ struct v4l2_ctrl *hflip;
+ struct v4l2_ctrl *vflip;
+ };
+ struct {
+ /* exposure cluster */
+ struct v4l2_ctrl *auto_exposure;
+ struct v4l2_ctrl *exposure;
+ };
+ struct {
+ /* saturation/hue cluster */
+ struct v4l2_ctrl *saturation;
+ struct v4l2_ctrl *hue;
+ };
+ struct v4l2_ctrl *brightness;
+ struct v4l2_ctrl *contrast;
+
+ struct mutex mutex; /* To serialize asynchronus callbacks */
+ bool streaming; /* Streaming on/off */
+
+ struct gpio_desc *resetb_gpio;
+ struct gpio_desc *pwdn_gpio;
+};
+
+struct ov7740_pixfmt {
+ u32 mbus_code;
+ enum v4l2_colorspace colorspace;
+ const struct reg_sequence *regs;
+ u32 reg_num;
+};
+
+struct ov7740_framesize {
+ u16 width;
+ u16 height;
+ const struct reg_sequence *regs;
+ u32 reg_num;
+};
+
+static const struct reg_sequence ov7740_vga[] = {
+ {0x55, 0x40},
+ {0x11, 0x02},
+
+ {0xd5, 0x10},
+ {0x0c, 0x12},
+ {0x0d, 0x34},
+ {0x17, 0x25},
+ {0x18, 0xa0},
+ {0x19, 0x03},
+ {0x1a, 0xf0},
+ {0x1b, 0x89},
+ {0x22, 0x03},
+ {0x29, 0x18},
+ {0x2b, 0xf8},
+ {0x2c, 0x01},
+ {REG_HOUTSIZE, 0xa0},
+ {REG_VOUTSIZE, 0xf0},
+ {0x33, 0xc4},
+ {REG_OUTSIZE_LSB, 0x0},
+ {0x35, 0x05},
+ //{0x36, 0x3f},
+ {0x04, 0x60},
+ {0x27, 0x80},
+ {0x3d, 0x0f},
+ {0x3e, 0x80},
+ {0x3f, 0x40},
+ {0x40, 0x7f},
+ {0x41, 0x6a},
+ {0x42, 0x29},
+ {0x44, 0x22},
+ {0x45, 0x41},
+ {0x47, 0x02},
+ {0x49, 0x64},
+ {0x4a, 0xa1},
+ {0x4b, 0x40},
+ {0x4c, 0x1a},
+ {0x4d, 0x50},
+ {0x4e, 0x13},
+ {0x64, 0x00},
+ {0x67, 0x88},
+ {0x68, 0x1a},
+
+ {0x14, 0x28},
+ {0x24, 0x3c},
+ {0x25, 0x30},
+ {0x26, 0x72},
+ {0x50, 0x97},
+ {0x51, 0x1f},
+ {0x52, 0x00},
+ {0x53, 0x00},
+ {0x20, 0x00},
+ {0x21, 0xcf},
+ {0x50, 0x4b},
+ {0x38, 0x14},
+ {0xe9, 0x00},
+ {0x56, 0x55},
+ {0x57, 0xff},
+ {0x58, 0xff},
+ {0x59, 0xff},
+ {0x5f, 0x04},
+ {0xec, 0x00},
+ {0x13, 0xff},
+
+ //{0x80,0x7f},
+ {0x81, 0x3f},
+ {0x82, 0x32},
+ //{0x83, 0x01},
+ {0x38, 0x11},
+ {0x84, 0x70},
+ {0x85, 0x00},
+ {0x86, 0x03},
+ {0x87, 0x01},
+ {0x88, 0x05},
+ {0x89, 0x30},
+ {0x8d, 0x30},
+ {0x8f, 0x85},
+ {0x93, 0x30},
+ {0x95, 0x85},
+ {0x99, 0x30},
+ {0x9b, 0x85},
+
+ {0x9c, 0x08},
+ {0x9d, 0x12},
+ {0x9e, 0x23},
+ {0x9f, 0x45},
+ {0xa0, 0x55},
+ {0xa1, 0x64},
+ {0xa2, 0x72},
+ {0xa3, 0x7f},
+ {0xa4, 0x8b},
+ {0xa5, 0x95},
+ {0xa6, 0xa7},
+ {0xa7, 0xb5},
+ {0xa8, 0xcb},
+ {0xa9, 0xdd},
+ {0xaa, 0xec},
+ {0xab, 0x1a},
+
+ {0xce, 0x78},
+ {0xcf, 0x6e},
+ {0xd0, 0x0a},
+ {0xd1, 0x0c},
+ {0xd2, 0x84},
+ {0xd3, 0x90},
+ {0xd4, 0x1e},
+
+ {0x5a, 0x24},
+ {0x5b, 0x1f},
+ {0x5c, 0x88},
+ {0x5d, 0x60},
+
+ {0xac, 0x6e},
+ {0xbe, 0xff},
+ {0xbf, 0x00},
+
+ {0x0f, 0x1d},
+ {0x0f, 0x1f},
+};
+
+static struct ov7740_framesize ov7740_framesizes[] = {
+ {
+ .width = VGA_WIDTH,
+ .height = VGA_HEIGHT,
+ .regs = ov7740_vga,
+ .reg_num = ARRAY_SIZE(ov7740_vga),
+ },
+};
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov7740_get_register(struct v4l2_subdev *sd,
+ struct v4l2_dbg_register *reg)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+ struct regmap *regmap = ov7740->regmap;
+ unsigned int val = 0;
+ int ret;
+
+ ret = regmap_read(regmap, reg->reg & 0xff, &val);
+ reg->val = val;
+ reg->size = 1;
+
+ return 0;
+}
+
+static int ov7740_set_register(struct v4l2_subdev *sd,
+ const struct v4l2_dbg_register *reg)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+ struct regmap *regmap = ov7740->regmap;
+
+ regmap_write(regmap, reg->reg & 0xff, reg->val & 0xff);
+
+ return 0;
+}
+#endif
+
+static int ov7740_set_power(struct v4l2_subdev *sd, int on)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+
+ if (ov7740->pwdn_gpio)
+ gpiod_direction_output(ov7740->pwdn_gpio, !on);
+ if (on && ov7740->resetb_gpio) {
+ gpiod_set_value(ov7740->resetb_gpio, 1);
+ usleep_range(500, 1000);
+ gpiod_set_value(ov7740->resetb_gpio, 0);
+ usleep_range(3000, 5000);
+ }
+
+ return 0;
+}
+
+static struct v4l2_subdev_core_ops ov7740_subdev_core_ops = {
+ .log_status = v4l2_ctrl_subdev_log_status,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .g_register = ov7740_get_register,
+ .s_register = ov7740_set_register,
+#endif
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static int ov7740_set_white_balance(struct ov7740 *ov7740, int awb)
+{
+ struct regmap *regmap = ov7740->regmap;
+ unsigned int value;
+ int ret;
+
+ ret = regmap_read(regmap, REG_ISP_CTRL00, &value);
+ if (!ret) {
+ if (awb)
+ value |= (ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
+ else
+ value &= ~(ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
+ ret = regmap_write(regmap, REG_ISP_CTRL00, value);
+ if (ret)
+ return ret;
+ }
+
+ if (!awb) {
+ ret = regmap_write(regmap, REG_BGAIN,
+ ov7740->blue_balance->val);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(regmap, REG_RGAIN, ov7740->red_balance->val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ov7740_set_saturation(struct regmap *regmap, int value)
+{
+ int ret;
+
+ ret = regmap_write(regmap, REG_USAT, (unsigned char)value);
+ ret = regmap_write(regmap, REG_VSAT, (unsigned char)value);
+
+ return ret;
+}
+
+static int ov7740_set_gain(struct regmap *regmap, int value)
+{
+ int ret;
+
+ ret = regmap_write(regmap, REG_GAIN, value & 0xff);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(regmap, REG_CTRL15,
+ REG15_GAIN_MSB, (value >> 8) & 0x3);
+ if (!ret)
+ ret = regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
+
+ return ret;
+}
+
+static int ov7740_set_autogain(struct regmap *regmap, int value)
+{
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(regmap, REG_REG13, ®);
+ if (ret)
+ return ret;
+ if (value)
+ reg |= REG13_AGC_EN;
+ else
+ reg &= ~REG13_AGC_EN;
+ return regmap_write(regmap, REG_REG13, reg);
+}
+
+static int ov7740_set_brightness(struct regmap *regmap, int value)
+{
+ /* Turn off AEC/AGC */
+ regmap_update_bits(regmap, REG_REG13, REG13_AEC_EN, 0);
+ regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
+
+ if (value >= 0) {
+ regmap_write(regmap, REG_YBRIGHT, (unsigned char)value);
+ regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 0);
+ } else{
+ regmap_write(regmap, REG_YBRIGHT, (unsigned char)(-value));
+ regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 1);
+ }
+
+ return 0;
+}
+
+static int ov7740_set_contrast(struct regmap *regmap, int value)
+{
+ return regmap_write(regmap, REG_YGAIN, (unsigned char)value);
+}
+
+static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
+{
+ struct regmap *regmap = ov7740->regmap;
+ unsigned int value0, value1;
+ int ret;
+
+ if (!ctrl->val)
+ return 0;
+
+ ret = regmap_read(regmap, REG_GAIN, &value0);
+ if (ret)
+ return ret;
+ ret = regmap_read(regmap, REG_CTRL15, &value1);
+ if (ret)
+ return ret;
+
+ ov7740->gain->val = (value1 << 8) | (value0 & 0xff);
+
+ return 0;
+}
+
+static int ov7740_set_exp(struct regmap *regmap, int value)
+{
+ int ret;
+
+ /* Turn off AEC/AGC */
+ ret = regmap_update_bits(regmap, REG_REG13,
+ REG13_AEC_EN | REG13_AGC_EN, 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(regmap, REG_AEC, (unsigned char)value);
+ if (ret)
+ return ret;
+
+ return regmap_write(regmap, REG_HAEC, (unsigned char)(value >> 8));
+}
+
+static int ov7740_set_autoexp(struct regmap *regmap,
+ enum v4l2_exposure_auto_type value)
+{
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(regmap, REG_REG13, ®);
+ if (!ret) {
+ if (value == V4L2_EXPOSURE_AUTO)
+ reg |= (REG13_AEC_EN | REG13_AGC_EN);
+ else
+ reg &= ~(REG13_AEC_EN | REG13_AGC_EN);
+ ret = regmap_write(regmap, REG_REG13, reg);
+ }
+
+ return ret;
+}
+
+
+static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ov7740 *ov7740 = container_of(ctrl->handler,
+ struct ov7740, ctrl_handler);
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUTOGAIN:
+ ret = ov7740_get_gain(ov7740, ctrl);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ov7740 *ov7740 = container_of(ctrl->handler,
+ struct ov7740, ctrl_handler);
+ struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
+ struct regmap *regmap = ov7740->regmap;
+ int ret;
+ u8 val = 0;
+
+ if (pm_runtime_get_if_in_use(&client->dev) <= 0)
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ret = ov7740_set_white_balance(ov7740, ctrl->val);
+ break;
+ case V4L2_CID_SATURATION:
+ ret = ov7740_set_saturation(regmap, ctrl->val);
+ break;
+ case V4L2_CID_BRIGHTNESS:
+ ret = ov7740_set_brightness(regmap, ctrl->val);
+ break;
+ case V4L2_CID_CONTRAST:
+ ret = ov7740_set_contrast(regmap, ctrl->val);
+ break;
+ case V4L2_CID_VFLIP:
+ ret = regmap_update_bits(regmap, REG_REG0C,
+ REG0C_IMG_FLIP, val);
+ break;
+ case V4L2_CID_HFLIP:
+ val = ctrl->val ? REG0C_IMG_MIRROR : 0x00;
+ ret = regmap_update_bits(regmap, REG_REG0C,
+ REG0C_IMG_MIRROR, val);
+ break;
+ case V4L2_CID_AUTOGAIN:
+ if (!ctrl->val)
+ return ov7740_set_gain(regmap, ov7740->gain->val);
+
+ ret = ov7740_set_autogain(regmap, ctrl->val);
+ break;
+
+ case V4L2_CID_EXPOSURE_AUTO:
+ if (ctrl->val == V4L2_EXPOSURE_MANUAL)
+ return ov7740_set_exp(regmap, ov7740->exposure->val);
+
+ ret = ov7740_set_autoexp(regmap, ctrl->val);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops ov7740_ctrl_ops = {
+ .g_volatile_ctrl = ov7740_get_volatile_ctrl,
+ .s_ctrl = ov7740_set_ctrl,
+};
+
+static int ov7740_start_streaming(struct ov7740 *ov7740)
+{
+ int ret;
+
+ /* Apply customized values from user */
+ ret = __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+static int ov7740_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret = 0;
+
+ mutex_lock(&ov7740->mutex);
+ if (ov7740->streaming == enable) {
+ mutex_unlock(&ov7740->mutex);
+ return 0;
+ }
+
+ if (enable) {
+ ret = pm_runtime_get_sync(&client->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&client->dev);
+ goto err_unlock;
+ }
+
+ ret = ov7740_start_streaming(ov7740);
+ if (ret)
+ goto err_rpm_put;
+ } else {
+ pm_runtime_put(&client->dev);
+ }
+
+ ov7740->streaming = enable;
+
+ mutex_unlock(&ov7740->mutex);
+ return ret;
+
+err_rpm_put:
+ pm_runtime_put(&client->dev);
+err_unlock:
+ mutex_unlock(&ov7740->mutex);
+ return ret;
+}
+
+static int ov7740_get_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *parms)
+{
+ struct v4l2_captureparm *cp = &parms->parm.capture;
+ struct v4l2_fract *tpf = &cp->timeperframe;
+
+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ memset(cp, 0, sizeof(struct v4l2_captureparm));
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+
+ tpf->numerator = 1;
+ tpf->denominator = 60;
+
+ return 0;
+}
+
+static int ov7740_set_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *parms)
+{
+ struct v4l2_captureparm *cp = &parms->parm.capture;
+ struct v4l2_fract *tpf = &cp->timeperframe;
+
+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (cp->extendedmode != 0)
+ return -EINVAL;
+
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+
+ tpf->numerator = 1;
+ tpf->denominator = 60;
+
+ return 0;
+}
+
+static struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
+ .s_stream = ov7740_set_stream,
+ .s_parm = ov7740_set_parm,
+ .g_parm = ov7740_get_parm,
+};
+
+static const struct reg_sequence ov7740_format_yuyv[] = {
+ {0x12, 0x00},
+ {0x36, 0x3f},
+ {0x80, 0x7f},
+ {0x83, 0x01},
+};
+
+static const struct reg_sequence ov7740_format_bggr8[] = {
+ {0x36, 0x2f},
+ {0x80, 0x01},
+ {0x83, 0x04},
+};
+
+static struct ov7740_pixfmt ov7740_formats[] = {
+ {
+ .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .regs = ov7740_format_yuyv,
+ .reg_num = ARRAY_SIZE(ov7740_format_yuyv),
+ },
+ {
+ .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .regs = ov7740_format_bggr8,
+ .reg_num = ARRAY_SIZE(ov7740_format_bggr8),
+ }
+};
+#define N_OV7740_FMTS ARRAY_SIZE(ov7740_formats)
+
+static int ov7740_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad || code->index >= N_OV7740_FMTS)
+ return -EINVAL;
+
+ code->code = ov7740_formats[code->index].mbus_code;
+
+ return 0;
+}
+
+static int ov7740_enum_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ if (fie->pad)
+ return -EINVAL;
+
+ if (fie->index >= 1)
+ return -EINVAL;
+
+ if ((fie->width != VGA_WIDTH) || (fie->height != VGA_HEIGHT))
+ return -EINVAL;
+
+ fie->interval.numerator = 1;
+ fie->interval.denominator = 60;
+
+ return 0;
+}
+
+static int ov7740_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->pad)
+ return -EINVAL;
+
+ if (fse->index > 0)
+ return -EINVAL;
+
+ fse->min_width = fse->max_width = VGA_WIDTH;
+ fse->min_height = fse->max_height = VGA_HEIGHT;
+
+ return 0;
+}
+
+static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *fmt,
+ struct ov7740_pixfmt **ret_fmt,
+ struct ov7740_framesize **ret_frmsize)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+ struct ov7740_framesize *fsize = &ov7740_framesizes[0];
+ int index, i;
+
+ for (index = 0; index < N_OV7740_FMTS; index++) {
+ if (ov7740_formats[index].mbus_code == fmt->code)
+ break;
+ }
+ if (index >= N_OV7740_FMTS) {
+ /* default to first format */
+ index = 0;
+ fmt->code = ov7740_formats[0].mbus_code;
+ }
+ if (ret_fmt != NULL)
+ *ret_fmt = ov7740_formats + index;
+
+ for (i = 0; i < ARRAY_SIZE(ov7740_framesizes); i++) {
+ if ((fsize->width >= fmt->width) &&
+ (fsize->height >= fmt->height)) {
+ fmt->width = fsize->width;
+ fmt->height = fsize->height;
+ break;
+ }
+
+ fsize++;
+ }
+
+ if (ret_frmsize != NULL)
+ *ret_frmsize = fsize;
+
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = ov7740_formats[index].colorspace;
+
+ ov7740->format = *fmt;
+
+ return 0;
+}
+
+static int ov7740_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+ struct ov7740_pixfmt *ovfmt;
+ struct ov7740_framesize *fsize;
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ struct v4l2_mbus_framefmt *mbus_fmt;
+#endif
+ int ret;
+
+ mutex_lock(&ov7740->mutex);
+ if (format->pad) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL);
+ if (ret)
+ goto error;
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
+ *mbus_fmt = format->format;
+
+ mutex_unlock(&ov7740->mutex);
+ return 0;
+#else
+ ret = -ENOTTY;
+ goto error;
+#endif
+ }
+
+ ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize);
+ if (ret)
+ goto error;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ regmap_multi_reg_write(ov7740->regmap,
+ ovfmt->regs, ovfmt->reg_num);
+
+ regmap_multi_reg_write(ov7740->regmap,
+ fsize->regs, fsize->reg_num);
+ }
+
+ ov7740->fmt = ovfmt;
+
+ mutex_unlock(&ov7740->mutex);
+ return 0;
+
+error:
+ mutex_unlock(&ov7740->mutex);
+ return ret;
+}
+
+static int ov7740_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ struct v4l2_mbus_framefmt *mbus_fmt;
+#endif
+ int ret = 0;
+
+ mutex_lock(&ov7740->mutex);
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
+ format->format = *mbus_fmt;
+ ret = 0;
+#else
+ ret = -ENOTTY;
+#endif
+ } else {
+ format->format = ov7740->format;
+ }
+ mutex_unlock(&ov7740->mutex);
+
+ return ret;
+}
+
+static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
+ .enum_frame_interval = ov7740_enum_frame_interval,
+ .enum_frame_size = ov7740_enum_frame_size,
+ .enum_mbus_code = ov7740_enum_mbus_code,
+ .get_fmt = ov7740_get_fmt,
+ .set_fmt = ov7740_set_fmt,
+};
+
+static struct v4l2_subdev_ops ov7740_subdev_ops = {
+ .core = &ov7740_subdev_core_ops,
+ .video = &ov7740_subdev_video_ops,
+ .pad = &ov7740_subdev_pad_ops,
+};
+
+static void ov7740_get_default_format(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *format)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+
+ format->width = ov7740->frmsize->width;
+ format->height = ov7740->frmsize->height;
+ format->colorspace = ov7740->fmt->colorspace;
+ format->code = ov7740->fmt->mbus_code;
+ format->field = V4L2_FIELD_NONE;
+}
+
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+ struct v4l2_mbus_framefmt *format =
+ v4l2_subdev_get_try_format(sd, fh->pad, 0);
+
+ mutex_lock(&ov7740->mutex);
+ ov7740_get_default_format(sd, format);
+ mutex_unlock(&ov7740->mutex);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = {
+ .open = ov7740_open,
+};
+#endif
+
+static int ov7740_probe_dt(struct i2c_client *client,
+ struct ov7740 *ov7740)
+{
+ ov7740->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ov7740->resetb_gpio)) {
+ dev_info(&client->dev, "can't get %s GPIO\n", "reset");
+ return PTR_ERR(ov7740->resetb_gpio);
+ }
+
+ ov7740->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(ov7740->pwdn_gpio)) {
+ dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
+ return PTR_ERR(ov7740->pwdn_gpio);
+ }
+
+ return 0;
+}
+
+static int ov7740_detect(struct ov7740 *ov7740)
+{
+ struct regmap *regmap = ov7740->regmap;
+ unsigned int midh, midl, pidh, pidl;
+ int ret;
+
+ ret = regmap_read(regmap, REG_MIDH, &midh);
+ if (ret)
+ return ret;
+ if (midh != 0x7f)
+ return -ENODEV;
+
+ ret = regmap_read(regmap, REG_MIDL, &midl);
+ if (ret)
+ return ret;
+ if (midl != 0xa2)
+ return -ENODEV;
+
+ ret = regmap_read(regmap, REG_PIDH, &pidh);
+ if (ret)
+ return ret;
+ if (pidh != 0x77)
+ return -ENODEV;
+
+ ret = regmap_read(regmap, REG_PIDL, &pidl);
+ if (ret)
+ return ret;
+ if ((pidl != 0x40) && (pidl != 0x41) && (pidl != 0x42))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int ov7740_init_controls(struct ov7740 *ov7740)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
+ struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
+ int ret;
+
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 2);
+ if (ret < 0)
+ return ret;
+
+ ctrl_hdlr->lock = &ov7740->mutex;
+ ov7740->auto_wb = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_AUTO_WHITE_BALANCE,
+ 0, 1, 1, 1);
+ ov7740->blue_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_BLUE_BALANCE,
+ 0, 0xff, 1, 0x80);
+ ov7740->red_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_RED_BALANCE,
+ 0, 0xff, 1, 0x80);
+
+ ov7740->brightness = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_BRIGHTNESS,
+ -255, 255, 1, 0);
+ ov7740->contrast = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_CONTRAST,
+ 0, 127, 1, 0x20);
+ ov7740->saturation = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 256, 1, 0x80);
+ ov7740->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+ ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_GAIN, 0, 1023, 1, 500);
+ ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+ ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
+ V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
+ ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
+ &ov7740_ctrl_ops,
+ V4L2_CID_EXPOSURE_AUTO,
+ V4L2_EXPOSURE_MANUAL, 0,
+ V4L2_EXPOSURE_AUTO);
+
+ ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+ v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
+ v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
+ v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
+ V4L2_EXPOSURE_MANUAL, false);
+ v4l2_ctrl_cluster(2, &ov7740->hflip);
+
+ ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
+ if (ret) {
+ dev_err(&client->dev, "%s control init failed (%d)\n",
+ __func__, ret);
+ goto error;
+ }
+
+ ov7740->subdev.ctrl_handler = ctrl_hdlr;
+ return 0;
+
+error:
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+ mutex_destroy(&ov7740->mutex);
+ return ret;
+}
+
+static void ov7740_free_controls(struct ov7740 *ov7740)
+{
+ v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
+ mutex_destroy(&ov7740->mutex);
+}
+
+#define OV7740_MAX_REGISTER 0xff
+static const struct regmap_config ov7740_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = OV7740_MAX_REGISTER,
+};
+
+static int ov7740_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ov7740 *ov7740;
+ struct v4l2_subdev *sd;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&client->dev,
+ "OV7740: I2C-Adapter doesn't support SMBUS\n");
+ return -EIO;
+ }
+
+ ov7740 = devm_kzalloc(&client->dev, sizeof(*ov7740), GFP_KERNEL);
+ if (!ov7740)
+ return -ENOMEM;
+
+ ov7740->xvclk = devm_clk_get(&client->dev, "xvclk");
+ if (IS_ERR(ov7740->xvclk)) {
+ ret = PTR_ERR(ov7740->xvclk);
+ dev_err(&client->dev,
+ "OV7740: fail to get xvclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = ov7740_probe_dt(client, ov7740);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(ov7740->xvclk);
+ if (ret)
+ return ret;
+
+ ov7740->regmap = devm_regmap_init_i2c(client, &ov7740_regmap_config);
+ if (IS_ERR(ov7740->regmap)) {
+ ret = PTR_ERR(ov7740->regmap);
+ dev_err(&client->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto error_regmap_init;
+ }
+
+ sd = &ov7740->subdev;
+ client->flags |= I2C_CLIENT_SCCB;
+ v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops);
+
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ sd->internal_ops = &ov7740_subdev_internal_ops;
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+#endif
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ ov7740->pad.flags = MEDIA_PAD_FL_SOURCE;
+ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad);
+ if (ret)
+ goto error_regmap_init;
+#endif
+
+ ov7740_set_power(sd, 1);
+
+ ret = ov7740_detect(ov7740);
+ if (ret)
+ goto error_detect;
+
+ mutex_init(&ov7740->mutex);
+
+ ret = ov7740_init_controls(ov7740);
+ if (ret)
+ goto error_init_controls;
+
+ v4l_info(client, "chip found @ 0x%02x (%s)\n",
+ client->addr << 1, client->adapter->name);
+
+ ov7740->fmt = &ov7740_formats[0];
+ ov7740->frmsize = &ov7740_framesizes[0];
+
+ ov7740_get_default_format(sd, &ov7740->format);
+
+ ret = v4l2_async_register_subdev(sd);
+ if (ret)
+ goto error_async_register;
+
+ pm_runtime_get_noresume(&client->dev);
+ pm_runtime_set_active(&client->dev);
+ pm_runtime_enable(&client->dev);
+ pm_runtime_put(&client->dev);
+
+ return 0;
+
+error_async_register:
+ v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
+error_init_controls:
+ ov7740_free_controls(ov7740);
+ ov7740_set_power(sd, 0);
+error_detect:
+ media_entity_cleanup(&ov7740->subdev.entity);
+error_regmap_init:
+ clk_disable_unprepare(ov7740->xvclk);
+
+ return ret;
+}
+
+static int ov7740_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+
+ clk_disable_unprepare(ov7740->xvclk);
+ mutex_destroy(&ov7740->mutex);
+ v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ media_entity_cleanup(&ov7740->subdev.entity);
+#endif
+ v4l2_async_unregister_subdev(sd);
+ ov7740_free_controls(ov7740);
+
+ pm_runtime_get_sync(&client->dev);
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_put_noidle(&client->dev);
+
+ return 0;
+}
+
+static int __maybe_unused ov7740_runtime_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+
+ clk_disable_unprepare(ov7740->xvclk);
+ ov7740_set_power(sd, 0);
+
+ return 0;
+}
+
+static int __maybe_unused ov7740_runtime_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
+
+ ov7740_set_power(sd, 1);
+ return clk_prepare_enable(ov7740->xvclk);
+}
+
+static const struct i2c_device_id ov7740_id[] = {
+ { "ov7740", 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, ov7740_id);
+
+static const struct dev_pm_ops ov7740_pm_ops = {
+ SET_RUNTIME_PM_OPS(ov7740_runtime_suspend, ov7740_runtime_resume, NULL)
+};
+
+static const struct of_device_id ov7740_of_match[] = {
+ {.compatible = "ovti,ov7740", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ov7740_of_match);
+
+
+static struct i2c_driver ov7740_i2c_driver = {
+ .driver = {
+ .name = "ov7740",
+ .pm = &ov7740_pm_ops,
+ .of_match_table = of_match_ptr(ov7740_of_match),
+ },
+ .probe = ov7740_probe,
+ .remove = ov7740_remove,
+ .id_table = ov7740_id,
+};
+module_i2c_driver(ov7740_i2c_driver);
+
+MODULE_DESCRIPTION("The V4L2 driver for Omnivision 7740 sensor");
+MODULE_AUTHOR("Songjun Wu <songjun.wu@atmel.com>");
+MODULE_LICENSE("GPL v2");
--
2.15.0
^ permalink raw reply related
* [PATCH v5 1/2] media: ov7740: Document device tree bindings
From: Wenyou Yang @ 2017-11-28 5:22 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Rob Herring, Mark Rutland
Cc: linux-kernel, Nicolas Ferre, devicetree, Sakari Ailus,
Jonathan Corbet, Hans Verkuil, linux-arm-kernel,
Linux Media Mailing List, Wenyou Yang
In-Reply-To: <20171128052259.4957-1-wenyou.yang@microchip.com>
Add the device tree binding documentation for the ov7740 sensor driver.
Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
---
Changes in v5: None
Changes in v4: None
Changes in v3:
- Explicitly document the "remote-endpoint" property.
Changes in v2: None
.../devicetree/bindings/media/i2c/ov7740.txt | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt
diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt
new file mode 100644
index 000000000000..af781c3a5f0e
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt
@@ -0,0 +1,47 @@
+* Omnivision OV7740 CMOS image sensor
+
+The Omnivision OV7740 image sensor supports multiple output image
+size, such as VGA, and QVGA, CIF and any size smaller. It also
+supports the RAW RGB and YUV output formats.
+
+The common video interfaces bindings (see video-interfaces.txt) should
+be used to specify link to the image data receiver. The OV7740 device
+node should contain one 'port' child node with an 'endpoint' subnode.
+
+Required Properties:
+- compatible: "ovti,ov7740".
+- reg: I2C slave address of the sensor.
+- clocks: Reference to the xvclk input clock.
+- clock-names: "xvclk".
+
+Optional Properties:
+- reset-gpios: Rreference to the GPIO connected to the reset_b pin,
+ if any. Active low with pull-ip resistor.
+- powerdown-gpios: Reference to the GPIO connected to the pwdn pin,
+ if any. Active high with pull-down resistor.
+
+Endpoint node mandatory properties:
+- remote-endpoint: A phandle to the bus receiver's endpoint node.
+
+Example:
+
+ i2c1: i2c@fc028000 {
+ ov7740: camera@21 {
+ compatible = "ovti,ov7740";
+ reg = <0x21>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>;
+ clocks = <&isc>;
+ clock-names = "xvclk";
+ assigned-clocks = <&isc>;
+ assigned-clock-rates = <24000000>;
+ reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>;
+ powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>;
+
+ port {
+ ov7740_0: endpoint {
+ remote-endpoint = <&isc_0>;
+ };
+ };
+ };
+ };
--
2.15.0
^ permalink raw reply related
* [PATCH v5 0/2] media: ov7740: Add a V4L2 sensor-level driver
From: Wenyou Yang @ 2017-11-28 5:22 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Rob Herring, Mark Rutland
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Nicolas Ferre,
devicetree-u79uwXL29TY76Z2rM5mHXA, Sakari Ailus, Jonathan Corbet,
Hans Verkuil, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Linux Media Mailing List, Wenyou Yang
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740
VGA camera image sensor.
Changes in v5:
- Squash the driver and MAINTAINERS entry patches to one.
- Precede the driver patch with the bindings patch.
Changes in v4:
- Assign 'val' a initial value to avoid warning: 'val' may be
used uninitialized.
- Rename REG_REG15 to avoid warning: "REG_REG15" redefined.
Changes in v3:
- Explicitly document the "remote-endpoint" property.
- Put the MAINTAINERS change to a separate patch.
Changes in v2:
- Split off the bindings into a separate patch.
- Add a new entry to the MAINTAINERS file.
Wenyou Yang (2):
media: ov7740: Document device tree bindings
media: i2c: Add the ov7740 image sensor driver
.../devicetree/bindings/media/i2c/ov7740.txt | 47 +
MAINTAINERS | 8 +
drivers/media/i2c/Kconfig | 8 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/ov7740.c | 1220 ++++++++++++++++++++
5 files changed, 1284 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt
create mode 100644 drivers/media/i2c/ov7740.c
--
2.15.0
--
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
* Re: [PATCH 03/13] ARM: dts: imx6qdl: SolidRun: move microsom includes into .dts
From: Jon Nettleton @ 2017-11-28 4:46 UTC (permalink / raw)
To: Russell King
Cc: Shawn Guo, Sascha Hauer, Fabio Estevam, Rob Herring, Mark Rutland,
linux-arm-kernel, devicetree
In-Reply-To: <E1eJMdo-0002qf-2D@rmk-PC.armlinux.org.uk>
[-- Attachment #1: Type: text/plain, Size: 3305 bytes --]
On Mon, Nov 27, 2017 at 5:52 PM, Russell King <rmk+kernel@armlinux.org.uk>
wrote:
> Move the microsom includes into the .dts files so different options can
> be accomodated at the lowest level.
>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
> arch/arm/boot/dts/imx6dl-cubox-i.dts | 1 +
> arch/arm/boot/dts/imx6dl-hummingboard.dts | 1 +
> arch/arm/boot/dts/imx6q-cubox-i.dts | 1 +
> arch/arm/boot/dts/imx6q-hummingboard.dts | 1 +
> arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 1 -
> arch/arm/boot/dts/imx6qdl-hummingboard.dtsi | 1 -
> 6 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx6dl-cubox-i.dts
> b/arch/arm/boot/dts/imx6dl-cubox-i.dts
> index f10a36b8647d..222c269f687a 100644
> --- a/arch/arm/boot/dts/imx6dl-cubox-i.dts
> +++ b/arch/arm/boot/dts/imx6dl-cubox-i.dts
> @@ -41,6 +41,7 @@
> /dts-v1/;
>
> #include "imx6dl.dtsi"
> +#include "imx6qdl-microsom.dtsi"
> #include "imx6qdl-cubox-i.dtsi"
>
> / {
> diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts
> b/arch/arm/boot/dts/imx6dl-hummingboard.dts
> index 39c2602fa87c..1709810de77e 100644
> --- a/arch/arm/boot/dts/imx6dl-hummingboard.dts
> +++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts
> @@ -42,6 +42,7 @@
> /dts-v1/;
>
> #include "imx6dl.dtsi"
> +#include "imx6qdl-microsom.dtsi"
> #include "imx6qdl-hummingboard.dtsi"
>
> / {
> diff --git a/arch/arm/boot/dts/imx6q-cubox-i.dts
> b/arch/arm/boot/dts/imx6q-cubox-i.dts
> index b68aa0e57f20..8f39682c33a9 100644
> --- a/arch/arm/boot/dts/imx6q-cubox-i.dts
> +++ b/arch/arm/boot/dts/imx6q-cubox-i.dts
> @@ -41,6 +41,7 @@
> /dts-v1/;
>
> #include "imx6q.dtsi"
> +#include "imx6qdl-microsom.dtsi"
> #include "imx6qdl-cubox-i.dtsi"
>
> / {
> diff --git a/arch/arm/boot/dts/imx6q-hummingboard.dts
> b/arch/arm/boot/dts/imx6q-hummingboard.dts
> index 69a7a0a1cb21..6fc692940e6b 100644
> --- a/arch/arm/boot/dts/imx6q-hummingboard.dts
> +++ b/arch/arm/boot/dts/imx6q-hummingboard.dts
> @@ -42,6 +42,7 @@
> /dts-v1/;
>
> #include "imx6q.dtsi"
> +#include "imx6qdl-microsom.dtsi"
> #include "imx6qdl-hummingboard.dtsi"
>
> / {
> diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
> b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
> index 57ce2dbb6ad9..98ec7ce1f2a3 100644
> --- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
> @@ -38,7 +38,6 @@
> * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> * OTHER DEALINGS IN THE SOFTWARE.
> */
> -#include "imx6qdl-microsom.dtsi"
> #include <dt-bindings/input/input.h>
> #include <dt-bindings/gpio/gpio.h>
>
> diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
> b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
> index afd981e9b5e3..84e6392fee1f 100644
> --- a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
> @@ -38,7 +38,6 @@
> * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> * OTHER DEALINGS IN THE SOFTWARE.
> */
> -#include "imx6qdl-microsom.dtsi"
>
> / {
> chosen {
>
Since we are going through and adding the som dtsi include to all the
device-tree files, would it make sense to rename the microsom.dtsi at this
point in time? Perhaps something like imx6qdl-sr-microsom.dtsi?
-Jon
[-- Attachment #2: Type: text/html, Size: 4378 bytes --]
^ permalink raw reply
* Re: [PATCH v2 10/35] nds32: Atomic operations
From: Vincent Chen @ 2017-11-28 4:24 UTC (permalink / raw)
To: Mark Rutland
Cc: Greentime Hu, Greentime, Linux Kernel Mailing List, Arnd Bergmann,
linux-arch, Thomas Gleixner, Jason Cooper, Marc Zyngier,
Rob Herring, Networking, DTML, Al Viro, David Howells,
Will Deacon, Daniel Lezcano, linux-serial, Vincent Chen
In-Reply-To: <20171127135724.yy2jjjuby3xu74mm@lakrids.cambridge.arm.com>
2017-11-27 21:57 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> Hi,
>
> On Mon, Nov 27, 2017 at 08:27:57PM +0800, Greentime Hu wrote:
>> +static inline void arch_spin_unlock(arch_spinlock_t * lock)
>> +{
>> + asm volatile(
>> + "xor $r15, $r15, $r15\n"
>> + "swi $r15, [%0]\n"
>> + :
>> + :"r"(&lock->lock)
>> + :"memory");
>> +}
>
> This looks suspicious. There's no clobber for $r15, so isn't this
> corrupting a GPR behind the back of the compiler?
>
Thanks.
$r15 is reserved for assembler.
For safety, compiler always put $r15 in clobber register list by default.
> Shouldn't there be a tmp variable for the register allocation rather
> than hard-coding $r15?
>
>> +static inline void arch_write_unlock(arch_rwlock_t * rw)
>> +{
>> + asm volatile(
>> + "xor $r15, $r15, $r15\n"
>> + "swi $r15, [%0]\n"
>> + :
>> + :"r"(&rw->lock)
>> + :"memory","$r15");
>> +}
>
> This time you have a clobber, but it's still not clear to me why you
> don't use a tmp variable and leave the register allocation to the
> compiler.
>
Thanks.
When I recheck the code, I found spinlock.h is not needed due that we
do not support SMP.
So, We decide to remove spinlock.h in the next version patch.
Vincent
> Thanks,
> Mark.
^ permalink raw reply
* Re: [PATCH V4 00/12] drivers: Boot Constraints core
From: Viresh Kumar @ 2017-11-28 4:18 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Vincent Guittot, Stephen Boyd, Rajendra Nayak,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robdclark-Re5JQEeQqe8AvxtiuMwx3w, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
l.stach-bIcnvbaLZ9MEGnE8C9+IrQ, shawnguo-DgEjT+Ai2ygdnm+yROfE0A,
fabio.estevam-3arQi8VN3Tc, nm-l0cyMroinI0,
xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-u79uwXL29TY76Z2rM5mHXA, Frank Rowand
In-Reply-To: <cover.1509284255.git.viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 29-10-17, 19:18, Viresh Kumar wrote:
> Here is V4 of the boot constraints core based on your feedback from V3.
> We now have support for three platforms (as you suggested) included in
> this series: Hisilicon, IMX and Qualcomm.
Hi Greg,
I was waiting for rc1 to come out before sending a reminder for this
series and so here is one :)
--
viresh
--
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] ARM: dts: sun8i: h3: Add dts file for Libre Computer Board ALL-H3-CC H3 ver.
From: Chen-Yu Tsai @ 2017-11-28 4:12 UTC (permalink / raw)
To: Maxime Ripard
Cc: Chen-Yu Tsai, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Corentin Labbe
The Libre Computer Board ALL-H3-CC from Libre Technology is a Raspberry
Pi B+ form factor single board computer based on the Allwinner H3 SoC.
The board has 1GB DDR3 SDRAM, provided by 4 2Gb chips. The mounting holes
and connectors are in the exact same position as on the Raspberry Pi B+.
Raspberry Pi B+ like peripherals supported on this board include:
- Power input through micro-USB connector (without USB OTG)
- Native 100 Mbps ethernet using the internal PHY, as opposed to
USB-based on the RPi
- 4x USB 2.0 host ports, directly connected to the SoC, as opposed to
being connected through a USB 2.0 hub on the RPi
- TV and audio output on a 3.5mm TRRS jack
- HDMI output
- Micro-SD card slot
- Standard RPi B+ GPIO header, with the standard peripherals routed to
the same pins.
* 5V, 3.3V power, and ground
* I2C0 on the H3 is routed to I2C1 pins on the RPi header
* I2C1 on the H3 is routed to I2C0 pins on the RPi header
* UART1 on the H3 is routed to UART0 pins on the RPi header
* SPI0 on the H3 is routed to SPI0 pins on the RPi header,
with GPIO pin PA17 replacing the missing Chip Select 1
* I2S1 on the H3 is routed to PCM pins on the RPi header
- Additional peripherals from the H3 are available on different pins.
These include I2S0, JTAG, PWM1, SPDIF, SPI1, and UART3
In addition, there are a number of new features:
- Console UART header
- Consumer IR receiver
- Camera interface (not compatible with RPi)
- Onboard microphone
- eMMC expansion module port
- Heatsink mounting holes
This patch adds a dts file for this board that enables all "onboard"
peripherals currently supported. This means no display or camera
support.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
There are two other variants [1] of this board, with different SoCs and
DRAM configuration. But the board remains the same, thanks to the SoCs
being pin compatible.
Do we need different board compatible strings? FWIW the soc compatible
string already encodes the soc variant, and the DRAM stuff is handled
by the bootloader. The filename also has the SoC family and chip name.
The displayed board model also has the SoC variant included. The board
itself is named "ALL-H3-CC".
I'm asking as we have the same issue with the Bananapi M2+ [2], where
they've released new variants with different SoCs and DRAM capacities
using the same board. Not sure if they are commercially available though.
Last, the LED polarity is wrong. This is due to the EMAC driver not
following the DT binding and looking for the "allwinner,leds-active-low"
under the PHY node, instead of the EMAC node. I've notified Corentin of
this issue.
[1] https://www.kickstarter.com/projects/librecomputer/libre-computer-board-tritium-sbc-linux-android-7-n
[2] http://www.banana-pi.org/m2plus.html
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts | 196 +++++++++++++++++++++
2 files changed, 197 insertions(+)
create mode 100644 arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 3c139c63098f..aa68f719692f 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -953,6 +953,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-h2-plus-orangepi-zero.dtb \
sun8i-h3-bananapi-m2-plus.dtb \
sun8i-h3-beelink-x2.dtb \
+ sun8i-h3-libretech-all-h3-cc.dtb \
sun8i-h3-nanopi-m1.dtb \
sun8i-h3-nanopi-m1-plus.dtb \
sun8i-h3-nanopi-neo.dtb \
diff --git a/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts b/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts
new file mode 100644
index 000000000000..6f544e007f71
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2017 Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Libre Computer Board ALL-H3-CC H3";
+ compatible = "libretech,all-h3-cc", "allwinner,sun8i-h3";
+
+ aliases {
+ ethernet0 = &emac;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pwr_led {
+ label = "librecomputer:pwr";
+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+ default-state = "on";
+ };
+
+ status_led {
+ label = "librecomputer:status";
+ gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA7 */
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ recovery {
+ label = "recovery";
+ linux,code = <BTN_0>;
+ gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+ };
+ };
+
+ reg_vcc1v2: vcc1v2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc1v2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <®_vcc5v0>;
+ gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+ enable-active-high;
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <®_vcc5v0>;
+ };
+
+ /* This represents the board's 5V input */
+ reg_vcc5v0: vcc5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_vcc_dram: vcc-dram {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-dram";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <®_vcc5v0>;
+ gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */
+ enable-active-high;
+ };
+
+ reg_vcc_io: vcc-io {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-io";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <®_vcc3v3>;
+ gpio = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */
+ };
+
+ reg_vdd_cpux: vdd-cpux {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpux";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <®_vcc5v0>;
+ gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+ enable-active-high;
+ };
+};
+
+&codec {
+ allwinner,audio-routing =
+ "Line Out", "LINEOUT",
+ "MIC1", "Mic",
+ "Mic", "MBIAS";
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
+&ir {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_pins_a>;
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ vmmc-supply = <®_vcc_io>;
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+ cd-inverted;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&ohci3 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbphy {
+ /* VBUS on USB ports are always on */
+ usb0_vbus-supply = <®_vcc5v0>;
+ usb1_vbus-supply = <®_vcc5v0>;
+ usb2_vbus-supply = <®_vcc5v0>;
+ usb3_vbus-supply = <®_vcc5v0>;
+ status = "okay";
+};
--
2.15.0
^ permalink raw reply related
* Re: [PATCH v7 1/2] dt-bindings: watchdog: Add Spreadtrum watchdog documentation
From: Guenter Roeck @ 2017-11-28 4:09 UTC (permalink / raw)
To: Eric Long, Rob Herring, Mark Rutland
Cc: baolin.wang-QSEj5FYQhm4dnm+yROfE0A,
linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
huitao.yue-lxIno14LUO0EEoCn2XhGlw
In-Reply-To: <61f88b7f9c1ac8a2d4bd7dbab672ad913bd2707d.1511835645.git.eric.long-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
On 11/27/2017 06:18 PM, Eric Long wrote:
> This patch adds the documentation for Spreadtrum watchdog driver.
>
> Signed-off-by: Eric Long <eric.long-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
The patch series is in my tree, and will ultimately find its way into Wim's tree.
No need to resend it anymore.
In general, if a patch is available in
git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git watchdog-next
there is no need to resend it.
Thanks,
Guenter
> ---
> Changes since v6:
> - No updates.
>
> Changes since v5:
> - No updates.
>
> Changes since v4:
> - No updates.
>
> Changes since v3:
> - No updates.
>
> Changes since v2:
> - Add acked tag from Rob.
>
> Changes since v1:
> - No updates.
> ---
> .../devicetree/bindings/watchdog/sprd-wdt.txt | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/watchdog/sprd-wdt.txt
>
> diff --git a/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt b/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt
> new file mode 100644
> index 0000000..aeaf3e0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt
> @@ -0,0 +1,19 @@
> +Spreadtrum SoCs Watchdog timer
> +
> +Required properties:
> +- compatible : Should be "sprd,sp9860-wdt".
> +- reg : Specifies base physical address and size of the registers.
> +- interrupts : Exactly one interrupt specifier.
> +- timeout-sec : Contain the default watchdog timeout in seconds.
> +- clock-names : Contain the input clock names.
> +- clocks : Phandles to input clocks.
> +
> +Example:
> + watchdog: watchdog@40310000 {
> + compatible = "sprd,sp9860-wdt";
> + reg = <0 0x40310000 0 0x1000>;
> + interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
> + timeout-sec = <12>;
> + clock-names = "enable", "rtc_enable";
> + clocks = <&clk_aon_apb_gates1 8>, <&clk_aon_apb_rtc_gates 9>;
> + };
>
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" 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 4/4] pinctrl: mediatek: update MAINTAINERS entry with MediaTek pinctrl driver
From: sean.wang @ 2017-11-28 3:50 UTC (permalink / raw)
To: robh+dt, mark.rutland, linus.walleij, matthias.bgg, devicetree,
linux-mediatek
Cc: linux-arm-kernel, linux-gpio, linux-kernel, Sean Wang
In-Reply-To: <cover.1511840374.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
I work for MediaTek on maintaining the existing MediaTek SoC whose target
to home gateway such as MT7622 and MT7623 that is reusing MT2701 related
files and will keep adding support for the following such kinds of SoCs
in the future.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52f..c0edf30 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10773,6 +10773,16 @@ M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
S: Maintained
F: drivers/pinctrl/intel/
+PIN CONTROLLER - MEDIATEK
+M: Sean Wang <sean.wang@mediatek.com>
+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
+F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
+F: drivers/pinctrl/mediatek/pinctrl-mtk-common.*
+F: drivers/pinctrl/mediatek/pinctrl-mt2701.c
+F: drivers/pinctrl/mediatek/pinctrl-mt7622.c
+
PIN CONTROLLER - QUALCOMM
M: Bjorn Andersson <bjorn.andersson@linaro.org>
S: Maintained
--
2.7.4
^ permalink raw reply related
* [PATCH 3/4] pinctrl: mediatek: add pinctrl driver for MT7622 SoC
From: sean.wang @ 2017-11-28 3:50 UTC (permalink / raw)
To: robh+dt, mark.rutland, linus.walleij, matthias.bgg, devicetree,
linux-mediatek
Cc: linux-arm-kernel, linux-gpio, linux-kernel, Sean Wang
In-Reply-To: <cover.1511840374.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
Add support for pinctrl on MT7622 SoC. The IO core found on the SoC has
the registers for pinctrl, pinconf and gpio mixed up in the same register
range. However, the IO core for the MT7622 SoC is completely distinct from
anyone of previous MediaTek SoCs which already had support, such as
the hardware internal, register address map and register detailed
definition for each pin.
Therefore, instead, the driver is being newly implemented by reusing
generic methods provided from the core layer with GENERIC_PINCONF,
GENERIC_PINCTRL_GROUPS, and GENERIC_PINMUX_FUNCTIONS for the sake of code
simplicity and rid of superfluous code. Where the function of pins
determined by groups is utilized in this driver which can help developers
less confused with what combinations of pins effective on the SoC and even
reducing the mistakes during the integration of those relevant boards.
As the gpio_chip handling is also only a few lines, the driver also
implements the gpio functionality directly through GPIOLIB.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/pinctrl/Makefile | 2 +-
drivers/pinctrl/mediatek/Kconfig | 10 +
drivers/pinctrl/mediatek/Makefile | 3 +-
drivers/pinctrl/mediatek/pinctrl-mt7622.c | 1536 +++++++++++++++++++++++++++++
4 files changed, 1549 insertions(+), 2 deletions(-)
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7622.c
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index d0d4844..c39aa482 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -64,5 +64,5 @@ obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/
obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
-obj-$(CONFIG_PINCTRL_MTK) += mediatek/
+obj-y += mediatek/
obj-$(CONFIG_PINCTRL_ZX) += zte/
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 03b3023..3e59874 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -32,6 +32,16 @@ config PINCTRL_MT8127
select PINCTRL_MTK
# For ARMv8 SoCs
+config PINCTRL_MT7622
+ bool "MediaTek MT7622 pin control"
+ depends on OF
+ depends on ARM64 || COMPILE_TEST
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GPIOLIB
+ select OF_GPIO
+
config PINCTRL_MT8173
bool "Mediatek MT8173 pin control"
depends on OF
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index 10d9014..ed7d2b2 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -1,10 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
# Core
-obj-y += pinctrl-mtk-common.o
+obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
# SoC Drivers
obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o
obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o
+obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
new file mode 100644
index 0000000..36205df
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
@@ -0,0 +1,1536 @@
+/*
+ * MediaTek MT7622 Pinctrl Driver
+ *
+ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.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.
+ *
+ * This program 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.
+ */
+
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/regmap.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
+#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
+#define PINCTRL_PIN_GROUP(name, id) \
+ { \
+ name, \
+ id##_pins, \
+ ARRAY_SIZE(id##_pins), \
+ id##_funcs, \
+ }
+
+#define MTK_GPIO_MODE 1
+#define MTK_INPUT 0
+#define MTK_OUTPUT 1
+#define MTK_DISABLE 0
+#define MTK_ENABLE 1
+
+/* Custom pinconf parameters */
+#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1)
+#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2)
+
+/* List these attributes which could be modified for the pin */
+enum {
+ PINCTRL_PIN_REG_MODE,
+ PINCTRL_PIN_REG_DIR,
+ PINCTRL_PIN_REG_DI,
+ PINCTRL_PIN_REG_DO,
+ PINCTRL_PIN_REG_SR,
+ PINCTRL_PIN_REG_SMT,
+ PINCTRL_PIN_REG_PD,
+ PINCTRL_PIN_REG_PU,
+ PINCTRL_PIN_REG_E4,
+ PINCTRL_PIN_REG_E8,
+ PINCTRL_PIN_REG_TDSEL,
+ PINCTRL_PIN_REG_RDSEL,
+ PINCTRL_PIN_REG_MAX,
+};
+
+/* struct mtk_pin_field - the structure that holds the information of the field
+ * used to describe the attribute for the pin
+ * @offset: the register offset relative to the base address
+ * @mask: the mask used to filter out the field from the register
+ * @bitpos: the start bit relative to the register
+ * @next: the indication that the field would be extended to the
+ next register
+ */
+struct mtk_pin_field {
+ u32 offset;
+ u32 mask;
+ u8 bitpos;
+ u8 next;
+};
+
+/* struct mtk_pin_field_calc - the structure that holds the range providing
+ * the guide used to look up the relevant field
+ * @s_pin: the start pin within the range
+ * @e_pin: the end pin within the range
+ * @s_addr: the start address for the range
+ * @x_addrs: the address distance between two consecutive registers
+ * within the range
+ * @s_bit: the start bit for the first register within the range
+ * @x_bits: the bit distance between two consecutive pins within
+ * the range
+ */
+struct mtk_pin_field_calc {
+ u16 s_pin;
+ u16 e_pin;
+ u32 s_addr;
+ u8 x_addrs;
+ u8 s_bit;
+ u8 x_bits;
+};
+
+/* struct mtk_pin_reg_calc - the structure that holds all ranges used to
+ * determine which register the pin would make use of
+ * for certain pin attribute.
+ * @range: the start address for the range
+ * @nranges: the number of items in the range
+ */
+struct mtk_pin_reg_calc {
+ const struct mtk_pin_field_calc *range;
+ unsigned int nranges;
+};
+
+/* struct mtk_pin_soc - the structure that holds SoC-specific data */
+struct mtk_pin_soc {
+ const struct mtk_pin_reg_calc *reg_cal;
+ const struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+ const struct group_desc *grps;
+ unsigned int ngrps;
+ const struct function_desc *funcs;
+ unsigned int nfuncs;
+};
+
+struct mtk_pinctrl {
+ struct pinctrl_dev *pctrl;
+ void __iomem *base;
+ struct device *dev;
+ struct gpio_chip chip;
+ const struct mtk_pin_soc *soc;
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_mode_range[] = {
+ {0, 0, 0x320, 0x10, 16, 4},
+ {1, 4, 0x3a0, 0x10, 16, 4},
+ {5, 5, 0x320, 0x10, 0, 4},
+ {6, 6, 0x300, 0x10, 4, 4},
+ {7, 7, 0x300, 0x10, 4, 4},
+ {8, 9, 0x350, 0x10, 20, 4},
+ {10, 10, 0x300, 0x10, 8, 4},
+ {11, 11, 0x300, 0x10, 8, 4},
+ {12, 12, 0x300, 0x10, 8, 4},
+ {13, 13, 0x300, 0x10, 8, 4},
+ {14, 15, 0x320, 0x10, 4, 4},
+ {16, 17, 0x320, 0x10, 20, 4},
+ {18, 21, 0x310, 0x10, 16, 4},
+ {22, 22, 0x380, 0x10, 16, 4},
+ {23, 23, 0x300, 0x10, 24, 4},
+ {24, 24, 0x300, 0x10, 24, 4},
+ {25, 25, 0x300, 0x10, 12, 4},
+ {25, 25, 0x300, 0x10, 12, 4},
+ {26, 26, 0x300, 0x10, 12, 4},
+ {27, 27, 0x300, 0x10, 12, 4},
+ {28, 28, 0x300, 0x10, 12, 4},
+ {29, 29, 0x300, 0x10, 12, 4},
+ {30, 30, 0x300, 0x10, 12, 4},
+ {31, 31, 0x300, 0x10, 12, 4},
+ {32, 32, 0x300, 0x10, 12, 4},
+ {33, 33, 0x300, 0x10, 12, 4},
+ {34, 34, 0x300, 0x10, 12, 4},
+ {35, 35, 0x300, 0x10, 12, 4},
+ {36, 36, 0x300, 0x10, 12, 4},
+ {37, 37, 0x300, 0x10, 20, 4},
+ {38, 38, 0x300, 0x10, 20, 4},
+ {39, 39, 0x300, 0x10, 20, 4},
+ {40, 40, 0x300, 0x10, 20, 4},
+ {41, 41, 0x300, 0x10, 20, 4},
+ {42, 42, 0x300, 0x10, 20, 4},
+ {43, 43, 0x300, 0x10, 20, 4},
+ {44, 44, 0x300, 0x10, 20, 4},
+ {45, 46, 0x300, 0x10, 20, 4},
+ {47, 47, 0x300, 0x10, 20, 4},
+ {48, 48, 0x300, 0x10, 20, 4},
+ {49, 49, 0x300, 0x10, 20, 4},
+ {50, 50, 0x300, 0x10, 20, 4},
+ {51, 70, 0x330, 0x10, 4, 4},
+ {71, 71, 0x300, 0x10, 16, 4},
+ {72, 72, 0x300, 0x10, 16, 4},
+ {73, 76, 0x310, 0x10, 0, 4},
+ {77, 77, 0x320, 0x10, 28, 4},
+ {78, 78, 0x320, 0x10, 12, 4},
+ {79, 82, 0x3a0, 0x10, 0, 4},
+ {83, 83, 0x350, 0x10, 28, 4},
+ {84, 84, 0x330, 0x10, 0, 4},
+ {85, 90, 0x360, 0x10, 4, 4},
+ {91, 94, 0x390, 0x10, 16, 4},
+ {95, 97, 0x380, 0x10, 20, 4},
+ {98, 101, 0x390, 0x10, 0, 4},
+ {102, 102, 0x360, 0x10, 0, 4},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_dir_range[] = {
+ {0, 102, 0x0, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_di_range[] = {
+ {0, 102, 0x200, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_do_range[] = {
+ {0, 102, 0x100, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_sr_range[] = {
+ {0, 31, 0x910, 0x10, 0, 1},
+ {32, 50, 0xa10, 0x10, 0, 1},
+ {51, 70, 0x810, 0x10, 0, 1},
+ {71, 72, 0xb10, 0x10, 0, 1},
+ {73, 86, 0xb10, 0x10, 4, 1},
+ {87, 90, 0xc10, 0x10, 0, 1},
+ {91, 102, 0xb10, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_smt_range[] = {
+ {0, 31, 0x920, 0x10, 0, 1},
+ {32, 50, 0xa20, 0x10, 0, 1},
+ {51, 70, 0x820, 0x10, 0, 1},
+ {71, 72, 0xb20, 0x10, 0, 1},
+ {73, 86, 0xb20, 0x10, 4, 1},
+ {87, 90, 0xc20, 0x10, 0, 1},
+ {91, 102, 0xb20, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_pu_range[] = {
+ {0, 31, 0x930, 0x10, 0, 1},
+ {32, 50, 0xa30, 0x10, 0, 1},
+ {51, 70, 0x830, 0x10, 0, 1},
+ {71, 72, 0xb30, 0x10, 0, 1},
+ {73, 86, 0xb30, 0x10, 4, 1},
+ {87, 90, 0xc30, 0x10, 0, 1},
+ {91, 102, 0xb30, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_pd_range[] = {
+ {0, 31, 0x940, 0x10, 0, 1},
+ {32, 50, 0xa40, 0x10, 0, 1},
+ {51, 70, 0x840, 0x10, 0, 1},
+ {71, 72, 0xb40, 0x10, 0, 1},
+ {73, 86, 0xb40, 0x10, 4, 1},
+ {87, 90, 0xc40, 0x10, 0, 1},
+ {91, 102, 0xb40, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_e4_range[] = {
+ {0, 31, 0x960, 0x10, 0, 1},
+ {32, 50, 0xa60, 0x10, 0, 1},
+ {51, 70, 0x860, 0x10, 0, 1},
+ {71, 72, 0xb60, 0x10, 0, 1},
+ {73, 86, 0xb60, 0x10, 4, 1},
+ {87, 90, 0xc60, 0x10, 0, 1},
+ {91, 102, 0xb60, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_e8_range[] = {
+ {0, 31, 0x970, 0x10, 0, 1},
+ {32, 50, 0xa70, 0x10, 0, 1},
+ {51, 70, 0x870, 0x10, 0, 1},
+ {71, 72, 0xb70, 0x10, 0, 1},
+ {73, 86, 0xb70, 0x10, 4, 1},
+ {87, 90, 0xc70, 0x10, 0, 1},
+ {91, 102, 0xb70, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_tdsel_range[] = {
+ {0, 31, 0x980, 0x4, 0, 4},
+ {32, 50, 0xa80, 0x4, 0, 4},
+ {51, 70, 0x880, 0x4, 0, 4},
+ {71, 72, 0xb80, 0x4, 0, 4},
+ {73, 86, 0xb80, 0x4, 16, 4},
+ {87, 90, 0xc80, 0x4, 0, 4},
+ {91, 102, 0xb88, 0x4, 8, 4},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_rdsel_range[] = {
+ {0, 31, 0x990, 0x4, 0, 6},
+ {32, 50, 0xa90, 0x4, 0, 6},
+ {51, 58, 0x890, 0x4, 0, 6},
+ {59, 60, 0x894, 0x4, 28, 6},
+ {61, 62, 0x894, 0x4, 16, 6},
+ {63, 66, 0x898, 0x4, 8, 6},
+ {67, 68, 0x89c, 0x4, 12, 6},
+ {69, 70, 0x89c, 0x4, 0, 6},
+ {71, 72, 0xb90, 0x4, 0, 6},
+ {73, 86, 0xb90, 0x4, 24, 6},
+ {87, 90, 0xc90, 0x4, 0, 6},
+ {91, 102, 0xb9c, 0x4, 12, 6},
+};
+
+static const struct mtk_pin_reg_calc mt7622_reg_cals[PINCTRL_PIN_REG_MAX] = {
+ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7622_pin_mode_range),
+ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7622_pin_dir_range),
+ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7622_pin_di_range),
+ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7622_pin_do_range),
+ [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt7622_pin_sr_range),
+ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7622_pin_smt_range),
+ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7622_pin_pu_range),
+ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7622_pin_pd_range),
+ [PINCTRL_PIN_REG_E4] = MTK_RANGE(mt7622_pin_e4_range),
+ [PINCTRL_PIN_REG_E8] = MTK_RANGE(mt7622_pin_e8_range),
+ [PINCTRL_PIN_REG_TDSEL] = MTK_RANGE(mt7622_pin_tdsel_range),
+ [PINCTRL_PIN_REG_RDSEL] = MTK_RANGE(mt7622_pin_rdsel_range),
+};
+
+static const struct pinctrl_pin_desc mt7622_pins[] = {
+ PINCTRL_PIN(0, "GPIO_A"),
+ PINCTRL_PIN(1, "I2S1_IN"),
+ PINCTRL_PIN(2, "I2S1_OUT"),
+ PINCTRL_PIN(3, "I2S_BCLK"),
+ PINCTRL_PIN(4, "I2S_WS"),
+ PINCTRL_PIN(5, "I2S_MCLK"),
+ PINCTRL_PIN(6, "TXD0"),
+ PINCTRL_PIN(7, "RXD0"),
+ PINCTRL_PIN(8, "SPI_WP"),
+ PINCTRL_PIN(9, "SPI_HOLD"),
+ PINCTRL_PIN(10, "SPI_CLK"),
+ PINCTRL_PIN(11, "SPI_MOSI"),
+ PINCTRL_PIN(12, "SPI_MISO"),
+ PINCTRL_PIN(13, "SPI_CS"),
+ PINCTRL_PIN(14, "SPI_SDA"),
+ PINCTRL_PIN(15, "SPI_SCL"),
+ PINCTRL_PIN(16, "I2S2_IN"),
+ PINCTRL_PIN(17, "I2S3_IN"),
+ PINCTRL_PIN(18, "I2S4_IN"),
+ PINCTRL_PIN(19, "I2S2_OUT"),
+ PINCTRL_PIN(20, "I2S3_OUT"),
+ PINCTRL_PIN(21, "I2S4_OUT"),
+ PINCTRL_PIN(22, "GPIO_B"),
+ PINCTRL_PIN(23, "MDC"),
+ PINCTRL_PIN(24, "MDIO"),
+ PINCTRL_PIN(25, "G2_TXD0"),
+ PINCTRL_PIN(26, "G2_TXD1"),
+ PINCTRL_PIN(27, "G2_TXD2"),
+ PINCTRL_PIN(28, "G2_TXD3"),
+ PINCTRL_PIN(29, "G2_TXEN"),
+ PINCTRL_PIN(30, "G2_TXC"),
+ PINCTRL_PIN(31, "G2_RXD0"),
+ PINCTRL_PIN(32, "G2_RXD1"),
+ PINCTRL_PIN(33, "G2_RXD2"),
+ PINCTRL_PIN(34, "G2_RXD3"),
+ PINCTRL_PIN(35, "G2_RXDV"),
+ PINCTRL_PIN(36, "G2_RXC"),
+ PINCTRL_PIN(37, "NCEB"),
+ PINCTRL_PIN(38, "NWEB"),
+ PINCTRL_PIN(39, "NREB"),
+ PINCTRL_PIN(40, "NDL4"),
+ PINCTRL_PIN(41, "NDL5"),
+ PINCTRL_PIN(42, "NDL6"),
+ PINCTRL_PIN(43, "NDL7"),
+ PINCTRL_PIN(44, "NRB"),
+ PINCTRL_PIN(45, "NCLE"),
+ PINCTRL_PIN(46, "NALE"),
+ PINCTRL_PIN(47, "NDL0"),
+ PINCTRL_PIN(48, "NDL1"),
+ PINCTRL_PIN(49, "NDL2"),
+ PINCTRL_PIN(50, "NDL3"),
+ PINCTRL_PIN(51, "MDI_TP_P0"),
+ PINCTRL_PIN(52, "MDI_TN_P0"),
+ PINCTRL_PIN(53, "MDI_RP_P0"),
+ PINCTRL_PIN(54, "MDI_RN_P0"),
+ PINCTRL_PIN(55, "MDI_TP_P1"),
+ PINCTRL_PIN(56, "MDI_TN_P1"),
+ PINCTRL_PIN(57, "MDI_RP_P1"),
+ PINCTRL_PIN(58, "MDI_RN_P1"),
+ PINCTRL_PIN(59, "MDI_RP_P2"),
+ PINCTRL_PIN(60, "MDI_RN_P2"),
+ PINCTRL_PIN(61, "MDI_TP_P2"),
+ PINCTRL_PIN(62, "MDI_TN_P2"),
+ PINCTRL_PIN(63, "MDI_TP_P3"),
+ PINCTRL_PIN(64, "MDI_TN_P3"),
+ PINCTRL_PIN(65, "MDI_RP_P3"),
+ PINCTRL_PIN(66, "MDI_RN_P3"),
+ PINCTRL_PIN(67, "MDI_RP_P4"),
+ PINCTRL_PIN(68, "MDI_RN_P4"),
+ PINCTRL_PIN(69, "MDI_TP_P4"),
+ PINCTRL_PIN(70, "MDI_TN_P4"),
+ PINCTRL_PIN(71, "SPI2_CK"),
+ PINCTRL_PIN(72, "SPI2_DATA"),
+ PINCTRL_PIN(73, "SPIC1_CLK"),
+ PINCTRL_PIN(74, "SPIC1_MOSI"),
+ PINCTRL_PIN(75, "SPIC1_MISO"),
+ PINCTRL_PIN(76, "SPIC1_CS"),
+ PINCTRL_PIN(77, "GPIO_D"),
+ PINCTRL_PIN(78, "WATCHDOG"),
+ PINCTRL_PIN(79, "RTS3_N"),
+ PINCTRL_PIN(80, "CTS3_N"),
+ PINCTRL_PIN(81, "TXD3"),
+ PINCTRL_PIN(82, "RXD3"),
+ PINCTRL_PIN(83, "PERST0_N"),
+ PINCTRL_PIN(84, "PERST1_N"),
+ PINCTRL_PIN(85, "WLED_N"),
+ PINCTRL_PIN(86, "EPHY_LED0_N"),
+ PINCTRL_PIN(87, "AUXIN0"),
+ PINCTRL_PIN(88, "AUXIN1"),
+ PINCTRL_PIN(89, "AUXIN2"),
+ PINCTRL_PIN(90, "AUXIN3"),
+ PINCTRL_PIN(91, "TXD4"),
+ PINCTRL_PIN(92, "RXD4"),
+ PINCTRL_PIN(93, "RTS4_IN"),
+ PINCTRL_PIN(94, "CST4_IN"),
+ PINCTRL_PIN(95, "PWM1"),
+ PINCTRL_PIN(96, "PWM2"),
+ PINCTRL_PIN(97, "PWM3"),
+ PINCTRL_PIN(98, "PWM4"),
+ PINCTRL_PIN(99, "PWM5"),
+ PINCTRL_PIN(100, "PWM6"),
+ PINCTRL_PIN(101, "PWM7"),
+ PINCTRL_PIN(102, "GPIO_E"),
+};
+
+/* List all groups consisting of these pins dedicated to the enablement of
+ * certain hardware block and the corresponding mode for all of the pins. The
+ * hardware probably has multiple combinations of these pinouts.
+ */
+
+/* EMMC */
+static int mt7622_emmc_pins[] = { 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, };
+static int mt7622_emmc_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+
+/* LED for EPHY */
+static int mt7622_ephy0_led_pins[] = { 86, };
+static int mt7622_ephy0_led_funcs[] = { 0, };
+static int mt7622_ephy1_led_pins[] = { 91, };
+static int mt7622_ephy1_led_funcs[] = { 2, };
+static int mt7622_ephy2_led_pins[] = { 92, };
+static int mt7622_ephy2_led_funcs[] = { 2, };
+static int mt7622_ephy3_led_pins[] = { 93, };
+static int mt7622_ephy3_led_funcs[] = { 2, };
+static int mt7622_ephy4_led_pins[] = { 94, };
+static int mt7622_ephy4_led_funcs[] = { 2, };
+
+/* Embedded Switch */
+static int mt7622_esw_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, };
+static int mt7622_esw_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
+
+/* GMAC1 */
+static int mt7622_gmac1_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, };
+static int mt7622_gmac1_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+
+/* GMAC2 */
+static int mt7622_gmac2_pins[] = { 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, };
+static int mt7622_gmac2_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
+
+/* I2C */
+static int mt7622_i2c0_pins[] = { 14, 15, };
+static int mt7622_i2c0_funcs[] = { 0, 0, };
+static int mt7622_i2c1_0_pins[] = { 55, 56, };
+static int mt7622_i2c1_0_funcs[] = { 0, 0, };
+static int mt7622_i2c1_1_pins[] = { 73, 74, };
+static int mt7622_i2c1_1_funcs[] = { 3, 3, };
+static int mt7622_i2c1_2_pins[] = { 87, 88, };
+static int mt7622_i2c1_2_funcs[] = { 0, 0, };
+static int mt7622_i2c2_0_pins[] = { 57, 58, };
+static int mt7622_i2c2_0_funcs[] = { 0, 0, };
+static int mt7622_i2c2_1_pins[] = { 75, 76, };
+static int mt7622_i2c2_1_funcs[] = { 3, 3, };
+static int mt7622_i2c2_2_pins[] = { 89, 90, };
+static int mt7622_i2c2_2_funcs[] = { 0, 0, };
+
+/* I2S */
+static int mt7622_i2s_in_bclk_ws_mclk_pins[] = { 3, 4, 5};
+static int mt7622_i2s_in_bclk_ws_mclk_funcs[] = { 3, 3, 0};
+static int mt7622_i2s1_in_data_pins[] = { 1, };
+static int mt7622_i2s1_in_data_funcs[] = { 0, };
+static int mt7622_i2s2_in_data_pins[] = { 16, };
+static int mt7622_i2s2_in_data_funcs[] = { 0, };
+static int mt7622_i2s3_in_data_pins[] = { 17, };
+static int mt7622_i2s3_in_data_funcs[] = { 0, };
+static int mt7622_i2s4_in_data_pins[] = { 18, };
+static int mt7622_i2s4_in_data_funcs[] = { 0, };
+static int mt7622_i2s_out_bclk_ws_mclk_pins[] = { 3, 4, 5, };
+static int mt7622_i2s_out_bclk_ws_mclk_funcs[] = { 0, 0, 0, };
+static int mt7622_i2s1_out_data_pins[] = { 2, };
+static int mt7622_i2s1_out_data_funcs[] = { 0, };
+static int mt7622_i2s2_out_data_pins[] = { 19, };
+static int mt7622_i2s2_out_data_funcs[] = { 0, };
+static int mt7622_i2s3_out_data_pins[] = { 20, };
+static int mt7622_i2s3_out_data_funcs[] = { 0, };
+static int mt7622_i2s4_out_data_pins[] = { 21, };
+static int mt7622_i2s4_out_data_funcs[] = { 0, };
+
+/* IR */
+static int mt7622_ir_0_tx_pins[] = { 16, };
+static int mt7622_ir_0_tx_funcs[] = { 4, };
+static int mt7622_ir_1_tx_pins[] = { 59, };
+static int mt7622_ir_1_tx_funcs[] = { 5, };
+static int mt7622_ir_2_tx_pins[] = { 99, };
+static int mt7622_ir_2_tx_funcs[] = { 3, };
+static int mt7622_ir_0_rx_pins[] = { 17, };
+static int mt7622_ir_0_rx_funcs[] = { 4, };
+static int mt7622_ir_1_rx_pins[] = { 60, };
+static int mt7622_ir_1_rx_funcs[] = { 5, };
+static int mt7622_ir_2_rx_pins[] = { 100, };
+static int mt7622_ir_2_rx_funcs[] = { 3, };
+
+/* MDIO */
+static int mt7622_mdc_mdio_pins[] = { 23, 24, };
+static int mt7622_mdc_mdio_funcs[] = { 0, 0, };
+
+/* PCIE */
+static int mt7622_pcie0_0_waken_clkreq_pins[] = { 14, 15, };
+static int mt7622_pcie0_0_waken_clkreq_funcs[] = { 2, 2, };
+static int mt7622_pcie0_1_waken_clkreq_pins[] = { 79, 80, };
+static int mt7622_pcie0_1_waken_clkreq_funcs[] = { 4, 4, };
+static int mt7622_pcie1_0_waken_clkreq_pins[] = { 14, 15, };
+static int mt7622_pcie1_0_waken_clkreq_funcs[] = { 3, 3, };
+static int mt7622_pcie0_pad_perst_pins[] = { 83, };
+static int mt7622_pcie0_pad_perst_funcs[] = { 0, };
+static int mt7622_pcie1_pad_perst_pins[] = { 84, };
+static int mt7622_pcie1_pad_perst_funcs[] = { 0, };
+
+/* Parallel NAND */
+static int mt7622_pnand_pins[] = { 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, };
+static int mt7622_pnand_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, };
+
+/* PWM */
+static int mt7622_pwm_ch1_0_pins[] = { 51, };
+static int mt7622_pwm_ch1_0_funcs[] = { 3, };
+static int mt7622_pwm_ch1_1_pins[] = { 73, };
+static int mt7622_pwm_ch1_1_funcs[] = { 4, };
+static int mt7622_pwm_ch1_2_pins[] = { 95, };
+static int mt7622_pwm_ch1_2_funcs[] = { 0, };
+static int mt7622_pwm_ch2_0_pins[] = { 52, };
+static int mt7622_pwm_ch2_0_funcs[] = { 3, };
+static int mt7622_pwm_ch2_1_pins[] = { 74, };
+static int mt7622_pwm_ch2_1_funcs[] = { 4, };
+static int mt7622_pwm_ch2_2_pins[] = { 96, };
+static int mt7622_pwm_ch2_2_funcs[] = { 0, };
+static int mt7622_pwm_ch3_0_pins[] = { 53, };
+static int mt7622_pwm_ch3_0_funcs[] = { 3, };
+static int mt7622_pwm_ch3_1_pins[] = { 75, };
+static int mt7622_pwm_ch3_1_funcs[] = { 4, };
+static int mt7622_pwm_ch3_2_pins[] = { 97, };
+static int mt7622_pwm_ch3_2_funcs[] = { 0, };
+static int mt7622_pwm_ch4_0_pins[] = { 54, };
+static int mt7622_pwm_ch4_0_funcs[] = { 3, };
+static int mt7622_pwm_ch4_1_pins[] = { 67, };
+static int mt7622_pwm_ch4_1_funcs[] = { 3, };
+static int mt7622_pwm_ch4_2_pins[] = { 76, };
+static int mt7622_pwm_ch4_2_funcs[] = { 4, };
+static int mt7622_pwm_ch4_3_pins[] = { 98, };
+static int mt7622_pwm_ch4_3_funcs[] = { 0, };
+static int mt7622_pwm_ch5_0_pins[] = { 68, };
+static int mt7622_pwm_ch5_0_funcs[] = { 3, };
+static int mt7622_pwm_ch5_1_pins[] = { 77, };
+static int mt7622_pwm_ch5_1_funcs[] = { 4, };
+static int mt7622_pwm_ch5_2_pins[] = { 99, };
+static int mt7622_pwm_ch5_2_funcs[] = { 0, };
+static int mt7622_pwm_ch6_0_pins[] = { 69, };
+static int mt7622_pwm_ch6_0_funcs[] = { 3, };
+static int mt7622_pwm_ch6_1_pins[] = { 78, };
+static int mt7622_pwm_ch6_1_funcs[] = { 4, };
+static int mt7622_pwm_ch6_2_pins[] = { 81, };
+static int mt7622_pwm_ch6_2_funcs[] = { 4, };
+static int mt7622_pwm_ch6_3_pins[] = { 100, };
+static int mt7622_pwm_ch6_3_funcs[] = { 0, };
+static int mt7622_pwm_ch7_0_pins[] = { 70, };
+static int mt7622_pwm_ch7_0_funcs[] = { 3, };
+static int mt7622_pwm_ch7_1_pins[] = { 82, };
+static int mt7622_pwm_ch7_1_funcs[] = { 4, };
+static int mt7622_pwm_ch7_2_pins[] = { 101, };
+static int mt7622_pwm_ch7_2_funcs[] = { 0, };
+
+/* SD */
+static int mt7622_sd_0_pins[] = { 16, 17, 18, 19, 20, 21, };
+static int mt7622_sd_0_funcs[] = { 2, 2, 2, 2, 2, 2, };
+static int mt7622_sd_1_pins[] = { 25, 26, 27, 28, 29, 30, };
+static int mt7622_sd_1_funcs[] = { 2, 2, 2, 2, 2, 2, };
+
+/* Serial NAND */
+static int mt7622_snfi_pins[] = { 8, 9, 10, 11, 12, 13, };
+static int mt7622_snfi_funcs[] = { 2, 2, 2, 2, 2, 2, };
+
+/* SPI NOR */
+static int mt7622_spi_pins[] = { 8, 9, 10, 11, 12, 13 };
+static int mt7622_spi_funcs[] = { 0, 0, 0, 0, 0, 0, };
+
+/* SPIC */
+static int mt7622_spic0_0_pins[] = { 63, 64, 65, 66, };
+static int mt7622_spic0_0_funcs[] = { 4, 4, 4, 4, };
+static int mt7622_spic0_1_pins[] = { 79, 80, 81, 82, };
+static int mt7622_spic0_1_funcs[] = { 3, 3, 3, 3, };
+static int mt7622_spic1_0_pins[] = { 67, 68, 69, 70, };
+static int mt7622_spic1_0_funcs[] = { 4, 4, 4, 4, };
+static int mt7622_spic1_1_pins[] = { 73, 74, 75, 76, };
+static int mt7622_spic1_1_funcs[] = { 0, 0, 0, 0, };
+
+/* TDM */
+static int mt7622_tdm_0_out_mclk_bclk_ws_pins[] = { 8, 9, 10, };
+static int mt7622_tdm_0_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_0_in_mclk_bclk_ws_pins[] = { 11, 12, 13, };
+static int mt7622_tdm_0_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_0_out_data_pins[] = { 20, };
+static int mt7622_tdm_0_out_data_funcs[] = { 3, };
+static int mt7622_tdm_0_in_data_pins[] = { 21, };
+static int mt7622_tdm_0_in_data_funcs[] = { 3, };
+static int mt7622_tdm_1_out_mclk_bclk_ws_pins[] = { 57, 58, 59, };
+static int mt7622_tdm_1_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_1_in_mclk_bclk_ws_pins[] = { 60, 61, 62, };
+static int mt7622_tdm_1_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_1_out_data_pins[] = { 55, };
+static int mt7622_tdm_1_out_data_funcs[] = { 3, };
+static int mt7622_tdm_1_in_data_pins[] = { 56, };
+static int mt7622_tdm_1_in_data_funcs[] = { 3, };
+
+/* UART */
+static int mt7622_uart0_0_tx_rx_pins[] = { 6, 7, };
+static int mt7622_uart0_0_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart1_0_tx_rx_pins[] = { 55, 56, };
+static int mt7622_uart1_0_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart1_0_rts_cts_pins[] = { 57, 58, };
+static int mt7622_uart1_0_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart1_1_tx_rx_pins[] = { 73, 74, };
+static int mt7622_uart1_1_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart1_1_rts_cts_pins[] = { 75, 76, };
+static int mt7622_uart1_1_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart2_0_tx_rx_pins[] = { 3, 4, };
+static int mt7622_uart2_0_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart2_0_rts_cts_pins[] = { 1, 2, };
+static int mt7622_uart2_0_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart2_1_tx_rx_pins[] = { 51, 52, };
+static int mt7622_uart2_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart2_1_rts_cts_pins[] = { 53, 54, };
+static int mt7622_uart2_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart2_2_tx_rx_pins[] = { 59, 60, };
+static int mt7622_uart2_2_tx_rx_funcs[] = { 4, 4, };
+static int mt7622_uart2_2_rts_cts_pins[] = { 61, 62, };
+static int mt7622_uart2_2_rts_cts_funcs[] = { 4, 4, };
+static int mt7622_uart2_3_tx_rx_pins[] = { 95, 96, };
+static int mt7622_uart2_3_tx_rx_funcs[] = { 3, 3, };
+static int mt7622_uart3_0_tx_rx_pins[] = { 57, 58, };
+static int mt7622_uart3_0_tx_rx_funcs[] = { 5, 5, };
+static int mt7622_uart3_1_tx_rx_pins[] = { 81, 82, };
+static int mt7622_uart3_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart3_1_rts_cts_pins[] = { 79, 80, };
+static int mt7622_uart3_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart4_0_tx_rx_pins[] = { 61, 62, };
+static int mt7622_uart4_0_tx_rx_funcs[] = { 5, 5, };
+static int mt7622_uart4_1_tx_rx_pins[] = { 91, 92, };
+static int mt7622_uart4_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart4_1_rts_cts_pins[] = { 93, 94 };
+static int mt7622_uart4_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart4_2_tx_rx_pins[] = { 97, 98, };
+static int mt7622_uart4_2_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart4_2_rts_cts_pins[] = { 95, 96 };
+static int mt7622_uart4_2_rts_cts_funcs[] = { 2, 2, };
+
+/* WLAN LED */
+static int mt7622_wled_pins[] = { 85, };
+static int mt7622_wled_funcs[] = { 0, };
+
+static const struct group_desc mt7622_groups[] = {
+ PINCTRL_PIN_GROUP("emmc", mt7622_emmc),
+ PINCTRL_PIN_GROUP("ephy0_led", mt7622_ephy0_led),
+ PINCTRL_PIN_GROUP("ephy1_led", mt7622_ephy1_led),
+ PINCTRL_PIN_GROUP("ephy2_led", mt7622_ephy2_led),
+ PINCTRL_PIN_GROUP("ephy3_led", mt7622_ephy3_led),
+ PINCTRL_PIN_GROUP("ephy4_led", mt7622_ephy4_led),
+ PINCTRL_PIN_GROUP("esw", mt7622_esw),
+ PINCTRL_PIN_GROUP("gmac1", mt7622_gmac1),
+ PINCTRL_PIN_GROUP("gmac2", mt7622_gmac2),
+ PINCTRL_PIN_GROUP("i2c0", mt7622_i2c0),
+ PINCTRL_PIN_GROUP("i2c1_0", mt7622_i2c1_0),
+ PINCTRL_PIN_GROUP("i2c1_1", mt7622_i2c1_1),
+ PINCTRL_PIN_GROUP("i2c1_2", mt7622_i2c1_2),
+ PINCTRL_PIN_GROUP("i2c2_0", mt7622_i2c2_0),
+ PINCTRL_PIN_GROUP("i2c2_1", mt7622_i2c2_1),
+ PINCTRL_PIN_GROUP("i2c2_2", mt7622_i2c2_2),
+ PINCTRL_PIN_GROUP("i2s_out_bclk_ws_mclk", mt7622_i2s_out_bclk_ws_mclk),
+ PINCTRL_PIN_GROUP("i2s_in_bclk_ws_mclk", mt7622_i2s_in_bclk_ws_mclk),
+ PINCTRL_PIN_GROUP("i2s1_in_data", mt7622_i2s1_in_data),
+ PINCTRL_PIN_GROUP("i2s2_in_data", mt7622_i2s2_in_data),
+ PINCTRL_PIN_GROUP("i2s3_in_data", mt7622_i2s3_in_data),
+ PINCTRL_PIN_GROUP("i2s4_in_data", mt7622_i2s4_in_data),
+ PINCTRL_PIN_GROUP("i2s1_out_data", mt7622_i2s1_out_data),
+ PINCTRL_PIN_GROUP("i2s2_out_data", mt7622_i2s2_out_data),
+ PINCTRL_PIN_GROUP("i2s3_out_data", mt7622_i2s3_out_data),
+ PINCTRL_PIN_GROUP("i2s4_out_data", mt7622_i2s4_out_data),
+ PINCTRL_PIN_GROUP("ir_0_tx", mt7622_ir_0_tx),
+ PINCTRL_PIN_GROUP("ir_1_tx", mt7622_ir_1_tx),
+ PINCTRL_PIN_GROUP("ir_2_tx", mt7622_ir_2_tx),
+ PINCTRL_PIN_GROUP("ir_0_rx", mt7622_ir_0_rx),
+ PINCTRL_PIN_GROUP("ir_1_rx", mt7622_ir_1_rx),
+ PINCTRL_PIN_GROUP("ir_2_rx", mt7622_ir_2_rx),
+ PINCTRL_PIN_GROUP("mdc_mdio", mt7622_mdc_mdio),
+ PINCTRL_PIN_GROUP("pcie0_0_waken_clkreq", mt7622_pcie0_0_waken_clkreq),
+ PINCTRL_PIN_GROUP("pcie0_1_waken_clkreq", mt7622_pcie0_1_waken_clkreq),
+ PINCTRL_PIN_GROUP("pcie1_0_waken_clkreq", mt7622_pcie1_0_waken_clkreq),
+ PINCTRL_PIN_GROUP("pcie0_pad_perst", mt7622_pcie0_pad_perst),
+ PINCTRL_PIN_GROUP("pcie1_pad_perst", mt7622_pcie1_pad_perst),
+ PINCTRL_PIN_GROUP("par_nand", mt7622_pnand),
+ PINCTRL_PIN_GROUP("pwm_ch1_0", mt7622_pwm_ch1_0),
+ PINCTRL_PIN_GROUP("pwm_ch1_1", mt7622_pwm_ch1_1),
+ PINCTRL_PIN_GROUP("pwm_ch1_2", mt7622_pwm_ch1_2),
+ PINCTRL_PIN_GROUP("pwm_ch2_0", mt7622_pwm_ch2_0),
+ PINCTRL_PIN_GROUP("pwm_ch2_1", mt7622_pwm_ch2_1),
+ PINCTRL_PIN_GROUP("pwm_ch2_2", mt7622_pwm_ch2_2),
+ PINCTRL_PIN_GROUP("pwm_ch3_0", mt7622_pwm_ch3_0),
+ PINCTRL_PIN_GROUP("pwm_ch3_1", mt7622_pwm_ch3_1),
+ PINCTRL_PIN_GROUP("pwm_ch3_2", mt7622_pwm_ch3_2),
+ PINCTRL_PIN_GROUP("pwm_ch4_0", mt7622_pwm_ch4_0),
+ PINCTRL_PIN_GROUP("pwm_ch4_1", mt7622_pwm_ch4_1),
+ PINCTRL_PIN_GROUP("pwm_ch4_2", mt7622_pwm_ch4_2),
+ PINCTRL_PIN_GROUP("pwm_ch4_3", mt7622_pwm_ch4_3),
+ PINCTRL_PIN_GROUP("pwm_ch5_0", mt7622_pwm_ch5_0),
+ PINCTRL_PIN_GROUP("pwm_ch5_1", mt7622_pwm_ch5_1),
+ PINCTRL_PIN_GROUP("pwm_ch5_2", mt7622_pwm_ch5_2),
+ PINCTRL_PIN_GROUP("pwm_ch6_0", mt7622_pwm_ch6_0),
+ PINCTRL_PIN_GROUP("pwm_ch6_1", mt7622_pwm_ch6_1),
+ PINCTRL_PIN_GROUP("pwm_ch6_2", mt7622_pwm_ch6_2),
+ PINCTRL_PIN_GROUP("pwm_ch6_3", mt7622_pwm_ch6_3),
+ PINCTRL_PIN_GROUP("pwm_ch7_0", mt7622_pwm_ch7_0),
+ PINCTRL_PIN_GROUP("pwm_ch7_1", mt7622_pwm_ch7_1),
+ PINCTRL_PIN_GROUP("pwm_ch7_2", mt7622_pwm_ch7_2),
+ PINCTRL_PIN_GROUP("sd_0", mt7622_sd_0),
+ PINCTRL_PIN_GROUP("sd_1", mt7622_sd_1),
+ PINCTRL_PIN_GROUP("snfi", mt7622_snfi),
+ PINCTRL_PIN_GROUP("spi_nor", mt7622_spi),
+ PINCTRL_PIN_GROUP("spic0_0", mt7622_spic0_0),
+ PINCTRL_PIN_GROUP("spic0_1", mt7622_spic0_1),
+ PINCTRL_PIN_GROUP("spic1_0", mt7622_spic1_0),
+ PINCTRL_PIN_GROUP("spic1_1", mt7622_spic1_1),
+ PINCTRL_PIN_GROUP("tdm_0_out_mclk_bclk",
+ mt7622_tdm_0_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_0_in_mclk_bclk_ws",
+ mt7622_tdm_0_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_0_out_data", mt7622_tdm_0_out_data),
+ PINCTRL_PIN_GROUP("tdm_0_in_data", mt7622_tdm_0_in_data),
+ PINCTRL_PIN_GROUP("tdm_1_out_mclk_bclk",
+ mt7622_tdm_1_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_1_in_mclk_bclk_ws",
+ mt7622_tdm_1_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_1_out_data", mt7622_tdm_1_out_data),
+ PINCTRL_PIN_GROUP("tdm_1_in_data", mt7622_tdm_1_in_data),
+ PINCTRL_PIN_GROUP("uart0_0_tx_rx", mt7622_uart0_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_0_tx_rx", mt7622_uart1_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_0_rts_cts", mt7622_uart1_0_rts_cts),
+ PINCTRL_PIN_GROUP("uart1_1_tx_rx", mt7622_uart1_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_1_rts_cts", mt7622_uart1_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_0_tx_rx", mt7622_uart2_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_0_rts_cts", mt7622_uart2_0_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_1_tx_rx", mt7622_uart2_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_1_rts_cts", mt7622_uart2_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_2_tx_rx", mt7622_uart2_2_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_2_rts_cts", mt7622_uart2_2_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_3_tx_rx", mt7622_uart2_3_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_0_tx_rx", mt7622_uart3_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_1_tx_rx", mt7622_uart3_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_1_rts_cts", mt7622_uart3_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart4_0_tx_rx", mt7622_uart4_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_1_tx_rx", mt7622_uart4_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_1_rts_cts", mt7622_uart4_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart4_2_tx_rx", mt7622_uart4_2_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_2_rts_cts", mt7622_uart4_2_rts_cts),
+ PINCTRL_PIN_GROUP("wled", mt7622_wled),
+};
+
+/* Joint those groups owning the same capability in user point of view which
+ * allows that people tend to use through the device tree.
+ */
+static const char *mt7622_emmc_groups[] = { "emmc", };
+static const char *mt7622_ethernet_groups[] = { "esw", "mdc_mdio", "gmac1",
+ "gmac2", };
+static const char *mt7622_i2c_groups[] = { "i2c0", "i2c1_0", "i2c1_1",
+ "i2c1_2", "i2c2_0", "i2c2_1",
+ "i2c2_2", };
+static const char *mt7622_i2s_groups[] = { "i2s_out_bclk_ws_mclk",
+ "i2s_in_bclk_ws_mclk",
+ "i2s1_in_data", "i2s2_in_data",
+ "i2s3_in_data", "i2s4_in_data",
+ "i2s1_out_data", "i2s2_out_data",
+ "i2s3_out_data", "i2s4_out_data", };
+static const char *mt7622_ir_groups[] = { "ir_0_tx", "ir_1_tx", "ir_2_tx",
+ "ir_0_rx", "ir_1_rx", "ir_2_rx"};
+static const char *mt7622_led_groups[] = { "ephy0_led", "ephy1_led",
+ "ephy2_led", "ephy3_led",
+ "ephy4_led", "wled", };
+static const char *mt7622_flash_groups[] = { "par_nand", "snfi", "spi_nor"};
+static const char *mt7622_pcie_groups[] = { "pcie0_0_waken_clkreq",
+ "pcie0_1_waken_clkreq",
+ "pcie1_0_waken_clkreq",
+ "pcie0_pad_perst",
+ "pcie1_pad_perst", };
+static const char *mt7622_pwm_groups[] = { "pwm_ch1_0", "pwm_ch1_1",
+ "pwm_ch1_2", "pwm_ch2_0",
+ "pwm_ch2_1", "pwm_ch2_2",
+ "pwm_ch3_0", "pwm_ch3_1",
+ "pwm_ch3_2", "pwm_ch4_0",
+ "pwm_ch4_1", "pwm_ch4_2",
+ "pwm_ch4_3", "pwm_ch5_0",
+ "pwm_ch5_1", "pwm_ch5_2",
+ "pwm_ch6_0", "pwm_ch6_1",
+ "pwm_ch6_2", "pwm_ch6_3",
+ "pwm_ch7_0", "pwm_ch7_1",
+ "pwm_ch7_2" };
+static const char *mt7622_sd_groups[] = { "sd_0", "sd_1", };
+static const char *mt7622_spic_groups[] = { "spic0_0", "spic0_1", "spic1_0",
+ "spic1_1", };
+static const char *mt7622_tdm_groups[] = { "tdm_0_out_mclk_bclk",
+ "tdm_0_in_mclk_bclk_ws",
+ "tdm_0_out_data",
+ "tdm_0_in_data",
+ "tdm_1_out_mclk_bclk",
+ "tdm_1_in_mclk_bclk_ws",
+ "tdm_1_out_data",
+ "tdm_1_in_data", };
+
+static const char *mt7622_uart_groups[] = { "uart0_0_tx_rx",
+ "uart1_0_tx_rx", "uart1_0_rts_cts",
+ "uart1_1_tx_rx", "uart1_1_rts_cts",
+ "uart2_0_tx_rx", "uart2_0_rts_cts",
+ "uart2_1_tx_rx", "uart2_1_rts_cts",
+ "uart2_2_tx_rx", "uart2_2_rts_cts",
+ "uart2_3_tx_rx",
+ "uart3_0_tx_rx",
+ "uart3_1_tx_rx", "uart3_1_rts_cts",
+ "uart4_0_tx_rx",
+ "uart4_1_tx_rx", "uart4_1_rts_cts",
+ "uart4_2_tx_rx",
+ "uart4_2_rts_cts",};
+
+static const struct function_desc mt7622_functions[] = {
+ {"emmc", mt7622_emmc_groups, ARRAY_SIZE(mt7622_emmc_groups)},
+ {"eth", mt7622_ethernet_groups, ARRAY_SIZE(mt7622_ethernet_groups)},
+ {"i2c", mt7622_i2c_groups, ARRAY_SIZE(mt7622_i2c_groups)},
+ {"i2s", mt7622_i2s_groups, ARRAY_SIZE(mt7622_i2s_groups)},
+ {"ir", mt7622_ir_groups, ARRAY_SIZE(mt7622_ir_groups)},
+ {"led", mt7622_led_groups, ARRAY_SIZE(mt7622_led_groups)},
+ {"flash", mt7622_flash_groups, ARRAY_SIZE(mt7622_flash_groups)},
+ {"pcie", mt7622_pcie_groups, ARRAY_SIZE(mt7622_pcie_groups)},
+ {"pwm", mt7622_pwm_groups, ARRAY_SIZE(mt7622_pwm_groups)},
+ {"sd", mt7622_sd_groups, ARRAY_SIZE(mt7622_sd_groups)},
+ {"spi", mt7622_spic_groups, ARRAY_SIZE(mt7622_spic_groups)},
+ {"tdm", mt7622_tdm_groups, ARRAY_SIZE(mt7622_tdm_groups)},
+ {"uart", mt7622_uart_groups, ARRAY_SIZE(mt7622_uart_groups)},
+};
+
+static const struct pinconf_generic_params mtk_custom_bindings[] = {
+ {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0},
+ {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0},
+};
+
+#ifdef CONFIG_DEBUG_FS
+static const struct pin_config_item mtk_conf_items[] = {
+ PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
+ PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
+};
+#endif
+
+static const struct mtk_pin_soc mt7622_data = {
+ .reg_cal = mt7622_reg_cals,
+ .pins = mt7622_pins,
+ .npins = ARRAY_SIZE(mt7622_pins),
+ .grps = mt7622_groups,
+ .ngrps = ARRAY_SIZE(mt7622_groups),
+ .funcs = mt7622_functions,
+ .nfuncs = ARRAY_SIZE(mt7622_functions),
+};
+
+static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
+{
+ writel_relaxed(val, pctl->base + reg);
+}
+
+static u32 mtk_r32(struct mtk_pinctrl *pctl, u32 reg)
+{
+ return readl_relaxed(pctl->base + reg);
+}
+
+static void mtk_rmw(struct mtk_pinctrl *pctl, u32 reg, u32 mask, u32 set)
+{
+ u32 val;
+
+ val = mtk_r32(pctl, reg);
+ val &= ~mask;
+ val |= set;
+ mtk_w32(pctl, reg, val);
+}
+
+static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, int pin,
+ const struct mtk_pin_reg_calc *rc,
+ struct mtk_pin_field *pfd)
+{
+ const struct mtk_pin_field_calc *c, *e;
+ u32 bits;
+
+ c = rc->range;
+ e = c + rc->nranges;
+
+ while (c < e) {
+ if (pin >= c->s_pin && pin <= c->e_pin)
+ break;
+ c++;
+ }
+
+ if (c >= e) {
+ dev_err(hw->dev, "Out of range for pin = %d\n", pin);
+ return -EINVAL;
+ }
+
+ /* Caculated bits as the overall offset the pin is located at */
+ bits = c->s_bit + (pin - c->s_pin) * (c->x_bits);
+
+ /* Fill pfd from bits and 32-bit register applied is assumed */
+ pfd->offset = c->s_addr + c->x_addrs * (bits / 32);
+ pfd->bitpos = bits % 32;
+ pfd->mask = (1 << c->x_bits) - 1;
+
+ /* pfd->next is used for indicating that bit wrapping-around happens
+ * which requires the manipulation for bit 0 starting in the next
+ * register to form the complete field read/write.
+ */
+ pfd->next = pfd->bitpos + c->x_bits - 1 > 31 ? c->x_addrs : 0;
+
+ return 0;
+}
+
+static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw, int pin,
+ int field, struct mtk_pin_field *pfd)
+{
+ const struct mtk_pin_reg_calc *rc;
+
+ if (field < 0 || field >= PINCTRL_PIN_REG_MAX) {
+ dev_err(hw->dev, "Invalid Field %d\n", field);
+ return -EINVAL;
+ }
+
+ if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
+ rc = &hw->soc->reg_cal[field];
+ } else {
+ dev_err(hw->dev, "Undefined range for field %d\n", field);
+ return -EINVAL;
+ }
+
+ return mtk_hw_pin_field_lookup(hw, pin, rc, pfd);
+}
+
+static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
+{
+ *l = 32 - pf->bitpos;
+ *h = get_count_order(pf->mask) - *l;
+}
+
+static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
+ struct mtk_pin_field *pf, int value)
+{
+ int nbits_l, nbits_h;
+
+ mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+ mtk_rmw(hw, pf->offset, pf->mask << pf->bitpos,
+ (value & pf->mask) << pf->bitpos);
+
+ mtk_rmw(hw, pf->offset + pf->next, BIT(nbits_h) - 1,
+ (value & pf->mask) >> nbits_l);
+}
+
+static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
+ struct mtk_pin_field *pf, int *value)
+{
+ int nbits_l, nbits_h, h, l;
+
+ mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+ l = (mtk_r32(hw, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
+ h = (mtk_r32(hw, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
+
+ *value = (h << nbits_l) | l;
+}
+
+static int mtk_hw_set_value(struct mtk_pinctrl *hw, int pin, int field,
+ int value)
+{
+ struct mtk_pin_field pf;
+ int err;
+
+ err = mtk_hw_pin_field_get(hw, pin, field, &pf);
+ if (err)
+ return err;
+
+ if (!pf.next)
+ mtk_rmw(hw, pf.offset, pf.mask << pf.bitpos,
+ (value & pf.mask) << pf.bitpos);
+ else
+ mtk_hw_write_cross_field(hw, &pf, value);
+
+ return 0;
+}
+
+static int mtk_hw_get_value(struct mtk_pinctrl *hw, int pin, int field,
+ int *value)
+{
+ struct mtk_pin_field pf;
+ int err;
+
+ err = mtk_hw_pin_field_get(hw, pin, field, &pf);
+ if (err)
+ return err;
+
+ if (!pf.next)
+ *value = (mtk_r32(hw, pf.offset) >> pf.bitpos) & pf.mask;
+ else
+ mtk_hw_read_cross_field(hw, &pf, value);
+
+ return 0;
+}
+
+static int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int selector, unsigned int group)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ struct function_desc *func;
+ struct group_desc *grp;
+ int i;
+
+ func = pinmux_generic_get_function(pctldev, selector);
+ if (!func)
+ return -EINVAL;
+
+ grp = pinctrl_generic_get_group(pctldev, group);
+ if (!grp)
+ return -EINVAL;
+
+ dev_dbg(pctldev->dev, "enable function %s group %s\n",
+ func->name, grp->name);
+
+ for (i = 0; i < grp->num_pins; i++) {
+ int *pin_modes = grp->data;
+
+ mtk_hw_set_value(hw, grp->pins[i], PINCTRL_PIN_REG_MODE,
+ pin_modes[i]);
+ }
+
+ return 0;
+}
+
+static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+
+ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_MODE, MTK_GPIO_MODE);
+}
+
+static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin, bool input)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+
+ /* hardware would take 0 as input direction */
+ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR, !input);
+}
+
+static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ u32 param = pinconf_to_config_param(*config);
+ int val, val2, err, reg, ret = 1;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PU, &val);
+ if (err)
+ return err;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PD, &val2);
+ if (err)
+ return err;
+
+ if (val || val2)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_SLEW_RATE:
+ reg = (param == PIN_CONFIG_BIAS_PULL_UP) ?
+ PINCTRL_PIN_REG_PU :
+ (param == PIN_CONFIG_BIAS_PULL_DOWN) ?
+ PINCTRL_PIN_REG_PD : PINCTRL_PIN_REG_SR;
+
+ err = mtk_hw_get_value(hw, pin, reg, &val);
+ if (err)
+ return err;
+
+ if (!val)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val);
+ if (err)
+ return -EINVAL;
+
+ /* HW takes input mode as zero; output mode as non-zero */
+ if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
+ (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val);
+ if (err)
+ return err;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_SMT, &val2);
+ if (err)
+ return err;
+
+ if (val || !val2)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E4, &val);
+ if (err)
+ return -EINVAL;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E8, &val2);
+ if (err)
+ return -EINVAL;
+
+ /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
+ * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
+ */
+ ret = ((val2 << 1) + val + 1) * 4;
+
+ break;
+ case MTK_PIN_CONFIG_TDSEL:
+ case MTK_PIN_CONFIG_RDSEL:
+ reg = (param == MTK_PIN_CONFIG_TDSEL) ?
+ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
+
+ err = mtk_hw_get_value(hw, pin, reg, &val);
+ if (err)
+ return -EINVAL;
+
+ ret = val;
+
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, ret);
+
+ return 0;
+}
+
+static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ u32 reg, param, arg;
+ int cfg, err = 0;
+
+ for (cfg = 0; cfg < num_configs; cfg++) {
+ param = pinconf_to_config_param(configs[cfg]);
+ arg = pinconf_to_config_argument(configs[cfg]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 :
+ (param == PIN_CONFIG_BIAS_PULL_UP) ? 1 : 2;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PU,
+ arg & 1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PD,
+ !!(arg & 2));
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT,
+ MTK_DISABLE);
+ if (err)
+ goto err;
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_SLEW_RATE:
+ reg = (param == PIN_CONFIG_SLEW_RATE) ?
+ PINCTRL_PIN_REG_SR : PINCTRL_PIN_REG_DIR;
+
+ arg = (param == PIN_CONFIG_INPUT_ENABLE) ? 0 :
+ (param == PIN_CONFIG_OUTPUT_ENABLE) ? 1 : arg;
+ err = mtk_hw_set_value(hw, pin, reg, arg);
+ if (err)
+ goto err;
+
+ break;
+ case PIN_CONFIG_OUTPUT:
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR,
+ MTK_OUTPUT);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DO,
+ arg);
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ /* arg = 1: Input mode & SMT enable ;
+ * arg = 0: Output mode & SMT disable
+ */
+ arg = arg ? 2 : 1;
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR,
+ arg & 1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT,
+ !!(arg & 2));
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ /* 4mA when (e8, e4) = (0, 0);
+ * 8mA when (e8, e4) = (0, 1);
+ * 12mA when (e8, e4) = (1, 0);
+ * 16mA when (e8, e4) = (1, 1)
+ */
+ if (!(arg % 4) && (arg >= 4 && arg <= 16)) {
+ arg = arg / 4 - 1;
+ err = mtk_hw_set_value(hw, pin,
+ PINCTRL_PIN_REG_E4,
+ arg & 0x1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin,
+ PINCTRL_PIN_REG_E8,
+ (arg & 0x2) >> 1);
+ if (err)
+ goto err;
+ } else {
+ err = -ENOTSUPP;
+ }
+ break;
+ case MTK_PIN_CONFIG_TDSEL:
+ case MTK_PIN_CONFIG_RDSEL:
+ reg = (param == MTK_PIN_CONFIG_TDSEL) ?
+ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
+
+ err = mtk_hw_set_value(hw, pin, reg, arg);
+ if (err)
+ goto err;
+ break;
+ default:
+ err = -ENOTSUPP;
+ }
+ }
+err:
+ return err;
+}
+
+static int mtk_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *config)
+{
+ const unsigned int *pins;
+ unsigned int i, npins, old = 0;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ if (mtk_pinconf_get(pctldev, pins[i], config))
+ return -ENOTSUPP;
+
+ /* configs do not match between two pins */
+ if (i && old != *config)
+ return -ENOTSUPP;
+
+ old = *config;
+ }
+
+ return 0;
+}
+
+static int mtk_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *configs,
+ unsigned int num_configs)
+{
+ const unsigned int *pins;
+ unsigned int i, npins;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct pinctrl_ops mtk_pctlops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static const struct pinmux_ops mtk_pmxops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = mtk_pinmux_set_mux,
+ .gpio_request_enable = mtk_pinmux_gpio_request_enable,
+ .gpio_set_direction = mtk_pinmux_gpio_set_direction,
+ .strict = true,
+};
+
+static const struct pinconf_ops mtk_confops = {
+ .is_generic = true,
+ .pin_config_get = mtk_pinconf_get,
+ .pin_config_set = mtk_pinconf_set,
+ .pin_config_group_get = mtk_pinconf_group_get,
+ .pin_config_group_set = mtk_pinconf_group_set,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
+static struct pinctrl_desc mtk_desc = {
+ .name = PINCTRL_PINCTRL_DEV,
+ .pctlops = &mtk_pctlops,
+ .pmxops = &mtk_pmxops,
+ .confops = &mtk_confops,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent);
+ int value;
+
+ mtk_hw_get_value(hw, gpio, PINCTRL_PIN_REG_DI, &value);
+
+ return !!value;
+}
+
+static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
+{
+ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent);
+
+ mtk_hw_set_value(hw, gpio, PINCTRL_PIN_REG_DO, !!value);
+}
+
+static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
+{
+ return pinctrl_gpio_direction_input(chip->base + gpio);
+}
+
+static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
+ int value)
+{
+ mtk_gpio_set(chip, gpio, value);
+
+ return pinctrl_gpio_direction_output(chip->base + gpio);
+}
+
+static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
+{
+ struct gpio_chip *chip = &hw->chip;
+ int ret;
+
+ chip->label = PINCTRL_PINCTRL_DEV;
+ chip->parent = hw->dev;
+ chip->request = gpiochip_generic_request;
+ chip->free = gpiochip_generic_free;
+ chip->direction_input = mtk_gpio_direction_input;
+ chip->direction_output = mtk_gpio_direction_output;
+ chip->get = mtk_gpio_get;
+ chip->set = mtk_gpio_set;
+ chip->base = -1;
+ chip->ngpio = hw->soc->npins;
+ chip->of_node = np;
+ chip->of_gpio_n_cells = 2;
+
+ ret = gpiochip_add_data(chip, hw);
+ if (ret < 0)
+ return ret;
+
+ ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
+ chip->ngpio);
+ if (ret < 0) {
+ gpiochip_remove(chip);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_build_groups(struct mtk_pinctrl *hw)
+{
+ int err, i;
+
+ for (i = 0; i < hw->soc->ngrps; i++) {
+ const struct group_desc *group = hw->soc->grps + i;
+
+ err = pinctrl_generic_add_group(hw->pctrl, group->name,
+ group->pins, group->num_pins,
+ group->data);
+ if (err) {
+ dev_err(hw->dev, "Failed to register group %s\n",
+ group->name);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int mtk_build_functions(struct mtk_pinctrl *hw)
+{
+ int i, err;
+
+ for (i = 0; i < hw->soc->nfuncs ; i++) {
+ const struct function_desc *func = hw->soc->funcs + i;
+
+ err = pinmux_generic_add_function(hw->pctrl, func->name,
+ func->group_names,
+ func->num_group_names,
+ func->data);
+ if (err) {
+ dev_err(hw->dev, "Failed to register function %s\n",
+ func->name);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pinctrl_of_match[] = {
+ { .compatible = "mediatek,mt7622-pinctrl", .data = &mt7622_data},
+ { }
+};
+
+static int mtk_pinctrl_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct mtk_pinctrl *hw;
+ const struct of_device_id *of_id =
+ of_match_device(mtk_pinctrl_of_match, &pdev->dev);
+ int err;
+
+ hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM;
+
+ hw->soc = of_id->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "missing IO resource\n");
+ return -ENXIO;
+ }
+
+ hw->dev = &pdev->dev;
+ hw->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hw->base))
+ return PTR_ERR(hw->base);
+
+ /* Setup pins descriptions per SoC types */
+ mtk_desc.pins = hw->soc->pins;
+ mtk_desc.npins = hw->soc->npins;
+ mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
+ mtk_desc.custom_params = mtk_custom_bindings;
+#ifdef CONFIG_DEBUG_FS
+ mtk_desc.custom_conf_items = mtk_conf_items;
+#endif
+
+ hw->pctrl = devm_pinctrl_register(&pdev->dev, &mtk_desc, hw);
+ if (IS_ERR(hw->pctrl))
+ return PTR_ERR(hw->pctrl);
+
+ /* Setup groups descriptions per SoC types */
+ err = mtk_build_groups(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to build groups\n");
+ return 0;
+ }
+
+ /* Setup functions descriptions per SoC types */
+ err = mtk_build_functions(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to build functions\n");
+ return err;
+ }
+
+ err = mtk_build_gpiochip(hw, pdev->dev.of_node);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to add gpio_chip\n");
+ return err;
+ }
+
+ platform_set_drvdata(pdev, hw);
+
+ return 0;
+}
+
+static struct platform_driver mtk_pinctrl_driver = {
+ .driver = {
+ .name = "mtk-pinctrl",
+ .of_match_table = mtk_pinctrl_of_match,
+ },
+ .probe = mtk_pinctrl_probe,
+};
+
+static int __init mtk_pinctrl_init(void)
+{
+ return platform_driver_register(&mtk_pinctrl_driver);
+}
+arch_initcall(mtk_pinctrl_init);
--
2.7.4
^ permalink raw reply related
* [PATCH 2/4] pinctrl: mediatek: cleanup for placing all drivers under the menu
From: sean.wang @ 2017-11-28 3:50 UTC (permalink / raw)
To: robh+dt, mark.rutland, linus.walleij, matthias.bgg, devicetree,
linux-mediatek
Cc: linux-arm-kernel, linux-gpio, linux-kernel, Sean Wang
In-Reply-To: <cover.1511840374.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
Since lots of MediaTek drivers had been added, it seems slightly better
for that adding cleanup for placing MediaTek pinctrl drivers under the
independent menu as other kinds of drivers usually was done.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index fac9866..03b3023 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -1,4 +1,5 @@
-if ARCH_MEDIATEK || COMPILE_TEST
+menu "MediaTek pinctrl drivers"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
config PINCTRL_MTK
bool
@@ -46,4 +47,4 @@ config PINCTRL_MT6397
default MFD_MT6397
select PINCTRL_MTK
-endif
+endmenu
--
2.7.4
^ permalink raw reply related
* [PATCH 1/4] dt-bindings: pinctrl: add bindings for MediaTek MT7622 SoC
From: sean.wang-NuS5LvNUpcJWk0Htik3J/w @ 2017-11-28 3:49 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sean Wang
In-Reply-To: <cover.1511840374.git.sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
From: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Add devicetree bindings for MediaTek MT7622 pinctrl driver.
Signed-off-by: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
.../devicetree/bindings/pinctrl/pinctrl-mt7622.txt | 330 +++++++++++++++++++++
1 file changed, 330 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
new file mode 100644
index 0000000..ce86d45
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
@@ -0,0 +1,330 @@
+== MediaTek MT7622 pinctrl controller ==
+
+Required properties for the root node:
+ - compatible: Should be one of the following
+ "mediatek,mt7622-pinctrl" for MT7622 SoC
+ - reg: offset and length of the pinctrl space
+
+ - gpio-controller: Marks the device node as a GPIO controller.
+ - #gpio-cells: Should be two. The first cell is the pin number and the
+ second is the GPIO flags.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+MT7622 pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, slew rate, etc.
+
+We support 2 types of configuration nodes. Those nodes can be either pinmux
+nodes or pinconf nodes. Each configuration node can consist of multiple nodes
+describing the pinmux and pinconf options.
+
+The name of each subnode is no matter as long as it is unique; all subnodes
+should be enumerated and processed purely based on their content.
+
+== pinmux nodes content ==
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pinmux subnode:
+
+Required properties are:
+ - groups: An array of strings. Each string contains the name of a group.
+ Valid values for these names are listed below.
+ - function: A string containing the name of the function to mux to the
+ group. Valid values for function names are listed below.
+
+== pinconf nodes content ==
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pinconf subnode:
+
+Required properties are:
+ - pins: An array of strings. Each string contains the name of a pin.
+ Valid values for these names are listed below.
+ - groups: An array of strings. Each string contains the name of a group.
+ Valid values for these names are listed below.
+
+Optional properies are:
+ bias-disable, bias-pull, bias-pull-down, input-enable,
+ input-schmitt-enable, input-schmitt-disable, output-enable
+ output-low, output-high, drive-strength, slew-rate
+
+ Valid arguments for 'slew-rate' are '0' and '1' to select between slow and
+ fast respectively.
+ Valid arguments for 'drive-strength', 4, 8, 12, or 16 in mA.
+
+The following specific properties as defined are valid to specify in a pinconf
+subnode:
+
+Optional properties are:
+ - mediatek,tdsel: Valid arguments are from 0 to 15
+ - mediatek,rdsel: Valid arguments are from 0 to 63
+
+== Valid values for pins, function and groups on MT7622 ==
+
+Valid values for pins are:
+pins can be referenced via the pin names as the below table shown and the
+related physical number is also put ahead of those names which helps cross
+references to pins between groups to know whether pins assignment conflict
+happens among devices try to acquire those available pins.
+
+ Pin #: Valid values for pins
+ -----------------------------
+ PIN 0: "GPIO_A"
+ PIN 1: "I2S1_IN"
+ PIN 2: "I2S1_OUT"
+ PIN 3: "I2S_BCLK"
+ PIN 4: "I2S_WS"
+ PIN 5: "I2S_MCLK"
+ PIN 6: "TXD0"
+ PIN 7: "RXD0"
+ PIN 8: "SPI_WP"
+ PIN 9: "SPI_HOLD"
+ PIN 10: "SPI_CLK"
+ PIN 11: "SPI_MOSI"
+ PIN 12: "SPI_MISO"
+ PIN 13: "SPI_CS"
+ PIN 14: "SPI_SDA"
+ PIN 15: "SPI_SCL"
+ PIN 16: "I2S2_IN"
+ PIN 17: "I2S3_IN"
+ PIN 18: "I2S4_IN"
+ PIN 19: "I2S2_OUT"
+ PIN 20: "I2S3_OUT"
+ PIN 21: "I2S4_OUT"
+ PIN 22: "GPIO_B"
+ PIN 23: "MDC"
+ PIN 24: "MDIO"
+ PIN 25: "G2_TXD0"
+ PIN 26: "G2_TXD1"
+ PIN 27: "G2_TXD2"
+ PIN 28: "G2_TXD3"
+ PIN 29: "G2_TXEN"
+ PIN 30: "G2_TXC"
+ PIN 31: "G2_RXD0"
+ PIN 32: "G2_RXD1"
+ PIN 33: "G2_RXD2"
+ PIN 34: "G2_RXD3"
+ PIN 35: "G2_RXDV"
+ PIN 36: "G2_RXC"
+ PIN 37: "NCEB"
+ PIN 38: "NWEB"
+ PIN 39: "NREB"
+ PIN 40: "NDL4"
+ PIN 41: "NDL5"
+ PIN 42: "NDL6"
+ PIN 43: "NDL7"
+ PIN 44: "NRB"
+ PIN 45: "NCLE"
+ PIN 46: "NALE"
+ PIN 47: "NDL0"
+ PIN 48: "NDL1"
+ PIN 49: "NDL2"
+ PIN 50: "NDL3"
+ PIN 51: "MDI_TP_P0"
+ PIN 52: "MDI_TN_P0"
+ PIN 53: "MDI_RP_P0"
+ PIN 54: "MDI_RN_P0"
+ PIN 55: "MDI_TP_P1"
+ PIN 56: "MDI_TN_P1"
+ PIN 57: "MDI_RP_P1"
+ PIN 58: "MDI_RN_P1"
+ PIN 59: "MDI_RP_P2"
+ PIN 60: "MDI_RN_P2"
+ PIN 61: "MDI_TP_P2"
+ PIN 62: "MDI_TN_P2"
+ PIN 63: "MDI_TP_P3"
+ PIN 64: "MDI_TN_P3"
+ PIN 65: "MDI_RP_P3"
+ PIN 66: "MDI_RN_P3"
+ PIN 67: "MDI_RP_P4"
+ PIN 68: "MDI_RN_P4"
+ PIN 69: "MDI_TP_P4"
+ PIN 70: "MDI_TN_P4"
+ PIN 71: "SPI2_CK"
+ PIN 72: "SPI2_DATA"
+ PIN 73: "SPIC1_CLK"
+ PIN 74: "SPIC1_MOSI"
+ PIN 75: "SPIC1_MISO"
+ PIN 76: "SPIC1_CS"
+ PIN 77: "GPIO_D"
+ PIN 78: "WATCHDOG"
+ PIN 79: "RTS3_N"
+ PIN 80: "CTS3_N"
+ PIN 81: "TXD3"
+ PIN 82: "RXD3"
+ PIN 83: "PERST0_N"
+ PIN 84: "PERST1_N"
+ PIN 85: "WLED_N"
+ PIN 86: "EPHY_LED0_N"
+ PIN 87: "AUXIN0"
+ PIN 88: "AUXIN1"
+ PIN 89: "AUXIN2"
+ PIN 90: "AUXIN3"
+ PIN 91: "TXD4"
+ PIN 92: "RXD4"
+ PIN 93: "RTS4_IN"
+ PIN 94: "CST4_IN"
+ PIN 95: "PWM1"
+ PIN 96: "PWM2"
+ PIN 97: "PWM3"
+ PIN 98: "PWM4"
+ PIN 99: "PWM5"
+ PIN 100: "PWM6"
+ PIN 101: "PWM7"
+ PIN 102: "GPIO_E"
+
+Valid values for function are:
+ "emmc", "eth", "i2c", "i2s", "ir", "led", "flash", "pcie",
+ "pwm", "sd", "spi", "tdm", "uart"
+
+Valid values for groups are:
+additional data is put followingly with valid value allowing us to know which
+applicable function and which relevant pins (in pin#) are able applied for that
+group.
+
+ Valid value function pins (in pin#)
+ -------------------------------------------------------------------------
+ "emmc" "emmc" 40, 41, 42, 43, 44, 45,
+ 47, 48, 49, 50
+ "esw" "eth" 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70
+ "mdc_mdio" "eth" 23, 24
+ "gmac1" "eth" 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70
+ "gmac2" "eth" 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36
+ "i2c0" "i2c" 14, 15
+ "i2c1_0" "i2c" 55, 56
+ "i2c1_1" "i2c" 73, 74
+ "i2c1_2" "i2c" 87, 88
+ "i2c2_0" "i2c" 57, 58
+ "i2c2_1" "i2c" 75, 76
+ "i2c2_2" "i2c" 89, 90
+ "i2s_in_bclk_ws_mclk" "i2s" 3, 4, 5
+ "i2s1_in_data" "i2s" 1
+ "i2s2_in_data" "i2s" 16
+ "i2s3_in_data" "i2s" 17
+ "i2s4_in_data" "i2s" 18
+ "i2s_out_bclk_ws_mclk" "i2s" 3, 4, 5
+ "i2s1_out_data" "i2s" 2
+ "i2s2_out_data" "i2s" 19
+ "i2s3_out_data" "i2s" 20
+ "i2s4_out_data" "i2s" 21
+ "ir_0_tx" "ir" 16
+ "ir_1_tx" "ir" 59
+ "ir_2_tx" "ir" 99
+ "ir_0_rx" "ir" 17
+ "ir_1_rx" "ir" 60
+ "ir_2_rx" "ir" 100
+ "ephy0_led" "led" 86
+ "ephy1_led" "led" 91
+ "ephy2_led" "led" 92
+ "ephy3_led" "led" 93
+ "ephy4_led" "led" 94
+ "wled" "led" 85
+ "par_nand" "flash" 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48,
+ 49, 50
+ "snfi" "flash" 8, 9, 10, 11, 12, 13
+ "spi_nor" "flash" 8, 9, 10, 11, 12, 13
+ "pcie0_0_waken_clkreq" "pcie" 14, 15
+ "pcie0_1_waken_clkreq" "pcie" 79, 80
+ "pcie1_0_waken_clkreq" "pcie" 14, 15
+ "pcie0_pad_perst" "pcie" 83
+ "pcie1_pad_perst" "pcie" 84
+ "pwm_ch1_0" "pwm" 51
+ "pwm_ch1_1" "pwm" 73
+ "pwm_ch1_2" "pwm" 95
+ "pwm_ch2_0" "pwm" 52
+ "pwm_ch2_1" "pwm" 74
+ "pwm_ch2_2" "pwm" 96
+ "pwm_ch3_0" "pwm" 53
+ "pwm_ch3_1" "pwm" 75
+ "pwm_ch3_2" "pwm" 97
+ "pwm_ch4_0" "pwm" 54
+ "pwm_ch4_1" "pwm" 67
+ "pwm_ch4_2" "pwm" 76
+ "pwm_ch4_3" "pwm" 98
+ "pwm_ch5_0" "pwm" 68
+ "pwm_ch5_1" "pwm" 77
+ "pwm_ch5_2" "pwm" 99
+ "pwm_ch6_0" "pwm" 69
+ "pwm_ch6_1" "pwm" 78
+ "pwm_ch6_2" "pwm" 81
+ "pwm_ch6_3" "pwm" 100
+ "pwm_ch7_0" "pwm" 70
+ "pwm_ch7_1" "pwm" 82
+ "pwm_ch7_2" "pwm" 101
+ "sd_0" "sd" 16, 17, 18, 19, 20, 21
+ "sd_1" "sd" 25, 26, 27, 28, 29, 30
+ "spic0_0" "spi" 63, 64, 65, 66
+ "spic0_1" "spi" 79, 80, 81, 82
+ "spic1_0" "spi" 67, 68, 69, 70
+ "spic1_1" "spi" 73, 74, 75, 76
+ "tdm_0_out_mclk_bclk" "tdm" 8, 9, 10
+ "tdm_0_in_mclk_bclk_ws" "tdm" 11, 12, 13
+ "tdm_0_out_data" "tdm" 20
+ "tdm_0_in_data" "tdm" 21
+ "tdm_1_out_mclk_bclk" "tdm" 57, 58, 59
+ "tdm_1_in_mclk_bclk_ws" "tdm" 60, 61, 62
+ "tdm_1_out_data" "tdm" 55
+ "tdm_1_in_data" "tdm" 56
+ "uart0_0_tx_rx" "uart" 6, 7
+ "uart1_0_tx_rx" "uart" 55, 56
+ "uart1_0_rts_cts" "uart" 57, 58
+ "uart1_1_tx_rx" "uart" 73, 74
+ "uart1_1_rts_cts" "uart" 75, 76
+ "uart2_0_tx_rx" "uart" 3, 4
+ "uart2_0_rts_cts" "uart" 1, 2
+ "uart2_1_tx_rx" "uart" 51, 52
+ "uart2_1_rts_cts" "uart" 53, 54
+ "uart2_2_tx_rx" "uart" 59, 60
+ "uart2_2_rts_cts" "uart" 61, 62
+ "uart2_3_tx_rx" "uart" 95, 96
+ "uart3_0_tx_rx" "uart" 57, 58
+ "uart3_1_tx_rx" "uart" 81, 82
+ "uart3_1_rts_cts" "uart" 79, 80
+ "uart4_0_tx_rx" "uart" 61, 62
+ "uart4_1_tx_rx" "uart" 91, 92
+ "uart4_1_rts_cts" "uart" 93, 94
+ "uart4_2_tx_rx" "uart" 97, 98
+ "uart4_2_rts_cts" "uart" 95, 96
+
+Example:
+
+ pio: pinctrl@10211000 {
+ compatible = "mediatek,mt7622-pinctrl";
+ reg = <0 0x10211000 0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ pinctrl_eth_default: eth-default {
+ mux_mdio {
+ groups = "mdc_mdio";
+ function = "eth";
+ drive-strength = <12>;
+ };
+
+ mux_gmac2 {
+ groups = "gmac2";
+ function = "eth";
+ drive-strength = <12>;
+ };
+
+ mux_esw {
+ groups = "esw";
+ function = "eth";
+ drive-strength = <8>;
+ };
+
+ conf_mdio {
+ pins = "MDC";
+ bias-pull-up;
+ };
+ };
+ };
--
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
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