* [v3, 5/7] mmc: sdhci-of-esdhc: add delay between tuning cycles
From: Yangbo Lu @ 2017-03-27 7:49 UTC (permalink / raw)
To: linux-mmc, devicetree, linux-arm-kernel, ulf.hansson,
Adrian Hunter, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1490600982-5410-1-git-send-email-yangbo.lu@nxp.com>
It's observed that eSDHC needed delay between tuning cycles for
HS200 successful tuning. This patch is to set 1ms delay for that.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None
Changes for v3:
- Used a host member for tuning delay instead of a quirk.
---
drivers/mmc/host/sdhci-of-esdhc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 8c8e147..0754ef4 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -807,6 +807,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
host->mmc_host_ops.start_signal_voltage_switch =
esdhc_signal_voltage_switch;
host->mmc_host_ops.execute_tuning = esdhc_execute_tuning;
+ host->tuning_delay = 1;
esdhc_init(pdev, host);
--
2.1.0.27.g96db324
^ permalink raw reply related
* [v3, 4/7] mmc: sdhci: Control the delay between tuning commands
From: Yangbo Lu @ 2017-03-27 7:49 UTC (permalink / raw)
To: linux-mmc, devicetree, linux-arm-kernel, ulf.hansson,
Adrian Hunter, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1490600982-5410-1-git-send-email-yangbo.lu@nxp.com>
From: Adrian Hunter <adrian.hunter@intel.com>
The delay between tuning commands for SD cards is not part of the
specification. A driver that needs it probably needs it for eMMC
too, whereas most drivers would probably like to set it to 0. Make
it a host member (host->tuning_delay) that defaults to the existing
behaviour. Drivers can set it to zero to eliminate the delay, or
set it to a positive value to always have a delay.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None
Changes for v3:
- Used a host member for tuning delay instead of a quirk.(Adrian's patch)
- Addressed warning in checkpatch.
---
drivers/mmc/host/sdhci.c | 11 ++++++++---
drivers/mmc/host/sdhci.h | 2 ++
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0d4485d..ffd1607 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2100,9 +2100,9 @@ static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
break;
}
- /* eMMC spec does not require a delay between tuning cycles */
- if (opcode == MMC_SEND_TUNING_BLOCK)
- mdelay(1);
+ /* Spec does not require a delay between tuning cycles */
+ if (host->tuning_delay > 0)
+ mdelay(host->tuning_delay);
}
pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
@@ -2164,6 +2164,9 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
host->mmc->retune_period = tuning_count;
+ if (host->tuning_delay < 0)
+ host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK;
+
sdhci_start_tuning(host);
__sdhci_execute_tuning(host, opcode);
@@ -3108,6 +3111,8 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev,
host->cqe_ier = SDHCI_CQE_INT_MASK;
host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK;
+ host->tuning_delay = -1;
+
return host;
}
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index fdb5d7e..2407960 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -538,6 +538,8 @@ struct sdhci_host {
#define SDHCI_TUNING_MODE_1 0
#define SDHCI_TUNING_MODE_2 1
#define SDHCI_TUNING_MODE_3 2
+ /* Delay (ms) between tuning commands */
+ int tuning_delay;
unsigned long private[0] ____cacheline_aligned;
};
--
2.1.0.27.g96db324
^ permalink raw reply related
* [v3, 3/7] mmc: sdhci-of-esdhc: add tuning support
From: Yangbo Lu @ 2017-03-27 7:49 UTC (permalink / raw)
To: linux-mmc, devicetree, linux-arm-kernel, ulf.hansson,
Adrian Hunter, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1490600982-5410-1-git-send-email-yangbo.lu@nxp.com>
eSDHC uses tuning block for tuning procedure. So the tuning
block control register must be configured properly before tuning.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- Replaced old function for mmc_host_ops.execute_tuning with
esdhc_execute_tuning to support eSDHC tuning.
Changes for v3:
- Put .execute_tuning assigning after after IS_ERR(host) check.
---
drivers/mmc/host/sdhci-esdhc.h | 5 +++++
drivers/mmc/host/sdhci-of-esdhc.c | 20 ++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index 6869567..c4bbd74 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -53,9 +53,14 @@
#define ESDHC_CLOCK_HCKEN 0x00000002
#define ESDHC_CLOCK_IPGEN 0x00000001
+/* Tuning Block Control Register */
+#define ESDHC_TBCTL 0x120
+#define ESDHC_TB_EN 0x00000004
+
/* Control Register for DMA transfer */
#define ESDHC_DMA_SYSCTL 0x40c
#define ESDHC_PERIPHERAL_CLK_SEL 0x00080000
+#define ESDHC_FLUSH_ASYNC_FIFO 0x00040000
#define ESDHC_DMA_SNOOP 0x00000040
#endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index a70499a..8c8e147 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -630,6 +630,25 @@ static int esdhc_signal_voltage_switch(struct mmc_host *mmc,
}
}
+static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u32 val;
+
+ /* Use tuning block for tuning procedure */
+ esdhc_clock_enable(host, false);
+ val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
+ val |= ESDHC_FLUSH_ASYNC_FIFO;
+ sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
+
+ val = sdhci_readl(host, ESDHC_TBCTL);
+ val |= ESDHC_TB_EN;
+ sdhci_writel(host, val, ESDHC_TBCTL);
+ esdhc_clock_enable(host, true);
+
+ return sdhci_execute_tuning(mmc, opcode);
+}
+
#ifdef CONFIG_PM_SLEEP
static u32 esdhc_proctl;
static int esdhc_of_suspend(struct device *dev)
@@ -787,6 +806,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
host->mmc_host_ops.start_signal_voltage_switch =
esdhc_signal_voltage_switch;
+ host->mmc_host_ops.execute_tuning = esdhc_execute_tuning;
esdhc_init(pdev, host);
--
2.1.0.27.g96db324
^ permalink raw reply related
* [v3, 2/7] mmc: sdhci-of-esdhc: add support for signal voltage switch
From: Yangbo Lu @ 2017-03-27 7:49 UTC (permalink / raw)
To: linux-mmc, devicetree, linux-arm-kernel, ulf.hansson,
Adrian Hunter, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1490600982-5410-1-git-send-email-yangbo.lu@nxp.com>
eSDHC supports signal voltage switch from 3.3v to 1.8v by
eSDHC_PROCTL[VOLT_SEL] bit. This bit changes the value of output
signal SDHC_VS, and there must be a control circuit out of eSDHC
to change the signal voltage according to SDHC_VS output signal.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- Used Adrain's method to support voltage switching:
host->mmc_host_ops.start_signal_voltage_switch =
esdhc_signal_voltage_switch;
Changes for v3:
- Put .start_signal_voltage_switch assigning after IS_ERR(host) check.
---
drivers/mmc/host/sdhci-esdhc.h | 1 +
drivers/mmc/host/sdhci-of-esdhc.c | 74 +++++++++++++++++++++++++++++++++++++++
2 files changed, 75 insertions(+)
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index 5343fc0..6869567 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -37,6 +37,7 @@
/* Protocol Control Register */
#define ESDHC_PROCTL 0x28
+#define ESDHC_VOLT_SEL 0x00000400
#define ESDHC_CTRL_4BITBUS (0x1 << 1)
#define ESDHC_CTRL_8BITBUS (0x2 << 1)
#define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 7ce1caf..a70499a 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -16,6 +16,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/sys_soc.h>
@@ -559,6 +560,76 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
}
+/* The SCFG, Supplemental Configuration Unit, provides SoC specific
+ * configuration and status registers for the device. There is a
+ * SDHC IO VSEL control register on SCFG for some platforms. It's
+ * used to support SDHC IO voltage switching.
+ */
+static const struct of_device_id scfg_device_ids[] = {
+ { .compatible = "fsl,t1040-scfg", },
+ { .compatible = "fsl,ls1012a-scfg", },
+ { .compatible = "fsl,ls1046a-scfg", },
+ {}
+};
+
+/* SDHC IO VSEL control register definition */
+#define SCFG_SDHCIOVSELCR 0x408
+#define SDHCIOVSELCR_TGLEN 0x80000000
+#define SDHCIOVSELCR_VSELVAL 0x60000000
+#define SDHCIOVSELCR_SDHC_VS 0x00000001
+
+static int esdhc_signal_voltage_switch(struct mmc_host *mmc,
+ struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct device_node *scfg_node;
+ void __iomem *scfg_base = NULL;
+ u32 sdhciovselcr;
+ u32 val;
+
+ /*
+ * Signal Voltage Switching is only applicable for Host Controllers
+ * v3.00 and above.
+ */
+ if (host->version < SDHCI_SPEC_300)
+ return 0;
+
+ val = sdhci_readl(host, ESDHC_PROCTL);
+
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ val &= ~ESDHC_VOLT_SEL;
+ sdhci_writel(host, val, ESDHC_PROCTL);
+ return 0;
+ case MMC_SIGNAL_VOLTAGE_180:
+ scfg_node = of_find_matching_node(NULL, scfg_device_ids);
+ if (scfg_node)
+ scfg_base = of_iomap(scfg_node, 0);
+ if (scfg_base) {
+ sdhciovselcr = SDHCIOVSELCR_TGLEN |
+ SDHCIOVSELCR_VSELVAL;
+ iowrite32be(sdhciovselcr,
+ scfg_base + SCFG_SDHCIOVSELCR);
+
+ val |= ESDHC_VOLT_SEL;
+ sdhci_writel(host, val, ESDHC_PROCTL);
+ mdelay(5);
+
+ sdhciovselcr = SDHCIOVSELCR_TGLEN |
+ SDHCIOVSELCR_SDHC_VS;
+ iowrite32be(sdhciovselcr,
+ scfg_base + SCFG_SDHCIOVSELCR);
+ iounmap(scfg_base);
+ } else {
+ val |= ESDHC_VOLT_SEL;
+ sdhci_writel(host, val, ESDHC_PROCTL);
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
#ifdef CONFIG_PM_SLEEP
static u32 esdhc_proctl;
static int esdhc_of_suspend(struct device *dev)
@@ -714,6 +785,9 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
if (IS_ERR(host))
return PTR_ERR(host);
+ host->mmc_host_ops.start_signal_voltage_switch =
+ esdhc_signal_voltage_switch;
+
esdhc_init(pdev, host);
sdhci_get_of_property(pdev);
--
2.1.0.27.g96db324
^ permalink raw reply related
* [v3, 1/7] mmc: sdhci-of-esdhc: add peripheral clock support
From: Yangbo Lu @ 2017-03-27 7:49 UTC (permalink / raw)
To: linux-mmc, devicetree, linux-arm-kernel, ulf.hansson,
Adrian Hunter, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1490600982-5410-1-git-send-email-yangbo.lu@nxp.com>
eSDHC could select peripheral clock or platform clock as clock source by
the PCS bit of eSDHC Control Register, and this bit couldn't be reset by
software reset for all. In default, the platform clock is used. But we have
to use peripheral clock since it has a higher frequency to support eMMC
HS200 mode and SD UHS-I mode. This patch is to add peripheral clock support
and use it instead of platform clock if it's declared in eSDHC dts node.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None
Changes for v3:
- None
---
drivers/mmc/host/sdhci-esdhc.h | 1 +
drivers/mmc/host/sdhci-of-esdhc.c | 70 +++++++++++++++++++++++++++++++++++++--
2 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index ece8b37..5343fc0 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -54,6 +54,7 @@
/* Control Register for DMA transfer */
#define ESDHC_DMA_SYSCTL 0x40c
+#define ESDHC_PERIPHERAL_CLK_SEL 0x00080000
#define ESDHC_DMA_SNOOP 0x00000040
#endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index ff37e74..7ce1caf 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/sys_soc.h>
+#include <linux/clk.h>
#include <linux/mmc/host.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -30,6 +31,7 @@ struct sdhci_esdhc {
u8 vendor_ver;
u8 spec_ver;
bool quirk_incorrect_hostver;
+ unsigned int peripheral_clock;
};
/**
@@ -414,15 +416,25 @@ static int esdhc_of_enable_dma(struct sdhci_host *host)
static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
- return pltfm_host->clock;
+ if (esdhc->peripheral_clock)
+ return esdhc->peripheral_clock;
+ else
+ return pltfm_host->clock;
}
static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
+ unsigned int clock;
- return pltfm_host->clock / 256 / 16;
+ if (esdhc->peripheral_clock)
+ clock = esdhc->peripheral_clock;
+ else
+ clock = pltfm_host->clock;
+ return clock / 256 / 16;
}
static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
@@ -512,6 +524,33 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
sdhci_writel(host, ctrl, ESDHC_PROCTL);
}
+static void esdhc_clock_enable(struct sdhci_host *host, bool enable)
+{
+ u32 val;
+ u32 timeout;
+
+ val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+
+ if (enable)
+ val |= ESDHC_CLOCK_SDCLKEN;
+ else
+ val &= ~ESDHC_CLOCK_SDCLKEN;
+
+ sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL);
+
+ timeout = 20;
+ val = ESDHC_CLOCK_STABLE;
+ while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) {
+ if (timeout == 0) {
+ pr_err("%s: Internal clock never stabilised.\n",
+ mmc_hostname(host->mmc));
+ break;
+ }
+ timeout--;
+ mdelay(1);
+ }
+}
+
static void esdhc_reset(struct sdhci_host *host, u8 mask)
{
sdhci_reset(host, mask);
@@ -613,6 +652,9 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_esdhc *esdhc;
+ struct device_node *np;
+ struct clk *clk;
+ u32 val;
u16 host_ver;
pltfm_host = sdhci_priv(host);
@@ -626,6 +668,30 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
esdhc->quirk_incorrect_hostver = true;
else
esdhc->quirk_incorrect_hostver = false;
+
+ np = pdev->dev.of_node;
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk)) {
+ /*
+ * esdhc->peripheral_clock would be assigned with a value
+ * which is eSDHC base clock when use periperal clock.
+ * For ls1046a, the clock value got by common clk API is
+ * peripheral clock while the eSDHC base clock is 1/2
+ * peripheral clock.
+ */
+ if (of_device_is_compatible(np, "fsl,ls1046a-esdhc"))
+ esdhc->peripheral_clock = clk_get_rate(clk) / 2;
+ else
+ esdhc->peripheral_clock = clk_get_rate(clk);
+ }
+
+ if (esdhc->peripheral_clock) {
+ esdhc_clock_enable(host, false);
+ val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
+ val |= ESDHC_PERIPHERAL_CLK_SEL;
+ sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
+ esdhc_clock_enable(host, true);
+ }
}
static int sdhci_esdhc_probe(struct platform_device *pdev)
--
2.1.0.27.g96db324
^ permalink raw reply related
* [v3, 0/7] Add SD UHS-I and eMMC HS200 support for eSDHC
From: Yangbo Lu @ 2017-03-27 7:49 UTC (permalink / raw)
To: linux-mmc, devicetree, linux-arm-kernel, ulf.hansson,
Adrian Hunter, Rob Herring, Mark Rutland, Catalin Marinas,
Will Deacon
Cc: Xiaobo Xie, Yangbo Lu
It's complicated to support SD UHS-I and eMMC HS200 for eSDHC because
there're many differences between eSDHC and SD/eMMC spec. Several
differences as below must be considered:
1. Peripheral clock must be used instead of platform clock.
- eSDHC could select peripheral clock or platform clock as its clock
source. According to RM, UHS-I/HS200 must use peripheral clock since
it supports higher frequency than platform clock.
- Patch 1 and patch 6 is to support this.
2. Signal voltage switching requires a control circuit out of eSDHC.
- eSDHC supports signal voltage switch from 3.3v to 1.8v by
eSDHC_PROCTL[VOLT_SEL] bit. This bit changes the value of output
signal SDHC_VS, and there must be a control circuit out of eSDHC
to change the signal voltage according to SDHC_VS output signal.
- Patch 2 is to support this.
3. eSDHC uses tuning block for tuning procedure.
- Tuning clock control register must be configured before tuning.
- Patch 3 is to support this.
4. Delay is needed between tuning cycles for HS200 tuning.
- Once a patch removed mdelay between tuning cycles.
But eSDHC needs it.
- Patch 4 and patch 5 is to support this.
5. UHS-I/HS200 modes could be enabled in dts node.
- Patch 7 is to support this.
Please review and merge these patches on mmc git tree if no changes
are required.
Adrian Hunter (1):
mmc: sdhci: Control the delay between tuning commands
Yangbo Lu (6):
mmc: sdhci-of-esdhc: add peripheral clock support
mmc: sdhci-of-esdhc: add support for signal voltage switch
mmc: sdhci-of-esdhc: add tuning support
mmc: sdhci-of-esdhc: add delay between tuning cycles
arm64: dts: ls1046a: add clocks property and compatible for eSDHC node
arm64: dts: ls1046ardb: add MMC HS200/UHS-1 modes support
arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts | 8 ++
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 3 +-
drivers/mmc/host/sdhci-esdhc.h | 7 +
drivers/mmc/host/sdhci-of-esdhc.c | 165 +++++++++++++++++++++-
drivers/mmc/host/sdhci.c | 11 +-
drivers/mmc/host/sdhci.h | 2 +
6 files changed, 190 insertions(+), 6 deletions(-)
--
2.1.0.27.g96db324
^ permalink raw reply
* [PATCH V5 1/4] arm64: dts: Add basic DT to support Spreadtrum's SP9860G
From: Chunyan Zhang @ 2017-03-27 7:32 UTC (permalink / raw)
To: robh+dt, mark.rutland, gregkh, catalin.marinas, will.deacon, arnd
Cc: mathieu.poirier, orson.zhai, linux-kernel, devicetree,
linux-arm-kernel, zhang.lyra, chunyan.zhang
In-Reply-To: <1490594208-26897-1-git-send-email-chunyan.zhang@spreadtrum.com>
From: Orson Zhai <orson.zhai@spreadtrum.com>
SC9860G is a 8 cores of A53 SoC with 4G LTE support SoC from Spreadtrum.
According to regular hierarchy of sprd dts, whale2.dtsi contains SoC
peripherals IP nodes, sc9860.dtsi contains stuff related to ARM core stuff
and sp9860g dts is for the board level.
Signed-off-by: Orson Zhai <orson.zhai@spreadtrum.com>
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
arch/arm64/boot/dts/sprd/Makefile | 3 +-
arch/arm64/boot/dts/sprd/sc9860.dtsi | 569 ++++++++++++++++++++++++++++++
arch/arm64/boot/dts/sprd/sp9860g-1h10.dts | 56 +++
arch/arm64/boot/dts/sprd/whale2.dtsi | 71 ++++
4 files changed, 698 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/boot/dts/sprd/sc9860.dtsi
create mode 100644 arch/arm64/boot/dts/sprd/sp9860g-1h10.dts
create mode 100644 arch/arm64/boot/dts/sprd/whale2.dtsi
diff --git a/arch/arm64/boot/dts/sprd/Makefile b/arch/arm64/boot/dts/sprd/Makefile
index b658c5e..f0535e6 100644
--- a/arch/arm64/boot/dts/sprd/Makefile
+++ b/arch/arm64/boot/dts/sprd/Makefile
@@ -1,4 +1,5 @@
-dtb-$(CONFIG_ARCH_SPRD) += sc9836-openphone.dtb
+dtb-$(CONFIG_ARCH_SPRD) += sc9836-openphone.dtb \
+ sp9860g-1h10.dtb
always := $(dtb-y)
subdir-y := $(dts-dirs)
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
new file mode 100644
index 0000000..7b7d8ce
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -0,0 +1,569 @@
+/*
+ * Spreadtrum SC9860 SoC
+ *
+ * Copyright (C) 2016, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "whale2.dtsi"
+
+/ {
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+ core1 {
+ cpu = <&CPU1>;
+ };
+ core2 {
+ cpu = <&CPU2>;
+ };
+ core3 {
+ cpu = <&CPU3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&CPU4>;
+ };
+ core1 {
+ cpu = <&CPU5>;
+ };
+ core2 {
+ cpu = <&CPU6>;
+ };
+ core3 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+
+ CPU0: cpu@530000 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530000>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+
+ CPU1: cpu@530001 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530001>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+
+ CPU2: cpu@530002 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530002>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+
+ CPU3: cpu@530003 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530003>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+
+ CPU4: cpu@530100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530100>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+
+ CPU5: cpu@530101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530101>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+
+ CPU6: cpu@530102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530102>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+
+ CPU7: cpu@530103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0 0x530103>;
+ enable-method = "psci";
+ cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+ };
+ };
+
+ idle-states{
+ entry-method = "arm,psci";
+
+ CORE_PD: core_pd {
+ compatible = "arm,idle-state";
+ entry-latency-us = <1000>;
+ exit-latency-us = <700>;
+ min-residency-us = <2500>;
+ local-timer-stop;
+ arm,psci-suspend-param = <0x00010002>;
+ };
+
+ CLUSTER_PD: cluster_pd {
+ compatible = "arm,idle-state";
+ entry-latency-us = <1000>;
+ exit-latency-us = <1000>;
+ min-residency-us = <3000>;
+ local-timer-stop;
+ arm,psci-suspend-param = <0x01010003>;
+ };
+ };
+
+ gic: interrupt-controller@12001000 {
+ compatible = "arm,gic-400";
+ reg = <0 0x12001000 0 0x1000>,
+ <0 0x12002000 0 0x2000>,
+ <0 0x12004000 0 0x2000>,
+ <0 0x12006000 0 0x2000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8)
+ | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8)
+ | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8)
+ | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8)
+ | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8)
+ | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a53-pmu", "arm,armv8-pmuv3";
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&CPU0>,
+ <&CPU1>,
+ <&CPU2>,
+ <&CPU3>,
+ <&CPU4>,
+ <&CPU5>,
+ <&CPU6>,
+ <&CPU7>;
+ };
+
+ soc {
+ funnel@10001000 { /* SoC Funnel */
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0 0x10001000 0 0x1000>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ soc_funnel_out_port: endpoint {
+ remote-endpoint = <&etb_in>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ soc_funnel_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&main_funnel_out_port>;
+ };
+ };
+
+ port@2 {
+ reg = <4>;
+ soc_funnel_in_port1: endpoint {
+ slave-mode;
+ remote-endpioint =
+ <&stm_out_port>;
+ };
+ };
+ };
+ };
+
+ etb@10003000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x10003000 0 0x1000>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+ port {
+ etb_in: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&soc_funnel_out_port>;
+ };
+ };
+ };
+
+ stm@10006000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0 0x10006000 0 0x1000>,
+ <0 0x01000000 0 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+ port {
+ stm_out_port: endpoint {
+ remote-endpoint =
+ <&soc_funnel_in_port1>;
+ };
+ };
+ };
+
+ funnel@11001000 { /* Cluster0 Funnel */
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0 0x11001000 0 0x1000>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ cluster0_funnel_out_port: endpoint {
+ remote-endpoint =
+ <&cluster0_etf_in>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ cluster0_funnel_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ cluster0_funnel_in_port1: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm1_out>;
+ };
+ };
+
+ port@3 {
+ reg = <2>;
+ cluster0_funnel_in_port2: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm2_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ cluster0_funnel_in_port3: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm3_out>;
+ };
+ };
+ };
+ };
+
+ funnel@11002000 { /* Cluster1 Funnel */
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0 0x11002000 0 0x1000>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ cluster1_funnel_out_port: endpoint {
+ remote-endpoint =
+ <&cluster1_etf_in>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ cluster1_funnel_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm4_out>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ cluster1_funnel_in_port1: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm5_out>;
+ };
+ };
+
+ port@3 {
+ reg = <2>;
+ cluster1_funnel_in_port2: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm6_out>;
+ };
+ };
+
+ port@4 {
+ reg = <3>;
+ cluster1_funnel_in_port3: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm7_out>;
+ };
+ };
+ };
+ };
+
+ etf@11003000 { /* ETF on Cluster0 */
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x11003000 0 0x1000>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ cluster0_etf_out: endpoint {
+ remote-endpoint =
+ <&main_funnel_in_port0>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ cluster0_etf_in: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&cluster0_funnel_out_port>;
+ };
+ };
+ };
+ };
+
+ etf@11004000 { /* ETF on Cluster1 */
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x11004000 0 0x1000>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ cluster1_etf_out: endpoint {
+ remote-endpoint =
+ <&main_funnel_in_port1>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ cluster1_etf_in: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&cluster1_funnel_out_port>;
+ };
+ };
+ };
+ };
+
+ funnel@11005000 { /* Main Funnel */
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0 0x11005000 0 0x1000>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ main_funnel_out_port: endpoint {
+ remote-endpoint =
+ <&soc_funnel_in_port0>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ main_funnel_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&cluster0_etf_out>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ main_funnel_in_port1: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&cluster1_etf_out>;
+ };
+ };
+ };
+ };
+
+ etm@11440000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11440000 0 0x1000>;
+ cpu = <&CPU0>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm0_out: endpoint {
+ remote-endpoint =
+ <&cluster0_funnel_in_port0>;
+ };
+ };
+ };
+
+ etm@11540000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11540000 0 0x1000>;
+ cpu = <&CPU1>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm1_out: endpoint {
+ remote-endpoint =
+ <&cluster0_funnel_in_port1>;
+ };
+ };
+ };
+
+ etm@11640000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11640000 0 0x1000>;
+ cpu = <&CPU2>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm2_out: endpoint {
+ remote-endpoint =
+ <&cluster0_funnel_in_port2>;
+ };
+ };
+ };
+
+ etm@11740000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11740000 0 0x1000>;
+ cpu = <&CPU3>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm3_out: endpoint {
+ remote-endpoint =
+ <&cluster0_funnel_in_port3>;
+ };
+ };
+ };
+
+ etm@11840000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11840000 0 0x1000>;
+ cpu = <&CPU4>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm4_out: endpoint {
+ remote-endpoint =
+ <&cluster1_funnel_in_port0>;
+ };
+ };
+ };
+
+ etm@11940000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11940000 0 0x1000>;
+ cpu = <&CPU5>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm5_out: endpoint {
+ remote-endpoint =
+ <&cluster1_funnel_in_port1>;
+ };
+ };
+ };
+
+ etm@11a40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11a40000 0 0x1000>;
+ cpu = <&CPU6>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm6_out: endpoint {
+ remote-endpoint =
+ <&cluster1_funnel_in_port2>;
+ };
+ };
+ };
+
+ etm@11b40000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x11b40000 0 0x1000>;
+ cpu = <&CPU7>;
+ clocks = <&ext_26m>;
+ clock-names = "apb_pclk";
+
+ port {
+ etm7_out: endpoint {
+ remote-endpoint =
+ <&cluster1_funnel_in_port3>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts b/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts
new file mode 100644
index 0000000..ae0b28c
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts
@@ -0,0 +1,56 @@
+/*
+ * Spreadtrum SP9860g board
+ *
+ * Copyright (C) 2017, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/dts-v1/;
+
+#include "sc9860.dtsi"
+
+/ {
+ model = "Spreadtrum SP9860G 3GFHD Board";
+
+ compatible = "sprd,sp9860g-1h10", "sprd,sc9860";
+
+ aliases {
+ serial0 = &uart0; /* for Bluetooth */
+ serial1 = &uart1; /* UART console */
+ serial2 = &uart2; /* Reserved */
+ serial3 = &uart3; /* for GPS */
+ };
+
+ memory{
+ device_type = "memory";
+ reg = <0x0 0x80000000 0 0x60000000>,
+ <0x1 0x80000000 0 0x60000000>;
+ };
+
+ chosen {
+ stdout-path = "serial1:115200n8";
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi
new file mode 100644
index 0000000..7c217c5
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/whale2.dtsi
@@ -0,0 +1,71 @@
+/*
+ * Spreadtrum Whale2 platform peripherals
+ *
+ * Copyright (C) 2016, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ soc: soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ap-apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x0 0x70000000 0x10000000>;
+
+ uart0: serial@0 {
+ compatible = "sprd,sc9860-uart",
+ "sprd,sc9836-uart";
+ reg = <0x0 0x100>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ext_26m>;
+ status = "disabled";
+ };
+
+ uart1: serial@100000 {
+ compatible = "sprd,sc9860-uart",
+ "sprd,sc9836-uart";
+ reg = <0x100000 0x100>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ext_26m>;
+ status = "disabled";
+ };
+
+ uart2: serial@200000 {
+ compatible = "sprd,sc9860-uart",
+ "sprd,sc9836-uart";
+ reg = <0x200000 0x100>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ext_26m>;
+ status = "disabled";
+ };
+
+ uart3: serial@300000 {
+ compatible = "sprd,sc9860-uart",
+ "sprd,sc9836-uart";
+ reg = <0x300000 0x100>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ext_26m>;
+ status = "disabled";
+ };
+ };
+
+ };
+
+ ext_26m: ext-26m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "ext_26m";
+ };
+};
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] of: add stub for of_n_addr_cells
From: Arnd Bergmann @ 2017-03-27 7:31 UTC (permalink / raw)
To: Tobias Regnery
Cc: Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
Linux Kernel Mailing List, Simon Horman
In-Reply-To: <20170327055454.c6kj4keeudqn4bps@builder>
On Mon, Mar 27, 2017 at 7:54 AM, Tobias Regnery
<tobias.regnery-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On 24.03.17, Arnd Bergmann wrote:
>> >
>> > +static inline int of_n_addr_cells(struct device_node *np)
>> > +{
>> > + return 0;
>> > +}
>> > +
>>
>> This looks good, but we should also do the same thing for of_n_size_cells().
>>
>> I think I sent something like this a few years ago, but never resubmitted it
>> when it was ignored at first.
>>
>> Arnd
>
> This seems sensible, I can send an updated patch with this change or I can
> send it as a separate patch, whatever the maintainers prefer.
I'd recommend sending an updated patch.
Arnd
--
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 v2] iio:adc: Driver for Linear Technology LTC2497 ADC
From: michael.hennerich-OyLXuOCK7orQT0dZR+AlfA @ 2017-03-27 7:23 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A, lars-Qo5EllUWu/uELgA04lAiVw,
knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Michael Hennerich
From: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
This patch adds support for the Analog Devices / Linear Technology
LTC2497 ADCs. The LTC2497 is a 16-channel (eight differential),
16-bit, high precision, delta-sigma ADC with an automatic, differential,
input current cancellation front end and a 2-wire, I2C interface.
Signed-off-by: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
Changes since v1:
- remove confusing kconfig help text
- use proper defines
- add descriptive comment
- fix removal order
- add poper commit mssage
---
.../devicetree/bindings/iio/adc/ltc2497.txt | 13 +
MAINTAINERS | 1 +
drivers/iio/adc/Kconfig | 10 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/ltc2497.c | 269 +++++++++++++++++++++
5 files changed, 294 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/adc/ltc2497.txt
create mode 100644 drivers/iio/adc/ltc2497.c
diff --git a/Documentation/devicetree/bindings/iio/adc/ltc2497.txt b/Documentation/devicetree/bindings/iio/adc/ltc2497.txt
new file mode 100644
index 0000000..c2829c19
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ltc2497.txt
@@ -0,0 +1,13 @@
+* Linear Technology / Analog Devices LTC2497 ADC
+
+Required properties:
+ - compatible: Should be "lltc,ltc2497"
+ - reg: Should contain the ADC I2C address
+ - vref-supply: The regulator supply for ADC reference voltage
+
+Example:
+ ltc2497: adc@76 {
+ compatible = "lltc,ltc2497";
+ reg = <0x76>;
+ vref-supply = <<c2497_reg>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index a7d6f9a..173043c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -813,6 +813,7 @@ W: http://wiki.analog.com/
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/*/ad*
+F: drivers/iio/adc/ltc2497*
X: drivers/iio/*/adjd*
F: drivers/staging/iio/*/ad*
F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 2268a6f..acc115b 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -326,6 +326,16 @@ config LTC2485
To compile this driver as a module, choose M here: the module will be
called ltc2485.
+config LTC2497
+ tristate "Linear Technology LTC2497 ADC driver"
+ depends on I2C
+ help
+ Say yes here to build support for Linear Technology LTC2497
+ 16-Bit 8-/16-Channel Delta Sigma ADC.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ltc2497.
+
config MAX1027
tristate "Maxim max1027 ADC driver"
depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 73dbe39..9d626b5 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2485) += ltc2485.o
+obj-$(CONFIG_LTC2497) += ltc2497.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o
obj-$(CONFIG_MAX1363) += max1363.o
diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c
new file mode 100644
index 0000000..7907534
--- /dev/null
+++ b/drivers/iio/adc/ltc2497.c
@@ -0,0 +1,269 @@
+/*
+ * ltc2497.c - Driver for Linear Technology LTC2497 ADC
+ *
+ * Copyright (C) 2017 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ *
+ * Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define LTC2497_ENABLE 0xA0
+#define LTC2497_SGL (1 << 4)
+#define LTC2497_DIFF (0 << 4)
+#define LTC2497_SIGN (1 << 3)
+#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE
+#define LTC2497_CONVERSION_TIME_MS 150ULL
+
+struct ltc2497_st {
+ struct i2c_client *client;
+ struct regulator *ref;
+ ktime_t time_prev;
+ u8 addr_prev;
+};
+
+static int ltc2497_wait_conv(struct ltc2497_st *st)
+{
+ s64 time_elapsed;
+
+ time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev);
+
+ if (time_elapsed < LTC2497_CONVERSION_TIME_MS) {
+ /* delay if conversion time not passed
+ * since last read or write
+ */
+ msleep(LTC2497_CONVERSION_TIME_MS - time_elapsed);
+ return 0;
+ }
+
+ if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) {
+ /* We're in automatic mode -
+ * so the last reading is stil not outdated
+ */
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val)
+{
+ struct i2c_client *client = st->client;
+ __be32 buf = 0;
+ int ret;
+
+ ret = ltc2497_wait_conv(st);
+ if (ret < 0 || st->addr_prev != address) {
+ ret = i2c_smbus_write_byte(st->client,
+ LTC2497_ENABLE | address);
+ if (ret < 0)
+ return ret;
+ st->addr_prev = address;
+ msleep(LTC2497_CONVERSION_TIME_MS);
+ }
+ ret = i2c_master_recv(client, (char *)&buf, 3);
+ if (ret < 0) {
+ dev_err(&client->dev, "i2c_master_recv failed\n");
+ return ret;
+ }
+ st->time_prev = ktime_get();
+
+ /* convert and shift the result,
+ * and finally convert from offset binary to signed integer
+ */
+ *val = (be32_to_cpu(buf) >> 14) - (1 << 17);
+
+ return ret;
+}
+
+static int ltc2497_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ltc2497_st *st = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&indio_dev->mlock);
+ ret = ltc2497_read(st, chan->address, val);
+ mutex_unlock(&indio_dev->mlock);
+ if (ret < 0)
+ return ret;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ ret = regulator_get_voltage(st->ref);
+ if (ret < 0)
+ return ret;
+
+ *val = ret / 1000;
+ *val2 = 17;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+#define LTC2497_CHAN(_chan, _addr) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = (_chan), \
+ .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+}
+
+#define LTC2497_CHAN_DIFF(_chan, _addr) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \
+ .channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\
+ .address = (_addr | _chan), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .differential = 1, \
+}
+
+static const struct iio_chan_spec ltc2497_channel[] = {
+ LTC2497_CHAN(0, LTC2497_SGL),
+ LTC2497_CHAN(1, LTC2497_SGL),
+ LTC2497_CHAN(2, LTC2497_SGL),
+ LTC2497_CHAN(3, LTC2497_SGL),
+ LTC2497_CHAN(4, LTC2497_SGL),
+ LTC2497_CHAN(5, LTC2497_SGL),
+ LTC2497_CHAN(6, LTC2497_SGL),
+ LTC2497_CHAN(7, LTC2497_SGL),
+ LTC2497_CHAN(8, LTC2497_SGL),
+ LTC2497_CHAN(9, LTC2497_SGL),
+ LTC2497_CHAN(10, LTC2497_SGL),
+ LTC2497_CHAN(11, LTC2497_SGL),
+ LTC2497_CHAN(12, LTC2497_SGL),
+ LTC2497_CHAN(13, LTC2497_SGL),
+ LTC2497_CHAN(14, LTC2497_SGL),
+ LTC2497_CHAN(15, LTC2497_SGL),
+ LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(3, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(4, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(5, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(6, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(7, LTC2497_DIFF),
+ LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN),
+ LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN),
+ LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN),
+ LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN),
+ LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN),
+ LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN),
+ LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN),
+ LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN),
+};
+
+static const struct iio_info ltc2497_info = {
+ .read_raw = ltc2497_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int ltc2497_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct iio_dev *indio_dev;
+ struct ltc2497_st *st;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_WRITE_BYTE))
+ return -EOPNOTSUPP;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ st->client = client;
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = id->name;
+ indio_dev->info = <c2497_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ltc2497_channel;
+ indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel);
+
+ st->ref = devm_regulator_get(&client->dev, "vref");
+ if (IS_ERR(st->ref))
+ return PTR_ERR(st->ref);
+
+ ret = regulator_enable(st->ref);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
+ if (ret < 0)
+ goto err_regulator_disable;
+
+ st->addr_prev = LTC2497_CONFIG_DEFAULT;
+ st->time_prev = ktime_get();
+
+ ret = iio_device_register(indio_dev);
+ if (ret < 0)
+ goto err_regulator_disable;
+
+ return 0;
+
+err_regulator_disable:
+ regulator_disable(st->ref);
+
+ return ret;
+}
+
+static int ltc2497_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ltc2497_st *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ regulator_disable(st->ref);
+
+ return 0;
+}
+
+static const struct i2c_device_id ltc2497_id[] = {
+ { "ltc2497", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ltc2497_id);
+
+static const struct of_device_id ltc2497_of_match[] = {
+ { .compatible = "lltc,ltc2497", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ltc2497_of_match);
+
+static struct i2c_driver ltc2497_driver = {
+ .driver = {
+ .name = "ltc2497",
+ .of_match_table = of_match_ptr(ltc2497_of_match),
+ },
+ .probe = ltc2497_probe,
+ .remove = ltc2497_remove,
+ .id_table = ltc2497_id,
+};
+module_i2c_driver(ltc2497_driver);
+
+MODULE_AUTHOR("Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>");
+MODULE_DESCRIPTION("Linear Technology LTC2497 ADC driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* RE: [PATCH v2 1/2] dts: arm64: add LS1043A DPAA support
From: Madalin-Cristian Bucur @ 2017-03-27 7:03 UTC (permalink / raw)
To: Shawn Guo
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
catalin.marinas@arm.com, Roy Pledge, will.deacon@arm.com,
linux-kernel@vger.kernel.org, Russell King - ARM Linux,
robh+dt@kernel.org, Kumar Gala,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20170327062719.GQ30608@dragon>
> -----Original Message-----
> From: Shawn Guo [mailto:shawnguo@kernel.org]
> Sent: Monday, March 27, 2017 9:27 AM
> Subject: Re: [PATCH v2 1/2] dts: arm64: add LS1043A DPAA support
>
> On Wed, Mar 22, 2017 at 10:58:12AM +0000, Madalin-Cristian Bucur wrote:
> > > > +&soc {
> > > > +
> > > > +/include/ "qoriq-fman3-0.dtsi"
> > > > +/include/ "qoriq-fman3-0-1g-0.dtsi"
> > > > +/include/ "qoriq-fman3-0-1g-1.dtsi"
> > > > +/include/ "qoriq-fman3-0-1g-2.dtsi"
> > > > +/include/ "qoriq-fman3-0-1g-3.dtsi"
> > > > +/include/ "qoriq-fman3-0-1g-4.dtsi"
> > > > +/include/ "qoriq-fman3-0-1g-5.dtsi"
> > > > +/include/ "qoriq-fman3-0-10g-0.dtsi"
> > >
> > > We usually put the includes at the beginning of the file, and #include
> > > is more recommended than /include/.
> >
> > I'm not making use of the header file inclusion feature #include
> provides
> > (nor plan to) in these files thus I've selected /include/ here.
>
> Let's be simple and consistent. Use #include please.
I can do that, running the preprocessor on these files without being required
does not add that much time in the end. I'm not a fan of this feature, I never
liked the fact one loses the liberty of easily using dtc directly to debug
using dtc -O dts when adding #includes.
> > > > + fman@1a00000 {
> > > > + enet0: ethernet@e0000 {
> > > > + };
> > > > +
> > > > + enet1: ethernet@e2000 {
> > > > + };
> > > > +
> > > > + enet2: ethernet@e4000 {
> > > > + };
> > > > +
> > > > + enet3: ethernet@e6000 {
> > > > + };
> > > > +
> > > > + enet4: ethernet@e8000 {
> > > > + };
> > > > +
> > > > + enet5: ethernet@ea000 {
> > > > + };
> > > > +
> > > > + enet6: ethernet@f0000 {
> > > > + };
> > > > + };
> > >
> > > I do not quite understand why these nodes are empty.
> >
> > These nodes provide the aliases (and custom SoC mapping) for the
> > FMan ports that are used on this particular SoC. The particular
> > node details are found in the port dtsi file thus no information
> > is required here. Given the fact that the numbering and actual
> > ports that are in use can vary between SoCs, the aliases cannot
> > be included in the port dtsi nor in the FMan dtsi.
>
> Do not completely follow. What do you mean by 'port dtsi file'? Maybe
> I should wait for you new patches with better commit log and comments to
> understand these odd empty nodes.
The DPAA IP can have a certain number of ports. Out of those, a certain
SoC can use all or only a subset, with diverse decisions on actual numbering
of the used ports. Next, when using the SoC on a particular board, some
ports will be used, some will not. The file hierarchy relates to this
hierarchy - you have individual port files that are included by the
SoC dtsi which in turn is included by the board dts. These nodes do not
need any new content as all the node details are provided by the port
dtsi files. The information they provide is the alias used for each port.
> >
> > > > +};
> > > > diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > > b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > > > index 0989d63..ee66bb2 100644
> > > > --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > > > +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > > > @@ -181,3 +181,5 @@
> > > > reg = <0>;
> > > > };
> > > > };
> > > > +
> > > > +/include/ "fsl-ls1043-post.dtsi"
> > >
> > > Move it to header of the file.
> >
> > This is to be included at the end, to make sure the references are
> > met and to allow overrides if needed.
>
> What is broken if you move the include to header?
Not much besides the structure we've always used for our SoCs device
trees. The file is called "-post.dtsi" because here is the place any
required overrides can be made, if needed. Moving to the top renders
having this separate file useless.
> >
> > > > diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > > b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > > > index c37110b..d94f003 100644
> > > > --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > > > +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > > > @@ -139,3 +139,78 @@
> > > > &duart1 {
> > > > status = "okay";
> > > > };
> > > > +
> > > > +/include/ "fsl-ls1043-post.dtsi"
> > > > +
> > >
> > > Ditto
> > >
> > > > +&soc {
> > > > + fman@1a00000 {
> > > > + ethernet@e0000 {
> > >
> > > You defined enet0 label. Why don't you use it?
> > >
> >
> > The enet0 label is used by u-boot for fix-ups, providing the
> > actual offset here makes it easier to follow.
>
> You will not need to construct the node hierarchy with label. And
> alias/label name is more easier to follow than offset.
>
> Shawn
When I said easier to follow I was referring to someone creating a
new device tree for his custom board, not someone reading the device
tree. If you have the board and SoC reference manuals in your hands
and you are writing a new board device tree, having the offset here
makes things easier. The benefit of having one less indentation level
is lesser than that.
Madalin
^ permalink raw reply
* [PATCH RESEND v5 7/7] mfd: dt-bindings: Add RK805 device tree bindings document
From: Elaine Zhang @ 2017-03-27 6:53 UTC (permalink / raw)
To: lee.jones-QSEj5FYQhm4dnm+yROfE0A,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
Cc: huangtao-TNX95d0MmH7DzftRWevZcw, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA, xxx-TNX95d0MmH7DzftRWevZcw,
Elaine Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, w.egorov-guT5V/WYfQezQB+pC5nmwQ,
chenjh-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <1490595705-28844-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add device tree bindings documentation for Rockchip's RK805 PMIC.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
Documentation/devicetree/bindings/mfd/rk808.txt | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt
index 9636ae8d8d41..91b65227afeb 100644
--- a/Documentation/devicetree/bindings/mfd/rk808.txt
+++ b/Documentation/devicetree/bindings/mfd/rk808.txt
@@ -1,11 +1,14 @@
RK8XX Power Management Integrated Circuit
The rk8xx family current members:
+rk805
rk808
rk818
Required properties:
-- compatible: "rockchip,rk808", "rockchip,rk818"
+- compatible: "rockchip,rk805"
+- compatible: "rockchip,rk808"
+- compatible: "rockchip,rk818"
- reg: I2C slave address
- interrupt-parent: The parent interrupt controller.
- interrupts: the interrupt outputs of the controller.
@@ -18,6 +21,14 @@ Optional properties:
- rockchip,system-power-controller: Telling whether or not this pmic is controlling
the system power.
+Optional RK805 properties:
+- vcc1-supply: The input supply for DCDC_REG1
+- vcc2-supply: The input supply for DCDC_REG2
+- vcc3-supply: The input supply for DCDC_REG3
+- vcc4-supply: The input supply for DCDC_REG4
+- vcc5-supply: The input supply for LDO_REG1 and LDO_REG2
+- vcc6-supply: The input supply for LDO_REG3
+
Optional RK808 properties:
- vcc1-supply: The input supply for DCDC_REG1
- vcc2-supply: The input supply for DCDC_REG2
@@ -56,6 +67,15 @@ by a child node of the 'regulators' node.
/* standard regulator bindings here */
};
+Following regulators of the RK805 PMIC regulators are supported. Note that
+the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
+number as described in RK805 datasheet.
+
+ - DCDC_REGn
+ - valid values for n are 1 to 4.
+ - LDO_REGn
+ - valid values for n are 1 to 3
+
Following regulators of the RK808 PMIC block are supported. Note that
the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
number as described in RK808 datasheet.
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v2 21/23] MAINTAINERS: Add file patterns for w1 device tree bindings
From: Geert Uytterhoeven @ 2017-03-27 6:50 UTC (permalink / raw)
To: Evgeniy Polyakov
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
Mark Rutland,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Greg Kroah-Hartman
In-Reply-To: <427591489432133-MCPEbMQOdsNxpj1cXAZ9Bg@public.gmane.org>
On Mon, Mar 13, 2017 at 8:08 PM, Evgeniy Polyakov <zbr-i6C2adt8DTjR7s880joybQ@public.gmane.org> wrote:
> 12.03.2017, 16:17, "Geert Uytterhoeven" <geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>:
>> Submitters of device tree binding documentation may forget to CC
>> the subsystem maintainer if this is missing.
>
> I have no objection on this patch, but I do not really know who is responsible for this and which tree should it come into.
> If it is ok, Greg, please pull it into your one, or I see devicetree@ mail in copy... Stumbled
"Please apply this patch directly if you want to be involved in device
tree binding documentation for your subsystem."
=> Greg.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
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 v2 2/2] ARM: dts: sun7i: Add CAN node and can0_pins_a pinctrl settings
From: Maxime Ripard @ 2017-03-27 6:46 UTC (permalink / raw)
To: Patrick Menschel
Cc: mark.rutland, devicetree, linux, linux-kernel, wens, robh+dt,
linux-can, linux-arm-kernel
In-Reply-To: <1490392339-23565-3-git-send-email-menschel.p@posteo.de>
[-- Attachment #1.1: Type: text/plain, Size: 1660 bytes --]
Hi Patrick,
On Fri, Mar 24, 2017 at 10:52:19PM +0100, Patrick Menschel wrote:
> The A20 SoC has an on-board CAN controller. This patch adds the device node
> and the corresponding pinctrl settings for pins PH20 and PH21.
>
> The CAN controller is inherited from the A10 SoC and uses the same driver.
>
> This patch is adapted from the description in
> Documentation/devicetree/bindings/net/can/sun4i_can.txt
>
> Signed-off-by: Patrick Menschel <menschel.p@posteo.de>
> ---
> arch/arm/boot/dts/sun7i-a20.dtsi | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
> index 2db97fc..25af586 100644
> --- a/arch/arm/boot/dts/sun7i-a20.dtsi
> +++ b/arch/arm/boot/dts/sun7i-a20.dtsi
> @@ -1096,6 +1096,11 @@
> #interrupt-cells = <3>;
> #gpio-cells = <3>;
>
> + can0_pins_a: can0@0 {
> + pins = "PH20","PH21";
> + function = "can";
> + };
> +
> clk_out_a_pins_a: clk_out_a@0 {
> pins = "PI12";
> function = "clk_out_a";
> @@ -1582,6 +1587,14 @@
> #size-cells = <0>;
> };
>
> + can0: can@01c2bc00 {
> + compatible = "allwinner,sun4i-a10-can";
Sorry for not spotting this earlier, but this would need an A20
compatible too, to deal with the case where it turns out not to be
compatible.
you can do something like this:
compatible = "allwinner,sun7i-a20-can", "allwinner,sun4i-a10-can";
Ideally the pinctrl groups addition should be split out in a separate
patch too.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 1/2] dts: arm64: add LS1043A DPAA support
From: Shawn Guo @ 2017-03-27 6:27 UTC (permalink / raw)
To: Madalin-Cristian Bucur
Cc: Roy Pledge, mark.rutland-5wv7dgnIgG8@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
catalin.marinas-5wv7dgnIgG8@public.gmane.org,
will.deacon-5wv7dgnIgG8@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Russell King - ARM Linux,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Kumar Gala,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <HE1PR04MB11297D944241012F44C0ADF8EC3C0-6LN7OEpIatWsitHo+Wi4ws9NdZoXdze2vxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
On Wed, Mar 22, 2017 at 10:58:12AM +0000, Madalin-Cristian Bucur wrote:
> > > +&soc {
> > > +
> > > +/include/ "qoriq-fman3-0.dtsi"
> > > +/include/ "qoriq-fman3-0-1g-0.dtsi"
> > > +/include/ "qoriq-fman3-0-1g-1.dtsi"
> > > +/include/ "qoriq-fman3-0-1g-2.dtsi"
> > > +/include/ "qoriq-fman3-0-1g-3.dtsi"
> > > +/include/ "qoriq-fman3-0-1g-4.dtsi"
> > > +/include/ "qoriq-fman3-0-1g-5.dtsi"
> > > +/include/ "qoriq-fman3-0-10g-0.dtsi"
> >
> > We usually put the includes at the beginning of the file, and #include
> > is more recommended than /include/.
>
> I'm not making use of the header file inclusion feature #include provides
> (nor plan to) in these files thus I've selected /include/ here.
Let's be simple and consistent. Use #include please.
> > > + fman@1a00000 {
> > > + enet0: ethernet@e0000 {
> > > + };
> > > +
> > > + enet1: ethernet@e2000 {
> > > + };
> > > +
> > > + enet2: ethernet@e4000 {
> > > + };
> > > +
> > > + enet3: ethernet@e6000 {
> > > + };
> > > +
> > > + enet4: ethernet@e8000 {
> > > + };
> > > +
> > > + enet5: ethernet@ea000 {
> > > + };
> > > +
> > > + enet6: ethernet@f0000 {
> > > + };
> > > + };
> >
> > I do not quite understand why these nodes are empty.
>
> These nodes provide the aliases (and custom SoC mapping) for the
> FMan ports that are used on this particular SoC. The particular
> node details are found in the port dtsi file thus no information
> is required here. Given the fact that the numbering and actual
> ports that are in use can vary between SoCs, the aliases cannot
> be included in the port dtsi nor in the FMan dtsi.
Do not completely follow. What do you mean by 'port dtsi file'? Maybe
I should wait for you new patches with better commit log and comments to
understand these odd empty nodes.
>
> > > +};
> > > diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > > index 0989d63..ee66bb2 100644
> > > --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > > +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
> > > @@ -181,3 +181,5 @@
> > > reg = <0>;
> > > };
> > > };
> > > +
> > > +/include/ "fsl-ls1043-post.dtsi"
> >
> > Move it to header of the file.
>
> This is to be included at the end, to make sure the references are
> met and to allow overrides if needed.
What is broken if you move the include to header?
>
> > > diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > > index c37110b..d94f003 100644
> > > --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > > +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
> > > @@ -139,3 +139,78 @@
> > > &duart1 {
> > > status = "okay";
> > > };
> > > +
> > > +/include/ "fsl-ls1043-post.dtsi"
> > > +
> >
> > Ditto
> >
> > > +&soc {
> > > + fman@1a00000 {
> > > + ethernet@e0000 {
> >
> > You defined enet0 label. Why don't you use it?
> >
>
> The enet0 label is used by u-boot for fix-ups, providing the
> actual offset here makes it easier to follow.
You will not need to construct the node hierarchy with label. And
alias/label name is more easier to follow than offset.
Shawn
--
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: [PATCHv2] phy: cpcap-usb: Add CPCAP PMIC USB support
From: Kishon Vijay Abraham I @ 2017-03-27 6:25 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Marcel Partap, Michael Scott
In-Reply-To: <20170322234602.5888-1-tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
Hi Tony,
On Thursday 23 March 2017 05:16 AM, Tony Lindgren wrote:
> Some Motorola phones like droid 4 use a custom CPCAP PMIC that has a
> multiplexing USB PHY.
>
> This USB PHY can operate at least in four modes using pin multiplexing
> and two control GPIOS:
>
> - Pass through companion PHY for the SoC USB PHY
> - ULPI PHY for the SoC
> - Pass through USB for the modem
> - UART debug console for the SoC
>
> This patch adds support for droid 4 USB PHY and debug UART modes,
> support for other modes can be added later on as needed.
>
> Both peripheral and host mode are working for the USB. The
> host mode depends on the cpcap-charger driver for VBUS.
>
> VBUS and ID pin detection are done using cpcap-adc IIO ADC
> driver.
>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: Marcel Partap <mpartap-hi6Y0CQ0nG0@public.gmane.org>
> Cc: Michael Scott <michael.scott-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Tested-by: Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
> ---
>
> Changes since v1:
>
> - Use iio_read_channel_processed() instead of iio_read_channel_scaled()
> as changed in the v2 of the ADC driver
>
> - Keep Tested-by from Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> as the change
> from v1 is trivial
>
> ---
> .../devicetree/bindings/phy/phy-cpcap-usb.txt | 40 ++
> drivers/phy/Kconfig | 8 +
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-cpcap-usb.c | 695 +++++++++++++++++++++
> 4 files changed, 744 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt
> create mode 100644 drivers/phy/phy-cpcap-usb.c
>
> diff --git a/Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt b/Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt
> @@ -0,0 +1,40 @@
> +Motorola CPCAP PMIC USB PHY binding
> +
> +Required properties:
> +compatible: Shall be either "motorola,cpcap-usb-phy" or
> + "motorola,mapphone-cpcap-usb-phy"
> +#phy-cells: Shall be 0
> +interrupts: CPCAP PMIC interrupts used by the USB PHY
> +interrupt-names: Interrupt names
> +io-channels: IIO ADC channels used by the USB PHY
> +io-channel-names: IIO ADC channel names
> +vusb-supply: Regulator for the PHY
> +
> +Optional properties:
> +pinctrl: Optional alternate pin modes for the PHY
> +pinctrl-names: Names for optional pin modes
> +mode-gpios: Optional GPIOs for configuring alternate modes
> +
> +Example:
> +cpcap_usb2_phy: phy {
> + compatible = "motorola,mapphone-cpcap-usb-phy";
> + pinctrl-0 = <&usb_gpio_mux_sel1 &usb_gpio_mux_sel2>;
> + pinctrl-1 = <&usb_ulpi_pins>;
> + pinctrl-2 = <&usb_utmi_pins>;
> + pinctrl-3 = <&uart3_pins>;
> + pinctrl-names = "default", "ulpi", "utmi", "uart";
> + #phy-cells = <0>;
> + interrupts-extended = <
> + &cpcap 15 0 &cpcap 14 0 &cpcap 28 0 &cpcap 19 0
> + &cpcap 18 0 &cpcap 17 0 &cpcap 16 0 &cpcap 49 0
> + &cpcap 48 1
> + >;
> + interrupt-names =
> + "id_ground", "id_float", "se0conn", "vbusvld",
> + "sessvld", "sessend", "se1", "dm", "dp";
> + mode-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH
> + &gpio1 0 GPIO_ACTIVE_HIGH>;
> + io-channels = <&cpcap_adc 2>, <&cpcap_adc 7>;
> + io-channel-names = "vbus", "id";
> + vusb-supply = <&vusb>;
> +};
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -47,6 +47,14 @@ config PHY_BERLIN_SATA
> help
> Enable this to support the SATA PHY on Marvell Berlin SoCs.
>
> +config PHY_CPCAP_USB
> + tristate "CPCAP USB PHY driver"
> + depends on USB_SUPPORT
> + select GENERIC_PHY
> + select USB_PHY
> + help
> + Enable this for CPCAP USB to work.
> +
> config ARMADA375_USBCLUSTER_PHY
> def_bool y
> depends on MACH_ARMADA_375 || COMPILE_TEST
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
> obj-$(CONFIG_PHY_BCM_NS_USB3) += phy-bcm-ns-usb3.o
> obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
> obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
> +obj-$(CONFIG_PHY_CPCAP_USB) += phy-cpcap-usb.o
> obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
> obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
> obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
> diff --git a/drivers/phy/phy-cpcap-usb.c b/drivers/phy/phy-cpcap-usb.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/phy/phy-cpcap-usb.c
> @@ -0,0 +1,695 @@
> +/*
> + * Motorola CPCAP PMIC USB PHY driver
> + * Copyright (C) 2017 Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
> + *
> + * Some parts based on earlier Motorola Linux kernel tree code in
> + * board-mapphone-usb.c and cpcap-usb-det.c:
> + * Copyright (C) 2007 - 2011 Motorola, Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/atomic.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/iio/consumer.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +#include <linux/gpio/consumer.h>
> +#include <linux/mfd/motorola-cpcap.h>
> +#include <linux/phy/omap_usb.h>
> +#include <linux/phy/phy.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/usb/musb.h>
> +
> +/* CPCAP_REG_USBC1 register bits */
> +#define CPCAP_BIT_IDPULSE BIT(15)
> +#define CPCAP_BIT_ID100KPU BIT(14)
> +#define CPCAP_BIT_IDPUCNTRL BIT(13)
> +#define CPCAP_BIT_IDPU BIT(12)
> +#define CPCAP_BIT_IDPD BIT(11)
> +#define CPCAP_BIT_VBUSCHRGTMR3 BIT(10)
> +#define CPCAP_BIT_VBUSCHRGTMR2 BIT(9)
> +#define CPCAP_BIT_VBUSCHRGTMR1 BIT(8)
> +#define CPCAP_BIT_VBUSCHRGTMR0 BIT(7)
> +#define CPCAP_BIT_VBUSPU BIT(6)
> +#define CPCAP_BIT_VBUSPD BIT(5)
> +#define CPCAP_BIT_DMPD BIT(4)
> +#define CPCAP_BIT_DPPD BIT(3)
> +#define CPCAP_BIT_DM1K5PU BIT(2)
> +#define CPCAP_BIT_DP1K5PU BIT(1)
> +#define CPCAP_BIT_DP150KPU BIT(0)
> +
> +/* CPCAP_REG_USBC2 register bits */
> +#define CPCAP_BIT_ZHSDRV1 BIT(15)
> +#define CPCAP_BIT_ZHSDRV0 BIT(14)
> +#define CPCAP_BIT_DPLLCLKREQ BIT(13)
> +#define CPCAP_BIT_SE0CONN BIT(12)
> +#define CPCAP_BIT_UARTTXTRI BIT(11)
> +#define CPCAP_BIT_UARTSWAP BIT(10)
> +#define CPCAP_BIT_UARTMUX1 BIT(9)
> +#define CPCAP_BIT_UARTMUX0 BIT(8)
> +#define CPCAP_BIT_ULPISTPLOW BIT(7)
> +#define CPCAP_BIT_TXENPOL BIT(6)
> +#define CPCAP_BIT_USBXCVREN BIT(5)
> +#define CPCAP_BIT_USBCNTRL BIT(4)
> +#define CPCAP_BIT_USBSUSPEND BIT(3)
> +#define CPCAP_BIT_EMUMODE2 BIT(2)
> +#define CPCAP_BIT_EMUMODE1 BIT(1)
> +#define CPCAP_BIT_EMUMODE0 BIT(0)
> +
> +/* CPCAP_REG_USBC3 register bits */
> +#define CPCAP_BIT_SPARE_898_15 BIT(15)
> +#define CPCAP_BIT_IHSTX03 BIT(14)
> +#define CPCAP_BIT_IHSTX02 BIT(13)
> +#define CPCAP_BIT_IHSTX01 BIT(12)
> +#define CPCAP_BIT_IHSTX0 BIT(11)
> +#define CPCAP_BIT_IDPU_SPI BIT(10)
> +#define CPCAP_BIT_UNUSED_898_9 BIT(9)
> +#define CPCAP_BIT_VBUSSTBY_EN BIT(8)
> +#define CPCAP_BIT_VBUSEN_SPI BIT(7)
> +#define CPCAP_BIT_VBUSPU_SPI BIT(6)
> +#define CPCAP_BIT_VBUSPD_SPI BIT(5)
> +#define CPCAP_BIT_DMPD_SPI BIT(4)
> +#define CPCAP_BIT_DPPD_SPI BIT(3)
> +#define CPCAP_BIT_SUSPEND_SPI BIT(2)
> +#define CPCAP_BIT_PU_SPI BIT(1)
> +#define CPCAP_BIT_ULPI_SPI_SEL BIT(0)
> +
> +struct cpcap_usb_ints_state {
> + bool id_ground;
> + bool id_float;
> + bool chrg_det;
> + bool rvrs_chrg;
> + bool vbusov;
> +
> + bool chrg_se1b;
> + bool se0conn;
> + bool rvrs_mode;
> + bool chrgcurr1;
> + bool vbusvld;
> + bool sessvld;
> + bool sessend;
> + bool se1;
> +
> + bool battdetb;
> + bool dm;
> + bool dp;
> +};
> +
> +enum cpcap_gpio_mode {
> + CPCAP_DM_DP,
> + CPCAP_MDM_RX_TX,
> + CPCAP_UNKNOWN,
> + CPCAP_OTG_DM_DP,
> +};
> +
> +struct cpcap_interrupt_desc {
> + struct list_head node; /* list of interrupts */
> + const char *name;
> + int irq;
> +};
> +
> +struct cpcap_phy_ddata {
> + struct regmap *reg;
> + struct device *dev;
> + struct clk *refclk;
> + struct usb_phy phy;
> + struct list_head irq_list;
> + struct mutex lock; /* for list of interrupts used */
> + struct delayed_work detect_work;
> + struct pinctrl *pins;
> + struct pinctrl_state *pins_ulpi;
> + struct pinctrl_state *pins_utmi;
> + struct pinctrl_state *pins_uart;
> +
> + struct gpio_desc *gpio[2];
> +
> + struct iio_channel *vbus;
> + struct iio_channel *id;
> +
> + struct regulator *vusb;
> + atomic_t active;
> +};
> +
> +static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
> +{
> + int error, value = 0;
> +
> + error = iio_read_channel_processed(ddata->vbus, &value);
> + if (error >= 0)
> + return value > 3900 ? true : false;
> +
> + dev_err(ddata->dev, "error reading VBUS: %i\n", error);
> +
> + return false;
> +}
> +
> +static int cpcap_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
> +{
> + otg->host = host;
> + if (!host)
> + otg->state = OTG_STATE_UNDEFINED;
> +
> + return 0;
> +}
> +
> +static int cpcap_usb_phy_set_peripheral(struct usb_otg *otg,
> + struct usb_gadget *gadget)
> +{
> + otg->gadget = gadget;
> + if (!gadget)
> + otg->state = OTG_STATE_UNDEFINED;
> +
> + return 0;
> +}
> +
> +static const struct phy_ops ops = {
> + .owner = THIS_MODULE,
> +};
Given that this phy doesn't have any phy_ops, Is there a reason for registering
this phy with the phy framework? Is it because this driver uses the phy_core's
pm_runtime feature?
> +
> +static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
> + struct cpcap_usb_ints_state *s)
> +{
> + int val, error;
> +
> + error = regmap_read(ddata->reg, CPCAP_REG_INTS1, &val);
> + if (error)
> + return error;
> +
> + s->id_ground = val & BIT(15);
> + s->id_float = val & BIT(14);
> + s->vbusov = val & BIT(11);
> +
> + error = regmap_read(ddata->reg, CPCAP_REG_INTS2, &val);
> + if (error)
> + return error;
> +
> + s->vbusvld = val & BIT(3);
> + s->sessvld = val & BIT(2);
> + s->sessend = val & BIT(1);
> + s->se1 = val & BIT(0);
> +
> + error = regmap_read(ddata->reg, CPCAP_REG_INTS4, &val);
> + if (error)
> + return error;
> +
> + s->dm = val & BIT(1);
> + s->dp = val & BIT(0);
> +
> + return 0;
> +}
> +
> +static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
> +static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
> +
> +static void cpcap_usb_detect(struct work_struct *work)
> +{
> + struct cpcap_phy_ddata *ddata;
> + struct cpcap_usb_ints_state s;
> + bool vbus = false;
> + int error;
> +
> + ddata = container_of(work, struct cpcap_phy_ddata, detect_work.work);
> +
> + error = cpcap_phy_get_ints_state(ddata, &s);
> + if (error)
> + return;
> +
> + /* See also cpcap-charger.c phy_companion for VBUS handling */
I think this companion should have ideally used extcon framework. Then we could
have used extcon_get_state() here.
> + if (s.id_ground) {
> + dev_info(ddata->dev, "id ground, USB host mode\n");
> + error = cpcap_usb_set_usb_mode(ddata);
> + if (error)
> + goto out_err;
> +
> + error = musb_mailbox(MUSB_ID_GROUND);
> + if (error)
> + goto out_err;
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
> + CPCAP_BIT_VBUSSTBY_EN,
> + CPCAP_BIT_VBUSSTBY_EN);
> + if (error)
> + goto out_err;
> +
> + return;
> + }
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
> + CPCAP_BIT_VBUSSTBY_EN, 0);
> + if (error)
> + goto out_err;
> +
> + vbus = cpcap_usb_vbus_valid(ddata);
> +
> + if (vbus) {
> + /* Are we connected to a docking station with vbus? */
> + if (s.id_ground) {
> + dev_info(ddata->dev, "connected to a dock\n");
> + error = cpcap_usb_set_usb_mode(ddata);
> + if (error)
> + goto out_err;
> + error = musb_mailbox(MUSB_ID_GROUND);
> + if (error)
> + goto out_err;
> +
> + return;
> + }
> +
> + /* Otherwise assume we're connected to a USB host */
> + dev_info(ddata->dev, "connected to USB host\n");
> + error = cpcap_usb_set_usb_mode(ddata);
> + if (error)
> + goto out_err;
> + error = musb_mailbox(MUSB_VBUS_VALID);
> + if (error)
> + goto out_err;
> +
> + return;
> + }
> +
> + /* Default to debug UART mode */
> + error = cpcap_usb_set_uart_mode(ddata);
> + if (error)
> + goto out_err;
> +
> + error = musb_mailbox(MUSB_VBUS_OFF);
> + if (error)
> + goto out_err;
> +
> + dev_info(ddata->dev, "set UART mode\n");
> +
> + return;
> +
> +out_err:
> + dev_err(ddata->dev, "error setting cable state: %i\n", error);
> +}
> +
> +static irqreturn_t cpcap_phy_irq_thread(int irq, void *data)
> +{
> + struct cpcap_phy_ddata *ddata = data;
> +
> + if (!atomic_read(&ddata->active))
> + return IRQ_NONE;
> +
> + schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int cpcap_usb_init_irq(struct platform_device *pdev,
> + struct cpcap_phy_ddata *ddata,
> + const char *name)
> +{
> + struct cpcap_interrupt_desc *d;
> + int irq, error;
> +
> + irq = platform_get_irq_byname(pdev, name);
> + if (!irq)
> + return -ENODEV;
> +
> + error = devm_request_threaded_irq(ddata->dev, irq, NULL,
> + cpcap_phy_irq_thread,
> + IRQF_SHARED,
> + name, ddata);
> + if (error) {
> + dev_err(ddata->dev, "could not get irq %s: %i\n",
> + name, error);
> +
> + return error;
> + }
> +
> + d = devm_kzalloc(ddata->dev, sizeof(*d), GFP_KERNEL);
> + if (!d)
> + return -ENOMEM;
> +
> + d->name = name;
> + d->irq = irq;
> + list_add(&d->node, &ddata->irq_list);
> +
> + return 0;
> +}
> +
> +static const char * const cpcap_phy_irqs[] = {
> + /* REG_INT_0 */
> + "id_ground", "id_float",
> +
> + /* REG_INT1 */
> + "se0conn", "vbusvld", "sessvld", "sessend", "se1",
> +
> + /* REG_INT_3 */
> + "dm", "dp",
> +};
> +
> +static int cpcap_usb_init_interrupts(struct platform_device *pdev,
> + struct cpcap_phy_ddata *ddata)
> +{
> + int i, error;
> +
> + for (i = 0; i < ARRAY_SIZE(cpcap_phy_irqs); i++) {
> + error = cpcap_usb_init_irq(pdev, ddata, cpcap_phy_irqs[i]);
> + if (error)
> + return error;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * Optional pins and modes. At least Motorola mapphone devices
> + * are using two GPIOs and dynamic pinctrl to multiplex PHY pins
> + * to UART, ULPI or UTMI mode.
> + */
> +
> +static int cpcap_usb_gpio_set_mode(struct cpcap_phy_ddata *ddata,
> + enum cpcap_gpio_mode mode)
> +{
> + if (!ddata->gpio[0] || !ddata->gpio[1])
> + return 0;
> +
> + gpiod_set_value(ddata->gpio[0], mode & 1);
> + gpiod_set_value(ddata->gpio[1], mode >> 1);
> +
> + return 0;
> +}
> +
> +static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
> +{
> + int error;
> +
> + error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
> + if (error)
> + goto out_err;
> +
> + if (ddata->pins_uart) {
> + error = pinctrl_select_state(ddata->pins, ddata->pins_uart);
> + if (error)
> + goto out_err;
> + }
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
> + CPCAP_BIT_VBUSPD,
> + CPCAP_BIT_VBUSPD);
> + if (error)
> + goto out_err;
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
> + 0xffff, CPCAP_BIT_UARTMUX0 |
> + CPCAP_BIT_EMUMODE0);
> + if (error)
> + goto out_err;
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, 0x7fff,
> + CPCAP_BIT_IDPU_SPI);
> + if (error)
> + goto out_err;
> +
> + return 0;
> +
> +out_err:
> + dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
> +
> + return error;
> +}
> +
> +static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
> +{
> + int error;
> +
> + error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
> + if (error)
> + return error;
> +
> + if (ddata->pins_utmi) {
> + error = pinctrl_select_state(ddata->pins, ddata->pins_utmi);
> + if (error) {
> + dev_err(ddata->dev, "could not set usb mode: %i\n",
> + error);
> +
> + return error;
> + }
> + }
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
> + CPCAP_BIT_VBUSPD, 0);
> + if (error)
> + goto out_err;
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
> + CPCAP_BIT_USBXCVREN,
> + CPCAP_BIT_USBXCVREN);
> + if (error)
> + goto out_err;
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
> + CPCAP_BIT_PU_SPI |
> + CPCAP_BIT_DMPD_SPI |
> + CPCAP_BIT_DPPD_SPI |
> + CPCAP_BIT_SUSPEND_SPI |
> + CPCAP_BIT_ULPI_SPI_SEL, 0);
> + if (error)
> + goto out_err;
> +
> + error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
> + CPCAP_BIT_USBXCVREN,
> + CPCAP_BIT_USBXCVREN);
> + if (error)
> + goto out_err;
> +
> + return 0;
> +
> +out_err:
> + dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
> +
> + return error;
> +}
> +
> +static int cpcap_usb_init_optional_pins(struct cpcap_phy_ddata *ddata)
> +{
> + ddata->pins = devm_pinctrl_get(ddata->dev);
> + if (IS_ERR(ddata->pins)) {
> + dev_info(ddata->dev, "default pins not configured: %ld\n",
> + PTR_ERR(ddata->pins));
> + ddata->pins = NULL;
> + }
> +
> + ddata->pins_ulpi = pinctrl_lookup_state(ddata->pins, "ulpi");
> + if (IS_ERR(ddata->pins_ulpi)) {
> + dev_info(ddata->dev, "ulpi pins not configured\n");
> + ddata->pins_ulpi = NULL;
> + }
> +
> + ddata->pins_utmi = pinctrl_lookup_state(ddata->pins, "utmi");
> + if (IS_ERR(ddata->pins_utmi)) {
> + dev_info(ddata->dev, "utmi pins not configured\n");
> + ddata->pins_utmi = NULL;
> + }
> +
> + ddata->pins_uart = pinctrl_lookup_state(ddata->pins, "uart");
> + if (IS_ERR(ddata->pins_uart)) {
> + dev_info(ddata->dev, "uart pins not configured\n");
> + ddata->pins_uart = NULL;
> + }
> +
> + if (ddata->pins_uart)
> + return pinctrl_select_state(ddata->pins, ddata->pins_uart);
> +
> + return 0;
> +}
> +
> +static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
> +{
> + int i;
> +
> + for (i = 0; i < 2; i++) {
> + ddata->gpio[i] = devm_gpiod_get_index(ddata->dev, "mode",
> + i, GPIOD_OUT_HIGH);
> + if (IS_ERR(ddata->gpio[i])) {
> + dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
> + i, PTR_ERR(ddata->gpio[i]));
> + ddata->gpio[i] = NULL;
> + }
> + }
> +}
> +
> +static int cpcap_usb_init_iio(struct cpcap_phy_ddata *ddata)
> +{
> + enum iio_chan_type type;
> + int error;
> +
> + ddata->vbus = devm_iio_channel_get(ddata->dev, "vbus");
> + if (IS_ERR(ddata->vbus)) {
> + error = PTR_ERR(ddata->vbus);
> + goto out_err;
> + }
> +
> + if (!ddata->vbus->indio_dev) {
> + error = -ENXIO;
> + goto out_err;
> + }
> +
> + error = iio_get_channel_type(ddata->vbus, &type);
> + if (error < 0)
> + goto out_err;
> +
> + if (type != IIO_VOLTAGE) {
> + error = -EINVAL;
> + goto out_err;
> + }
> +
> + return 0;
> +
> +out_err:
> + dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
> + error);
> +
> + return error;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id cpcap_usb_phy_id_table[] = {
> + {
> + .compatible = "motorola,cpcap-usb-phy",
> + },
> + {
> + .compatible = "motorola,mapphone-cpcap-usb-phy",
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, cpcap_usb_phy_id_table);
> +#endif
> +
> +static int cpcap_usb_phy_probe(struct platform_device *pdev)
> +{
> + struct cpcap_phy_ddata *ddata;
> + struct phy *generic_phy;
> + struct phy_provider *phy_provider;
> + struct usb_otg *otg;
> + const struct of_device_id *of_id;
> + int error;
> +
> + of_id = of_match_device(of_match_ptr(cpcap_usb_phy_id_table),
> + &pdev->dev);
> + if (!of_id)
> + return -EINVAL;
> +
> + ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
> + if (!ddata)
> + return -ENOMEM;
> +
> + ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!ddata->reg)
> + return -ENODEV;
> +
> + otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
> + if (!otg)
> + return -ENOMEM;
> +
> + ddata->dev = &pdev->dev;
> + ddata->phy.dev = ddata->dev;
> + ddata->phy.label = "cpcap_usb_phy";
> + ddata->phy.otg = otg;
> + ddata->phy.type = USB_PHY_TYPE_USB2;
> + INIT_LIST_HEAD(&ddata->irq_list);
> + otg->set_host = cpcap_usb_phy_set_host;
> + otg->set_peripheral = cpcap_usb_phy_set_peripheral;
> + otg->usb_phy = &ddata->phy;
> + mutex_init(&ddata->lock);
> + INIT_DELAYED_WORK(&ddata->detect_work, cpcap_usb_detect);
> + platform_set_drvdata(pdev, ddata);
> +
> + ddata->vusb = devm_regulator_get(&pdev->dev, "vusb");
> + if (IS_ERR(ddata->vusb))
> + return PTR_ERR(ddata->vusb);
> +
> + error = regulator_enable(ddata->vusb);
> + if (error)
> + return error;
Maybe we should create power_on ops and do regulator enable there?
Thanks
Kishon
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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 V4 3/4] dt-bindings: serial: add a new compatible string for SC9860
From: Chunyan Zhang @ 2017-03-27 6:23 UTC (permalink / raw)
To: Rob Herring
Cc: Chunyan Zhang, Mark Rutland,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org,
Catalin Marinas, Will Deacon, Arnd Bergmann, Mathieu Poirier,
Orson Zhai (翟京), Sudeep Holla,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <20170324023657.2iyh22lr52rme5bu@rob-hp-laptop>
Hi Rob,
On 24 March 2017 at 10:36, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Fri, Mar 17, 2017 at 01:51:37PM +0800, Chunyan Zhang wrote:
>> SC9860 use the same serial device which SC9836 uses, so added a new
>> compatible string to support SC9860 as well, also added an example
>> of how to describe this serial device in DT.
>>
>> Signed-off-by: Chunyan Zhang <chunyan.zhang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
>> ---
>> Documentation/devicetree/bindings/serial/sprd-uart.txt | 14 +++++++++++++-
>> 1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/serial/sprd-uart.txt b/Documentation/devicetree/bindings/serial/sprd-uart.txt
>> index 2aff0f2..1db5d6f 100644
>> --- a/Documentation/devicetree/bindings/serial/sprd-uart.txt
>> +++ b/Documentation/devicetree/bindings/serial/sprd-uart.txt
>> @@ -1,7 +1,19 @@
>> * Spreadtrum serial UART
>>
>> Required properties:
>> -- compatible: must be "sprd,sc9836-uart"
>> +- compatible: must be one of:
>> + * "sprd,sc9836-uart"
>> + * "sprd,sc9860-uart", "sprd,sc9836-uart"
>> +
>> - reg: offset and length of the register set for the device
>> - interrupts: exactly one interrupt specifier
>> - clocks: phandles to input clocks.
>> +
>> +Example:
>> + uart0: serial@000000 {
>
> serial@0
>
Addressed this.
> With that,
>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Thanks for your review,
Chunyan
>
>
>> + compatible = "sprd,sc9860-uart",
>> + "sprd,sc9836-uart";
>> + reg = <0x000000 0x100>;
>> + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&ext_26m>;
>> + };
>> --
>> 2.7.4
>>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v5 7/7] mfd: dt-bindings: Add RK805 device tree bindings document
From: Elaine Zhang @ 2017-03-27 6:23 UTC (permalink / raw)
To: lee.jones-QSEj5FYQhm4dnm+yROfE0A,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
Cc: huangtao-TNX95d0MmH7DzftRWevZcw, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA, xxx-TNX95d0MmH7DzftRWevZcw,
Elaine Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, w.egorov-guT5V/WYfQezQB+pC5nmwQ,
chenjh-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <1490595705-28844-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add device tree bindings documentation for Rockchip's RK805 PMIC.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
Documentation/devicetree/bindings/mfd/rk808.txt | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt
index 9636ae8d8d41..bfd94b3d1f90 100644
--- a/Documentation/devicetree/bindings/mfd/rk808.txt
+++ b/Documentation/devicetree/bindings/mfd/rk808.txt
@@ -1,11 +1,12 @@
RK8XX Power Management Integrated Circuit
The rk8xx family current members:
+rk805
rk808
rk818
Required properties:
-- compatible: "rockchip,rk808", "rockchip,rk818"
+- compatible: "rockchip,rk805", "rockchip,rk808", "rockchip,rk818"
- reg: I2C slave address
- interrupt-parent: The parent interrupt controller.
- interrupts: the interrupt outputs of the controller.
@@ -18,6 +19,14 @@ Optional properties:
- rockchip,system-power-controller: Telling whether or not this pmic is controlling
the system power.
+Optional RK805 properties:
+- vcc1-supply: The input supply for DCDC_REG1
+- vcc2-supply: The input supply for DCDC_REG2
+- vcc3-supply: The input supply for DCDC_REG3
+- vcc4-supply: The input supply for DCDC_REG4
+- vcc5-supply: The input supply for LDO_REG1 and LDO_REG2
+- vcc6-supply: The input supply for LDO_REG3
+
Optional RK808 properties:
- vcc1-supply: The input supply for DCDC_REG1
- vcc2-supply: The input supply for DCDC_REG2
@@ -56,6 +65,15 @@ by a child node of the 'regulators' node.
/* standard regulator bindings here */
};
+Following regulators of the RK805 PMIC regulators are supported. Note that
+the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
+number as described in RK805 datasheet.
+
+ - DCDC_REGn
+ - valid values for n are 1 to 4.
+ - LDO_REGn
+ - valid values for n are 1 to 3
+
Following regulators of the RK808 PMIC block are supported. Note that
the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
number as described in RK808 datasheet.
--
1.9.1
^ permalink raw reply related
* [PATCH v5 6/7] rtc: Kconfig: Name RK805 in Kconfig for RTC_DRV_RK808
From: Elaine Zhang @ 2017-03-27 6:23 UTC (permalink / raw)
To: lee.jones-QSEj5FYQhm4dnm+yROfE0A,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
Cc: huangtao-TNX95d0MmH7DzftRWevZcw, xxx-TNX95d0MmH7DzftRWevZcw,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
chenjh-TNX95d0MmH7DzftRWevZcw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
w.egorov-guT5V/WYfQezQB+pC5nmwQ, Elaine Zhang
In-Reply-To: <1490595705-28844-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
The RK808 and RK805 PMICs are using a similar register map.
We can reuse the rtc driver for the RK805 PMIC. So let's add
the RK805 in the Kconfig description.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
drivers/rtc/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 5dc673dc9487..47d6a8df06db 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -352,11 +352,11 @@ config RTC_DRV_MAX77686
will be called rtc-max77686.
config RTC_DRV_RK808
- tristate "Rockchip RK808/RK818 RTC"
+ tristate "Rockchip RK805/RK808/RK818 RTC"
depends on MFD_RK808
help
If you say yes here you will get support for the
- RTC of RK808 and RK818 PMIC.
+ RTC of RK805, RK808 and RK818 PMIC.
This driver can also be built as a module. If so, the module
will be called rk808-rtc.
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 3/3] Add XRA1403 support to MAINTAINERS file
From: Nandor Han @ 2017-03-27 6:23 UTC (permalink / raw)
To: linus.walleij, gnurou, robh+dt, mark.rutland, linux-gpio,
devicetree, linux-kernel
Cc: Nandor Han
In-Reply-To: <cover.1490595641.git.nandor.han@ge.com>
Add the XRA1403 support to MAINTAINERS list.
Signed-off-by: Nandor Han <nandor.han@ge.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 58b3a22..539c88c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13903,6 +13903,14 @@ L: linux-kernel@vger.kernel.org
S: Supported
F: drivers/char/xillybus/
+XRA1403 GPIO EXPANDER
+M: Nandor Han <nandor.han@ge.com>
+M: Semi Malinen <semi.malinen@ge.com>
+L: linux-gpio@vger.kernel.org
+S: Maintained
+F: drivers/gpio/gpio-xra1403.c
+F: Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
+
XTENSA XTFPGA PLATFORM SUPPORT
M: Max Filippov <jcmvbkbc@gmail.com>
L: linux-xtensa@linux-xtensa.org
--
2.10.1
^ permalink raw reply related
* [PATCH 2/3] doc,dts - add XRA1403 DTS binding documentation
From: Nandor Han @ 2017-03-27 6:23 UTC (permalink / raw)
To: linus.walleij, gnurou, robh+dt, mark.rutland, linux-gpio,
devicetree, linux-kernel
Cc: Nandor Han
In-Reply-To: <cover.1490595641.git.nandor.han@ge.com>
Add the XRA1403 DTS binding documentation.
Signed-off-by: Nandor Han <nandor.han@ge.com>
---
.../devicetree/bindings/gpio/gpio-xra1403.txt | 37 ++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
diff --git a/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
new file mode 100644
index 0000000..ccf5337
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
@@ -0,0 +1,37 @@
+GPIO Driver for XRA1403 16-BIT GPIO Expander With Reset Input from EXAR
+
+The XRA1403 is an 16-bit GPIO expander with an SPI interface. Features available:
+ - Individually programmable inputs:
+ - Internal pull-up resistors
+ - Polarity inversion
+ - Individual interrupt enable
+ - Rising edge and/or Falling edge interrupt
+ - Input filter
+ - Individually programmable outputs
+ - Output Level Control
+ - Output Three-State Control
+
+Properties
+----------
+Check documentation for SPI and GPIO controllers regarding properties needed to configure the node.
+
+ - compatible = "exar,xra1403".
+ - reg = SPI id of the device.
+ - gpio-controller: mark the node as gpio.
+
+Optional properties:
+-------------------
+ - reset-gpios: in case available used to control the device reset line.
+
+Example
+--------
+
+ gpioxra0: gpio@2 {
+ compatible = "exar,xra1403";
+ reg = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
+ spi-max-frequency = <1000000>;
+ status = "okay";
+ };
--
2.10.1
^ permalink raw reply related
* [PATCH 1/3] gpio - Add EXAR XRA1403 SPI GPIO expander driver
From: Nandor Han @ 2017-03-27 6:23 UTC (permalink / raw)
To: linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
gnurou-Re5JQEeQqe8AvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, linux-gpio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Nandor Han, Semi Malinen
In-Reply-To: <cover.1490595641.git.nandor.han-JJi787mZWgc@public.gmane.org>
This is a simple driver that provides a /sys/class/gpio
interface for controlling and configuring the GPIO lines.
It does not provide support for chip select or interrupts.
Signed-off-by: Nandor Han <nandor.han-JJi787mZWgc@public.gmane.org>
Signed-off-by: Semi Malinen <semi.malinen-JJi787mZWgc@public.gmane.org>
---
.../devicetree/bindings/vendor-prefixes.txt | 1 +
drivers/gpio/Kconfig | 5 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-xra1403.c | 252 +++++++++++++++++++++
4 files changed, 259 insertions(+)
create mode 100644 drivers/gpio/gpio-xra1403.c
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0ad67d5..7ca9d41 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -103,6 +103,7 @@ ettus NI Ettus Research
eukrea Eukréa Electromatique
everest Everest Semiconductor Co. Ltd.
everspin Everspin Technologies, Inc.
+exar Exar Corporation
excito Excito
ezchip EZchip Semiconductor
faraday Faraday Technology Corporation
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d6e3cfd..3a6c9a3 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1208,6 +1208,11 @@ config GPIO_PISOSR
GPIO driver for SPI compatible parallel-in/serial-out shift
registers. These are input only devices.
+config GPIO_XRA1403
+ tristate "EXAR XRA1403 16-bit GPIO expander"
+ help
+ GPIO driver for EXAR XRA1403 16-bit SPI-based GPIO expander.
+
endmenu
menu "SPI or I2C GPIO expanders"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index bd995dc..8f50844 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -139,6 +139,7 @@ obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o
obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o
+obj-$(CONFIG_GPIO_XRA1403) += gpio-xra1403.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c
new file mode 100644
index 0000000..1b7138a8
--- /dev/null
+++ b/drivers/gpio/gpio-xra1403.c
@@ -0,0 +1,252 @@
+/*
+ * GPIO driver for EXAR XRA1403 16-bit GPIO expander
+ *
+ * Copyright (c) 2017, General Electric Company
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+
+/* XRA1403 registers */
+#define XRA_GSR 0x00 /* GPIO State */
+#define XRA_OCR 0x02 /* Output Control */
+#define XRA_GCR 0x06 /* GPIO Configuration */
+
+/* SPI headers */
+#define XRA_READ 0x80 /* read bit of the SPI command byte */
+
+struct xra1403 {
+ struct mutex lock;
+ struct gpio_chip chip;
+ struct spi_device *spi;
+};
+
+static int xra1403_get_byte(struct xra1403 *xra, unsigned int addr)
+{
+ return spi_w8r8(xra->spi, XRA_READ | (addr << 1));
+}
+
+static int xra1403_get_bit(struct xra1403 *xra, unsigned int addr,
+ unsigned int bit)
+{
+ int ret;
+
+ ret = xra1403_get_byte(xra, addr + (bit > 7));
+ if (ret < 0)
+ return ret;
+
+ return !!(ret & BIT(bit % 8));
+}
+
+static int xra1403_set_bit(struct xra1403 *xra, unsigned int addr,
+ unsigned int bit, int value)
+{
+ int ret;
+ u8 mask;
+ u8 tx[2];
+
+ addr += bit > 7;
+
+ mutex_lock(&xra->lock);
+
+ ret = xra1403_get_byte(xra, addr);
+ if (ret < 0)
+ goto out_unlock;
+
+ mask = BIT(bit % 8);
+ if (value)
+ value = ret | mask;
+ else
+ value = ret & ~mask;
+
+ if (value != ret) {
+ tx[0] = addr << 1;
+ tx[1] = value;
+ ret = spi_write(xra->spi, tx, sizeof(tx));
+ } else {
+ ret = 0;
+ }
+
+out_unlock:
+ mutex_unlock(&xra->lock);
+
+ return ret;
+}
+
+static int xra1403_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+ return xra1403_set_bit(gpiochip_get_data(chip), XRA_GCR, offset, 1);
+}
+
+static int xra1403_direction_output(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ int ret;
+ struct xra1403 *xra = gpiochip_get_data(chip);
+
+ ret = xra1403_set_bit(xra, XRA_OCR, offset, value);
+ if (ret)
+ return ret;
+
+ ret = xra1403_set_bit(xra, XRA_GCR, offset, 0);
+
+ return ret;
+}
+
+static int xra1403_get(struct gpio_chip *chip, unsigned int offset)
+{
+ return xra1403_get_bit(gpiochip_get_data(chip), XRA_GSR, offset);
+}
+
+static void xra1403_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ xra1403_set_bit(gpiochip_get_data(chip), XRA_OCR, offset, value);
+}
+
+#ifdef CONFIG_DEBUG_FS
+#define XRA_REGS 0x16
+static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ int reg;
+ struct xra1403 *xra = gpiochip_get_data(chip);
+ int value[XRA_REGS];
+ int i;
+ unsigned int gcr;
+ unsigned int gsr;
+
+ seq_puts(s, "xra reg:");
+ for (reg = 0; reg < XRA_REGS; reg++)
+ seq_printf(s, " %2.2x", reg);
+ seq_puts(s, "\n value:");
+ for (reg = 0; reg < XRA_REGS; reg++) {
+ value[reg] = xra1403_get_byte(xra, reg);
+ seq_printf(s, " %2.2x", value[reg]);
+ }
+ seq_puts(s, "\n");
+
+ gcr = value[XRA_GCR + 1] << 8 | value[XRA_GCR];
+ gsr = value[XRA_GSR + 1] << 8 | value[XRA_GSR];
+ for (i = 0; i < chip->ngpio; i++) {
+ const char *label = gpiochip_is_requested(chip, i);
+
+ if (!label)
+ continue;
+
+ seq_printf(s, " gpio-%-3d (%-12s) %s %s\n",
+ chip->base + i, label,
+ (gcr & BIT(i)) ? "in" : "out",
+ (gsr & BIT(i)) ? "hi" : "lo");
+ }
+}
+#else
+#define xra1403_dbg_show NULL
+#endif
+
+static int xra1403_probe(struct spi_device *spi)
+{
+ struct xra1403 *xra;
+ struct gpio_desc *reset_gpio;
+
+ xra = devm_kzalloc(&spi->dev, sizeof(*xra), GFP_KERNEL);
+ if (!xra)
+ return -ENOMEM;
+
+ /* bring the chip out of reset */
+ reset_gpio = gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ dev_warn(&spi->dev, "could not get reset-gpios\n");
+ else if (reset_gpio)
+ gpiod_put(reset_gpio);
+
+ mutex_init(&xra->lock);
+
+ xra->chip.direction_input = xra1403_direction_input;
+ xra->chip.direction_output = xra1403_direction_output;
+ xra->chip.get = xra1403_get;
+ xra->chip.set = xra1403_set;
+ xra->chip.dbg_show = xra1403_dbg_show;
+
+ xra->chip.ngpio = 16;
+ xra->chip.label = "xra1403";
+
+ xra->chip.base = -1;
+ xra->chip.can_sleep = true;
+ xra->chip.parent = &spi->dev;
+ xra->chip.owner = THIS_MODULE;
+
+ xra->spi = spi;
+ spi_set_drvdata(spi, xra);
+
+ return gpiochip_add_data(&xra->chip, xra);
+}
+
+static int xra1403_remove(struct spi_device *spi)
+{
+ struct xra1403 *xra = spi_get_drvdata(spi);
+
+ gpiochip_remove(&xra->chip);
+
+ return 0;
+}
+
+static const struct spi_device_id xra1403_ids[] = {
+ { "xra1403" },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, xra1403_ids);
+
+static const struct of_device_id xra1403_spi_of_match[] = {
+ { .compatible = "exar,xra1403" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xra1403_spi_of_match);
+
+static struct spi_driver xra1403_driver = {
+ .probe = xra1403_probe,
+ .remove = xra1403_remove,
+ .id_table = xra1403_ids,
+ .driver = {
+ .name = "xra1403",
+ .of_match_table = of_match_ptr(xra1403_spi_of_match),
+ },
+};
+
+static int __init xra1403_init(void)
+{
+ return spi_register_driver(&xra1403_driver);
+}
+
+/*
+ * register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(xra1403_init);
+
+static void __exit xra1403_exit(void)
+{
+ spi_unregister_driver(&xra1403_driver);
+}
+module_exit(xra1403_exit);
+
+MODULE_AUTHOR("Nandor Han <nandor.han-JJi787mZWgc@public.gmane.org>");
+MODULE_AUTHOR("Semi Malinen <semi.malinen-JJi787mZWgc@public.gmane.org>");
+MODULE_DESCRIPTION("GPIO expander driver for EXAR XRA1403");
+MODULE_LICENSE("GPL v2");
--
2.10.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v5 5/7] clk: Kconfig: Name RK805 in Kconfig for COMMON_CLK_RK808
From: Elaine Zhang @ 2017-03-27 6:23 UTC (permalink / raw)
To: lee.jones-QSEj5FYQhm4dnm+yROfE0A,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
Cc: huangtao-TNX95d0MmH7DzftRWevZcw, xxx-TNX95d0MmH7DzftRWevZcw,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
chenjh-TNX95d0MmH7DzftRWevZcw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
w.egorov-guT5V/WYfQezQB+pC5nmwQ, Elaine Zhang
In-Reply-To: <1490595705-28844-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
The RK808 and RK805 PMICs are using a similar register map.
We can reuse the clk driver for the RK805 PMIC. So let's add
the RK805 in the Kconfig description.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
drivers/clk/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9356ab4b7d76..7ca8f02a1232 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -39,10 +39,10 @@ config COMMON_CLK_MAX77686
clock.
config COMMON_CLK_RK808
- tristate "Clock driver for RK808/RK818"
+ tristate "Clock driver for RK805/RK808/RK818"
depends on MFD_RK808
---help---
- This driver supports RK808 and RK818 crystal oscillator clock. These
+ This driver supports RK805, RK808 and RK818 crystal oscillator clock. These
multi-function devices have two fixed-rate oscillators,
clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
by control register.
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/3] XRA1403,gpio - add XRA1403 gpio expander driver
From: Nandor Han @ 2017-03-27 6:22 UTC (permalink / raw)
To: linus.walleij, gnurou, robh+dt, mark.rutland, linux-gpio,
devicetree, linux-kernel
Cc: Nandor Han
The patchset will add a driver to support basic functionality for
XRA1403 device. Features supported:
- configure gpin as input/out
- get/set gpio status
Documentation: A gpio-xra1403.txt file was added to document the DTS
bindings related to driver.
Testing:
1. XRA1403 connected to iMX53 MCU
2. Export gpio from userspace
3. Verify that corresponding gpio directories are created
in `/sys/class/gpio/gpioXX`
4. Export gpios from first and second bank as output
5. Set the output gpio pin to high/low and verify with the
oscilloscope that gpio status is according with the configured
value.
Nandor Han (3):
gpio - Add EXAR XRA1403 SPI GPIO expander driver
doc,dts - add XRA1403 DTS binding documentation
Add XRA1403 support to MAINTAINERS file
.../devicetree/bindings/gpio/gpio-xra1403.txt | 37 +++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
MAINTAINERS | 8 +
drivers/gpio/Kconfig | 5 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-xra1403.c | 252 +++++++++++++++++++++
6 files changed, 304 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
create mode 100644 drivers/gpio/gpio-xra1403.c
--
2.10.1
^ permalink raw reply
* [PATCH v5 4/7] mfd: rk808: Add RK805 support
From: Elaine Zhang @ 2017-03-27 6:21 UTC (permalink / raw)
To: lee.jones-QSEj5FYQhm4dnm+yROfE0A,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
Cc: huangtao-TNX95d0MmH7DzftRWevZcw, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA, xxx-TNX95d0MmH7DzftRWevZcw,
Elaine Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, w.egorov-guT5V/WYfQezQB+pC5nmwQ,
chenjh-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <1490595705-28844-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
The RK805 chip is a Power Management IC (PMIC) for multimedia and handheld
devices. It contains the following components:
- Regulators
- RTC
- Clocking
Both RK808 and RK805 chips are using a similar register map,
so we can reuse the RTC and Clocking functionality.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
drivers/mfd/Kconfig | 4 +-
drivers/mfd/rk808.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 55ecdfb74d31..b410a348b756 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -892,13 +892,13 @@ config MFD_RC5T583
different functionality of the device.
config MFD_RK808
- tristate "Rockchip RK808/RK818 Power Management Chip"
+ tristate "Rockchip RK805/RK808/RK818 Power Management Chip"
depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
- If you say yes here you get support for the RK808 and RK818
+ If you say yes here you get support for the RK805, RK808 and RK818
Power Management chips.
This driver provides common support for accessing the device
through I2C interface. The device supports multiple sub-devices
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index 3334a2a7f3fb..7276555f0630 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -70,6 +70,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
.volatile_reg = rk808_is_volatile_reg,
};
+static const struct regmap_config rk805_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK805_OFF_SOURCE_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = rk808_is_volatile_reg,
+};
+
static const struct regmap_config rk808_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -86,6 +94,16 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
}
};
+static const struct mfd_cell rk805s[] = {
+ { .name = "rk808-clkout", },
+ { .name = "rk808-regulator", },
+ {
+ .name = "rk808-rtc",
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resources = &rtc_resources[0],
+ },
+};
+
static const struct mfd_cell rk808s[] = {
{ .name = "rk808-clkout", },
{ .name = "rk808-regulator", },
@@ -106,6 +124,20 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
},
};
+static const struct rk808_reg_data rk805_pre_init_reg[] = {
+ {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
+ RK805_BUCK1_2_ILMAX_4000MA},
+ {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
+ RK805_BUCK1_2_ILMAX_4000MA},
+ {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
+ RK805_BUCK3_ILMAX_3000MA},
+ {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
+ RK805_BUCK4_ILMAX_3500MA},
+ {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA},
+ {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN},
+ {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},
+};
+
static const struct rk808_reg_data rk808_pre_init_reg[] = {
{ RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
{ RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
@@ -135,6 +167,41 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
VB_LO_SEL_3500MV },
};
+static const struct regmap_irq rk805_irqs[] = {
+ [RK805_IRQ_PWRON_RISE] = {
+ .mask = RK805_IRQ_PWRON_RISE_MSK,
+ .reg_offset = 0,
+ },
+ [RK805_IRQ_VB_LOW] = {
+ .mask = RK805_IRQ_VB_LOW_MSK,
+ .reg_offset = 0,
+ },
+ [RK805_IRQ_PWRON] = {
+ .mask = RK805_IRQ_PWRON_MSK,
+ .reg_offset = 0,
+ },
+ [RK805_IRQ_PWRON_LP] = {
+ .mask = RK805_IRQ_PWRON_LP_MSK,
+ .reg_offset = 0,
+ },
+ [RK805_IRQ_HOTDIE] = {
+ .mask = RK805_IRQ_HOTDIE_MSK,
+ .reg_offset = 0,
+ },
+ [RK805_IRQ_RTC_ALARM] = {
+ .mask = RK805_IRQ_RTC_ALARM_MSK,
+ .reg_offset = 0,
+ },
+ [RK805_IRQ_RTC_PERIOD] = {
+ .mask = RK805_IRQ_RTC_PERIOD_MSK,
+ .reg_offset = 0,
+ },
+ [RK805_IRQ_PWRON_FALL] = {
+ .mask = RK805_IRQ_PWRON_FALL_MSK,
+ .reg_offset = 0,
+ },
+};
+
static const struct regmap_irq rk808_irqs[] = {
/* INT_STS */
[RK808_IRQ_VOUT_LO] = {
@@ -247,6 +314,17 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
},
};
+static struct regmap_irq_chip rk805_irq_chip = {
+ .name = "rk805",
+ .irqs = rk805_irqs,
+ .num_irqs = ARRAY_SIZE(rk805_irqs),
+ .num_regs = 1,
+ .status_base = RK805_INT_STS_REG,
+ .mask_base = RK805_INT_STS_MSK_REG,
+ .ack_base = RK805_INT_STS_REG,
+ .init_ack_masked = true,
+};
+
static const struct regmap_irq_chip rk808_irq_chip = {
.name = "rk808",
.irqs = rk808_irqs,
@@ -272,6 +350,25 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
};
static struct i2c_client *rk808_i2c_client;
+
+static void rk805_device_shutdown(void)
+{
+ int ret;
+ struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
+
+ if (!rk808) {
+ dev_warn(&rk808_i2c_client->dev,
+ "have no rk805, so do nothing here\n");
+ return;
+ }
+
+ ret = regmap_update_bits(rk808->regmap,
+ RK805_DEV_CTRL_REG,
+ DEV_OFF, DEV_OFF);
+ if (ret)
+ dev_err(&rk808_i2c_client->dev, "power off error!\n");
+}
+
static void rk808_device_shutdown(void)
{
int ret;
@@ -309,6 +406,7 @@ static void rk818_device_shutdown(void)
}
static const struct of_device_id rk808_of_match[] = {
+ { .compatible = "rockchip,rk805" },
{ .compatible = "rockchip,rk808" },
{ .compatible = "rockchip,rk818" },
{ },
@@ -352,6 +450,15 @@ static int rk808_probe(struct i2c_client *client,
dev_info(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant);
switch (rk808->variant) {
+ case RK805_ID:
+ rk808->regmap_cfg = &rk805_regmap_config;
+ rk808->regmap_irq_chip = &rk805_irq_chip;
+ pre_init_reg = rk805_pre_init_reg;
+ nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
+ cells = rk805s;
+ nr_cells = ARRAY_SIZE(rk805s);
+ pm_pwroff_fn = rk805_device_shutdown;
+ break;
case RK808_ID:
rk808->regmap_cfg = &rk808_regmap_config;
rk808->regmap_irq_chip = &rk808_irq_chip;
@@ -444,6 +551,7 @@ static int rk808_remove(struct i2c_client *client)
}
static const struct i2c_device_id rk808_ids[] = {
+ { "rk805" },
{ "rk808" },
{ "rk818" },
{ },
--
1.9.1
^ permalink raw reply related
* [PATCH v5 3/7] regulator: rk808: Add regulator driver for RK805
From: Elaine Zhang @ 2017-03-27 6:21 UTC (permalink / raw)
To: lee.jones-QSEj5FYQhm4dnm+yROfE0A,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
Cc: huangtao-TNX95d0MmH7DzftRWevZcw, mark.rutland-5wv7dgnIgG8,
devicetree-u79uwXL29TY76Z2rM5mHXA, xxx-TNX95d0MmH7DzftRWevZcw,
Elaine Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, w.egorov-guT5V/WYfQezQB+pC5nmwQ,
chenjh-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <1490595705-28844-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add support for the rk805 regulator. The regulator module consists
of 4 DCDCs, 3 LDOs.
The output voltages are configurable and are meant to supply power
to the main processor and other components.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
drivers/regulator/Kconfig | 4 +-
drivers/regulator/rk808-regulator.c | 130 ++++++++++++++++++++++++++++++++++++
2 files changed, 132 insertions(+), 2 deletions(-)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index be06eb29c681..285e28051219 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -650,11 +650,11 @@ config REGULATOR_RC5T583
outputs which can be controlled by i2c communication.
config REGULATOR_RK808
- tristate "Rockchip RK808/RK818 Power regulators"
+ tristate "Rockchip RK805/RK808/RK818 Power regulators"
depends on MFD_RK808
help
Select this option to enable the power regulator of ROCKCHIP
- PMIC RK808 and RK818.
+ PMIC RK805,RK808 and RK818.
This driver supports the control of different power rails of device
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index fb44d5215e30..128c81e19ee8 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -65,6 +65,27 @@
/* max steps for increase voltage of Buck1/2, equal 100mv*/
#define MAX_STEPS_ONE_TIME 8
+#define RK805_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _etime) \
+ [_id] = { \
+ .name = (_match), \
+ .supply_name = (_supply), \
+ .of_match = of_match_ptr(_match), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .type = REGULATOR_VOLTAGE, \
+ .id = (_id), \
+ .n_voltages = (((_max) - (_min)) / (_step) + 1), \
+ .owner = THIS_MODULE, \
+ .min_uV = (_min) * 1000, \
+ .uV_step = (_step) * 1000, \
+ .vsel_reg = (_vreg), \
+ .vsel_mask = (_vmask), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
+ .enable_time = (_etime), \
+ .ops = &rk805_reg_ops, \
+ }
+
#define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _etime) \
[_id] = { \
@@ -298,6 +319,28 @@ static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv)
sel);
}
+static int rk805_set_suspend_enable(struct regulator_dev *rdev)
+{
+ unsigned int reg;
+
+ reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
+
+ return regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->enable_mask,
+ rdev->desc->enable_mask);
+}
+
+static int rk805_set_suspend_disable(struct regulator_dev *rdev)
+{
+ unsigned int reg;
+
+ reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
+
+ return regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->enable_mask,
+ 0);
+}
+
static int rk808_set_suspend_enable(struct regulator_dev *rdev)
{
unsigned int reg;
@@ -320,6 +363,27 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
rdev->desc->enable_mask);
}
+static struct regulator_ops rk805_reg_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_voltage = rk808_set_suspend_voltage,
+ .set_suspend_enable = rk805_set_suspend_enable,
+ .set_suspend_disable = rk805_set_suspend_disable,
+};
+
+static struct regulator_ops rk805_switch_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = rk805_set_suspend_enable,
+ .set_suspend_disable = rk805_set_suspend_disable,
+};
+
static struct regulator_ops rk808_buck1_2_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
@@ -369,6 +433,68 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
.set_suspend_disable = rk808_set_suspend_disable,
};
+static const struct regulator_desc rk805_reg[] = {
+ {
+ .name = "DCDC_REG1",
+ .supply_name = "vcc1",
+ .of_match = of_match_ptr("DCDC_REG1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK805_ID_DCDC1,
+ .ops = &rk805_reg_ops,
+ .type = REGULATOR_VOLTAGE,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK805_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK805_DCDC_EN_REG,
+ .enable_mask = BIT(0),
+ .owner = THIS_MODULE,
+ }, {
+ .name = "DCDC_REG2",
+ .supply_name = "vcc2",
+ .of_match = of_match_ptr("DCDC_REG2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK805_ID_DCDC2,
+ .ops = &rk805_reg_ops,
+ .type = REGULATOR_VOLTAGE,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK805_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK805_DCDC_EN_REG,
+ .enable_mask = BIT(1),
+ .owner = THIS_MODULE,
+ }, {
+ .name = "DCDC_REG3",
+ .supply_name = "vcc3",
+ .of_match = of_match_ptr("DCDC_REG3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK805_ID_DCDC3,
+ .ops = &rk805_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 1,
+ .enable_reg = RK805_DCDC_EN_REG,
+ .enable_mask = BIT(2),
+ .owner = THIS_MODULE,
+ },
+
+ RK805_DESC(RK805_ID_DCDC4, "DCDC_REG4", "vcc4", 800, 3400, 100,
+ RK805_BUCK4_ON_VSEL_REG, RK818_BUCK4_VSEL_MASK,
+ RK805_DCDC_EN_REG, BIT(3), 0),
+
+ RK805_DESC(RK805_ID_LDO1, "LDO_REG1", "vcc5", 800, 3400, 100,
+ RK805_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK805_LDO_EN_REG,
+ BIT(0), 400),
+ RK805_DESC(RK805_ID_LDO2, "LDO_REG2", "vcc5", 800, 3400, 100,
+ RK805_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK805_LDO_EN_REG,
+ BIT(1), 400),
+ RK805_DESC(RK805_ID_LDO3, "LDO_REG3", "vcc6", 800, 3400, 100,
+ RK805_LDO3_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK805_LDO_EN_REG,
+ BIT(2), 400),
+};
+
static const struct regulator_desc rk808_reg[] = {
{
.name = "DCDC_REG1",
@@ -625,6 +751,10 @@ static int rk808_regulator_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pdata);
switch (rk808->variant) {
+ case RK805_ID:
+ regulators = rk805_reg;
+ nregulators = RK805_NUM_REGULATORS;
+ break;
case RK808_ID:
regulators = rk808_reg;
nregulators = RK808_NUM_REGULATORS;
--
1.9.1
^ 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