Devicetree
 help / color / mirror / Atom feed
* [PATCH 4/4] clk: ti: omap4: set default-parents and default-rates using DT
From: Tero Kristo @ 2014-02-13  9:00 UTC (permalink / raw)
  To: linux-omap, mturquette; +Cc: linux-arm-kernel, devicetree
In-Reply-To: <1392282048-6284-1-git-send-email-t-kristo@ti.com>

Setup dpll_usb_ck and dpll_abe_ck using DT properties instead of hardcoding
the parents and rates in kernel.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/boot/dts/omap4.dtsi |   12 ++++++++++++
 drivers/clk/ti/clk-44xx.c    |   42 ------------------------------------------
 2 files changed, 12 insertions(+), 42 deletions(-)

diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index d3f8a6e..282ce66 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -761,3 +761,15 @@
 };
 
 /include/ "omap44xx-clocks.dtsi"
+
+&dpll_usb_ck {
+	default-rate = <960000000>;
+};
+
+&dpll_abe_ck {
+	default-rate = <98304000>;
+};
+
+&abe_dpll_refclk_mux_ck {
+	ti,default-parent = <&sys_32k_ck>;
+};
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
index ae00218..bc14a49 100644
--- a/drivers/clk/ti/clk-44xx.c
+++ b/drivers/clk/ti/clk-44xx.c
@@ -16,21 +16,6 @@
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 
-/*
- * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
- * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
- * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
- * half of this value.
- */
-#define OMAP4_DPLL_ABE_DEFFREQ				98304000
-
-/*
- * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
- * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
- * locked frequency for the USB DPLL is 960MHz.
- */
-#define OMAP4_DPLL_USB_DEFFREQ				960000000
-
 static struct ti_dt_clk omap44xx_clks[] = {
 	DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"),
 	DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
@@ -281,36 +266,9 @@ static struct ti_dt_clk omap44xx_clks[] = {
 
 int __init omap4xxx_dt_clk_init(void)
 {
-	int rc;
-	struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
-
 	ti_dt_clocks_register(omap44xx_clks);
 
 	omap2_clk_disable_autoidle_all();
 
-	/*
-	 * Lock USB DPLL on OMAP4 devices so that the L3INIT power
-	 * domain can transition to retention state when not in use.
-	 */
-	usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
-	rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
-	if (rc)
-		pr_err("%s: failed to configure USB DPLL!\n", __func__);
-
-	/*
-	 * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
-	 * state when turning the ABE clock domain. Workaround this by
-	 * locking the ABE DPLL on boot.
-	 * Lock the ABE DPLL in any case to avoid issues with audio.
-	 */
-	abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
-	sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
-	rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
-	abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
-	if (!rc)
-		rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
-	if (rc)
-		pr_err("%s: failed to configure ABE DPLL!\n", __func__);
-
 	return 0;
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 3/4] clk: ti: add support for default-rate property from DT
From: Tero Kristo @ 2014-02-13  9:00 UTC (permalink / raw)
  To: linux-omap, mturquette; +Cc: linux-arm-kernel, devicetree
In-Reply-To: <1392282048-6284-1-git-send-email-t-kristo@ti.com>

default-rate property can now be used to define default rates for clocks,
which get configured during boot.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/prm_common.c |    2 ++
 drivers/clk/ti/clk.c             |    1 +
 2 files changed, 3 insertions(+)

diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index b4c4ab9..4703545 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -528,5 +528,7 @@ int __init of_prcm_init(void)
 
 	ti_dt_clockdomains_setup();
 
+	of_clk_set_init_rates();
+
 	return 0;
 }
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index b1a6f71..23998b7 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -156,6 +156,7 @@ void ti_dt_clk_init_provider(struct device_node *parent, int index)
 		clk_init_cb = (of_clk_init_cb_t)match->data;
 		pr_debug("%s: initializing: %s\n", __func__, np->name);
 		clk_init_cb(np);
+		of_clk_parse_init_rate(np, NULL);
 	}
 
 	list_for_each_entry_safe(retry, tmp, &retry_list, link) {
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 2/4] clk: add support for default-rate
From: Tero Kristo @ 2014-02-13  9:00 UTC (permalink / raw)
  To: linux-omap, mturquette; +Cc: linux-arm-kernel, devicetree
In-Reply-To: <1392282048-6284-1-git-send-email-t-kristo@ti.com>

default-rate property can now be used to set initial rates for clocks.
This is added by default for all clocks which get initialized through
of_clk_init().

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 .../devicetree/bindings/clock/clock-bindings.txt   |    9 ++
 drivers/clk/clk.c                                  |   86 ++++++++++++++++++++
 include/linux/clk-provider.h                       |    2 +
 3 files changed, 97 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 7c52c29..d676112 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -44,6 +44,15 @@ For example:
   clocks by index. The names should reflect the clock output signal
   names for the device.
 
+default-rate:	Sets the rate of the clock during boot to the provided
+		rate.
+
+For example:
+
+    clk-divider {
+        default-rate = <1000000>;
+    };
+
 ==Clock consumers==
 
 Required properties:
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5517944..cb144e4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2526,6 +2526,89 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
 }
 EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
 
+static LIST_HEAD(clk_init_info_list);
+
+struct clk_init_info {
+	struct device_node *node;
+	struct clk *clk;
+	u32 rate;
+	struct list_head link;
+	struct list_head sort_link;
+};
+
+int __init of_clk_parse_init_rate(struct device_node *node, struct clk *clk)
+{
+	u32 rate;
+	struct clk_init_info *cinfo;
+
+	if (of_property_read_u32(node, "default-rate", &rate))
+		return 0;
+
+	cinfo = kzalloc(sizeof(*cinfo), GFP_KERNEL);
+	if (!cinfo)
+		return -ENOMEM;
+
+	cinfo->node = node;
+	cinfo->clk = clk;
+	cinfo->rate = rate;
+	list_add(&cinfo->link, &clk_init_info_list);
+	INIT_LIST_HEAD(&cinfo->sort_link);
+
+	return 0;
+}
+
+int __init of_clk_set_init_rates(void)
+{
+	struct clk_init_info *cinfo, *tmp;
+	struct of_phandle_args clkspec;
+	int ret = 0;
+	struct list_head sorted_list;
+	struct clk *clk;
+
+	INIT_LIST_HEAD(&sorted_list);
+
+	list_for_each_entry(cinfo, &clk_init_info_list, link) {
+		/* Get missing clk pointers */
+		if (!cinfo->clk) {
+			clkspec.np = cinfo->node;
+			cinfo->clk = of_clk_get_from_provider(&clkspec);
+		}
+
+		/* Check if we are the parent of any of the sorted clocks */
+		list_for_each_entry(tmp, &sorted_list, sort_link) {
+			clk = tmp->clk;
+			while (clk && clk != cinfo->clk)
+				clk = clk->parent;
+
+			if (clk == cinfo->clk) {
+				/* Add us before this node in the list */
+				list_add_tail(&cinfo->sort_link,
+					      &tmp->sort_link);
+				break;
+			}
+		}
+
+		if (list_empty(&cinfo->sort_link))
+			list_add_tail(&cinfo->sort_link, &sorted_list);
+	}
+
+	/* Process sorted list and set clk rates */
+	list_for_each_entry_safe(cinfo, tmp, &sorted_list, sort_link) {
+		int r = clk_set_rate(cinfo->clk, cinfo->rate);
+		if (r) {
+			pr_err("%s: clk_set_rate for %s failed: %d\n", __func__,
+			       cinfo->node->name, ret);
+			ret = r;
+		}
+
+		/* Clean up the static list */
+		list_del(&cinfo->link);
+		kfree(cinfo);
+	}
+
+	return ret;
+}
+
 /**
  * of_clk_init() - Scan and init clock providers from the DT
  * @matches: array of compatible values and init functions for providers.
@@ -2544,6 +2627,9 @@ void __init of_clk_init(const struct of_device_id *matches)
 	for_each_matching_node_and_match(np, matches, &match) {
 		of_clk_init_cb_t clk_init_cb = match->data;
 		clk_init_cb(np);
+		of_clk_parse_init_rate(np, NULL);
 	}
+
+	of_clk_set_init_rates();
 }
 #endif
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 939533d..1bbd194 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -506,6 +506,8 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
 int of_clk_get_parent_count(struct device_node *np);
 const char *of_clk_get_parent_name(struct device_node *np, int index);
+int of_clk_parse_init_rate(struct device_node *node, struct clk *clk);
+int of_clk_set_init_rates(void);
 
 void of_clk_init(const struct of_device_id *matches);
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 1/4] clk: ti: mux: add support for default-parenting
From: Tero Kristo @ 2014-02-13  9:00 UTC (permalink / raw)
  To: linux-omap, mturquette; +Cc: linux-arm-kernel, devicetree
In-Reply-To: <1392282048-6284-1-git-send-email-t-kristo@ti.com>

ti,mux-clock now supports ti,default-parent property, which can be used
to configure the default parent of the clock during boot. This property
can be added to board specific files, or under the clock data itself.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 Documentation/devicetree/bindings/clock/ti/mux.txt |    7 ++++++
 drivers/clk/ti/mux.c                               |   24 ++++++++++++++++++--
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/ti/mux.txt b/Documentation/devicetree/bindings/clock/ti/mux.txt
index 2d0d170..4e291eb 100644
--- a/Documentation/devicetree/bindings/clock/ti/mux.txt
+++ b/Documentation/devicetree/bindings/clock/ti/mux.txt
@@ -48,6 +48,8 @@ Optional properties:
   zero
 - ti,set-rate-parent : clk_set_rate is propagated to parent clock,
   not supported by the composite-mux-clock subtype
+- ti,default-parent : configures mux parent during boot to be the provided
+  phandle clock
 
 Examples:
 
@@ -65,6 +67,7 @@ abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck@4a306108 {
 	clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
 	ti,bit-shift = <24>;
 	reg = <0x0108>;
+	ti,default-parent = <&sys_32k_ck>;
 };
 
 mcbsp5_mux_fck: mcbsp5_mux_fck {
@@ -74,3 +77,7 @@ mcbsp5_mux_fck: mcbsp5_mux_fck {
 	ti,bit-shift = <4>;
 	reg = <0x02d8>;
 };
+
+&mcbsp5_mux_fck {
+	ti,default-parent = <&mcbsp_clks>;
+};
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index 0197a47..557a7ce 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -108,7 +108,8 @@ static struct clk *_register_mux(struct device *dev, const char *name,
 				 const char **parent_names, u8 num_parents,
 				 unsigned long flags, void __iomem *reg,
 				 u8 shift, u32 mask, u8 clk_mux_flags,
-				 u32 *table, spinlock_t *lock)
+				 u32 *table, int default_parent,
+				 spinlock_t *lock)
 {
 	struct clk_mux *mux;
 	struct clk *clk;
@@ -136,6 +137,9 @@ static struct clk *_register_mux(struct device *dev, const char *name,
 	mux->table = table;
 	mux->hw.init = &init;
 
+	if (default_parent >= 0)
+		ti_clk_mux_set_parent(&mux->hw, default_parent);
+
 	clk = clk_register(dev, &mux->hw);
 
 	if (IS_ERR(clk))
@@ -161,6 +165,8 @@ static void of_mux_clk_setup(struct device_node *node)
 	u32 mask = 0;
 	u32 shift = 0;
 	u32 flags = 0;
+	struct device_node *default_parent;
+	int default_parent_idx = -1;
 
 	num_parents = of_clk_get_parent_count(node);
 	if (num_parents < 2) {
@@ -174,6 +180,19 @@ static void of_mux_clk_setup(struct device_node *node)
 	for (i = 0; i < num_parents; i++)
 		parent_names[i] = of_clk_get_parent_name(node, i);
 
+	default_parent = of_parse_phandle(node, "ti,default-parent", 0);
+
+	if (default_parent) {
+		for (i = 0; i < num_parents; i++) {
+			struct device_node *tmp;
+			tmp = of_parse_phandle(node, "clocks", i);
+			if (tmp == default_parent) {
+				default_parent_idx = i;
+				break;
+			}
+		}
+	}
+
 	reg = ti_clk_get_reg_addr(node, 0);
 
 	if (!reg)
@@ -195,7 +214,8 @@ static void of_mux_clk_setup(struct device_node *node)
 	mask = (1 << fls(mask)) - 1;
 
 	clk = _register_mux(NULL, node->name, parent_names, num_parents, flags,
-			    reg, shift, mask, clk_mux_flags, NULL, NULL);
+			    reg, shift, mask, clk_mux_flags, NULL,
+			    default_parent_idx, NULL);
 
 	if (!IS_ERR(clk))
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 0/4] clk: dt: add support for default rate/parent
From: Tero Kristo @ 2014-02-13  9:00 UTC (permalink / raw)
  To: linux-omap, mturquette; +Cc: linux-arm-kernel, devicetree

Hi,

This set is a mix-match of new DT properties for generic and TI specific
clock drivers. Basically provided for commenting purposes. The patches
provide a way to configure clock parents / rates during boot through DT.

"default-rate" : sets rate of a clock during boot, supported for any DT
		 clock type (through generic clock driver)
"ti,default-parent" : selects a default parent for a multiplexer clock,
		      only supported for TI specific mux clock for now,
		      as generic mux clock does not support DT clocks

Patch #4 provided as a reference how to move the default rates / parents
from kernel code to DT.

Default-rate logic in patch #2 looks somewhat complicated, as the clocks
need to be sorted based on their parents to avoid cases where a child clock
would set its rate first, just to be overridden by its parent changing
rate later and resulting in incorrect rate for the child clock.

If the default-rate generic property is not going to fly, it can be moved
to TI only drivers also.

-Tero


^ permalink raw reply

* Re: [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Jingoo Han @ 2014-02-13  8:57 UTC (permalink / raw)
  To: 'Tanmay Inamdar'
  Cc: 'Liviu Dudau', 'Arnd Bergmann', devicetree,
	'linaro-kernel', 'linux-pci',
	'Will Deacon', 'LKML', 'Catalin Marinas',
	'Bjorn Helgaas', 'LAKML', 'Jingoo Han'
In-Reply-To: <CACoXjc=epN8=tFQKw6kZ27hTA=a+c56q1pikX_SSMKK1rsScCw@mail.gmail.com>



> -----Original Message-----
> From: Tanmay Inamdar [mailto:tinamdar@apm.com]
> Sent: Thursday, February 13, 2014 5:37 PM
> To: Jingoo Han
> Cc: Liviu Dudau; Arnd Bergmann; devicetree@vger.kernel.org; linaro-kernel; linux-pci; Will Deacon;
> LKML; Catalin Marinas; Bjorn Helgaas; LAKML
> Subject: Re: [PATCH] pci: Add support for creating a generic host_bridge from device tree
> 
> On Thu, Feb 13, 2014 at 12:10 AM, Jingoo Han <jg1.han@samsung.com> wrote:
> > On Thursday, February 06, 2014 7:18 PM, Liviu Dudau wrote:
> >> On Wed, Feb 05, 2014 at 10:26:27PM +0000, Tanmay Inamdar wrote:
> >> > Hello Liviu,
> >> >
> >> > I did not get the first email of this particular patch on any of
> >> > subscribed mailing lists (don't know why), hence replying here.
> >>
> >> Strange, it shows in the MARC and GMANE archive for linux-pci, probably
> >> a hickup on your receiving side?
> >>
> >> >
> >> > +struct pci_host_bridge *
> >> > +pci_host_bridge_of_init(struct device *parent, int busno, struct pci_ops *ops,
> >> > + void *host_data, struct list_head *resources)
> >> > +{
> >> > + struct pci_bus *root_bus;
> >> > + struct pci_host_bridge *bridge;
> >> > +
> >> > + /* first parse the host bridge bus ranges */
> >> > + if (pci_host_bridge_of_get_ranges(parent->of_node, resources))
> >> > + return NULL;
> >> > +
> >> > + /* then create the root bus */
> >> > + root_bus = pci_create_root_bus(parent, busno, ops, host_data, resources);
> >> > + if (!root_bus)
> >> > + return NULL;
> >> > +
> >> > + bridge = to_pci_host_bridge(root_bus->bridge);
> >> > +
> >> > + return bridge;
> >> > +}
> >> >
> >> > You are keeping the domain_nr inside pci_host_bridge structure. In
> >> > above API, domain_nr is required in 'pci_find_bus' function called
> >> > from 'pci_create_root_bus'. Since the bridge is allocated after
> >> > creating root bus, 'pci_find_bus' always gets domain_nr as 0. This
> >> > will cause problem for scanning multiple domains.
> >>
> >> Good catch. I was switching between creating a pci_controller in arch/arm64 and
> >> adding the needed bits in pci_host_bridge. After internal review I've decided to
> >> add the domain_nr to pci_host_bridge, but forgot to update the code everywhere.
> >
> > Hi Liviu Dudau,
> >
> > One more thing,
> > I am reviewing and compiling your patch.
> > Would you consider adding 'struct pci_sys_data' and 'struct hw_pci'?
> >
> > Currently, 4 PCIe Host drivers (pci-mvebu.c, pci-tegra.c,
> > pci-rcar-gen2.c, pcie-designware.c) are using 'struct pci_sys_data'
> > and 'struct hw_pci' in their drivers. Without this, it makes build
> > errors.
> >
> > In arm32, 'struct pci_sys_data' and 'struct hw_pci' is defined
> > in "arch/arm/include/asm/mach/pci.h".
> >
> > Tanmay Inamdar,
> > Your 'APM X-Gene PCIe' patch also needs 'struct pci_sys_data' and
> > 'struct hw_pci'. With Liviu Dudau's patch, it will make build
> > errors. Would you check this?
> 
> X-Gene PCIe host driver is dependent on arm64 PCI patch. My previous
> approach was based on 32bit arm PCI support. With Liviu's approach, I
> will have to make changes in host driver to get rid of hw_pci and
> pci_sys_data which are no longer required.

I want to use 'drivers/pci/host/pcie-designware.c' for both arm32
and arm64, without any code changes. However, it looks impossible.

I made 'drivers/pci/host/pcie-designware.c' based on 32bit arm PCI
support. Then, with Liviu's patch, do I have to make new code for arm64,
even though the same HW PCIe IP is used?

- For arm32
  drivers/pci/host/pcie-designware.c

- For arm64
  drivers/pci/host/pcie-designware-arm64.c


> 
> IMO it should not cause build errors for PCI host drivers dependent on
> architectures other than arm64. Can you post the error?
> 

I post the build errors.

  CC      drivers/pci/host/pcie-designware.o
  CHK     kernel/config_data.h
drivers/pci/host/pcie-designware.c:72:52: warning: 'struct pci_sys_data' declared inside parameter list [enabled by default]
 static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
                                                    ^
drivers/pci/host/pcie-designware.c:72:52: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
drivers/pci/host/pcie-designware.c: In function 'sys_to_pcie'
drivers/pci/host/pcie-designware.c:74:12: error: dereferencing pointer to incomplete type
  return sys->private_data;
            ^
drivers/pci/host/pcie-designware.c: In function 'dw_pcie_msi_map'
drivers/pci/host/pcie-designware.c:384:2: error: implicit declaration of function 'set_irq_flags' [-Werror=implicit-function-declaration]
  set_irq_flags(irq, IRQF_VALID);
  ^
drivers/pci/host/pcie-designware.c:384:21: error: 'IRQF_VALID??undeclared (first use in this function)
  set_irq_flags(irq, IRQF_VALID);
                     ^
drivers/pci/host/pcie-designware.c:384:21: note: each undeclared identifier is reported only once for each function it appears in
drivers/pci/host/pcie-designware.c: In function 'dw_pcie_host_init'
drivers/pci/host/pcie-designware.c:492:2: error: invalid use of undefined type 'struct hw_pci'
  dw_pci.nr_controllers = 1;
  ^
drivers/pci/host/pcie-designware.c:493:2: error: invalid use of undefined type 'struct hw_pci'
  dw_pci.private_data = (void **)&pp;
  ^
drivers/pci/host/pcie-designware.c:495:2: error: implicit declaration of function 'pci_common_init' [-Werror=implicit-function-declaration]
  pci_common_init(&dw_pci);
  ^
drivers/pci/host/pcie-designware.c:498:2: error: invalid use of undefined type 'struct hw_pci'
  dw_pci.domain++;
  ^
drivers/pci/host/pcie-designware.c: At top level:
drivers/pci/host/pcie-designware.c:698:41: warning: 'struct pci_sys_data??declared inside parameter list [enabled by default]
 static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
                                         ^
drivers/pci/host/pcie-designware.c: In function 'dw_pcie_setup'
drivers/pci/host/pcie-designware.c:702:2: warning: passing argument 1 of 'sys_to_pcie' from incompatible pointer type [enabled by default]
  pp = sys_to_pcie(sys);
  ^
drivers/pci/host/pcie-designware.c:72:33: note: expected 'struct pci_sys_data *' but argument is of type 'struct pci_sys_data *'
 static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
                                 ^
drivers/pci/host/pcie-designware.c:708:6: error: dereferencing pointer to incomplete type
   sys->io_offset = global_io_offset - pp->config.io_bus_addr;
      ^
drivers/pci/host/pcie-designware.c:711:31: error: dereferencing pointer to incomplete type
   pci_add_resource_offset(&sys->resources, &pp->io,
                               ^
drivers/pci/host/pcie-designware.c:712:9: error: dereferencing pointer to incomplete type
      sys->io_offset);
         ^
drivers/pci/host/pcie-designware.c:715:5: error: dereferencing pointer to incomplete type
  sys->mem_offset = pp->mem.start - pp->config.mem_bus_addr;
     ^
drivers/pci/host/pcie-designware.c:716:30: error: dereferencing pointer to incomplete type
  pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
                              ^
drivers/pci/host/pcie-designware.c:716:56: error: dereferencing pointer to incomplete type
  pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
                                                        ^
drivers/pci/host/pcie-designware.c: At top level:
drivers/pci/host/pcie-designware.c:721:56: warning: 'struct pci_sys_data' declared inside parameter list [enabled by default]
 static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
                                                        ^
drivers/pci/host/pcie-designware.c: In function 'dw_pcie_scan_bus'
drivers/pci/host/pcie-designware.c:724:9: warning: passing argument 1 of 'sys_to_pcie' from incompatible pointer type [enabled by default]
  struct pcie_port *pp = sys_to_pcie(sys);
         ^
drivers/pci/host/pcie-designware.c:72:33: note: expected 'struct pci_sys_data *' but argument is of type 'sruct pci_sys_data *'
 static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
                                 ^
drivers/pci/host/pcie-designware.c:727:24: error: dereferencing pointer to incomplete type
   pp->root_bus_nr = sys->busnr;
                        ^
drivers/pci/host/pcie-designware.c:728:36: error: dereferencing pointer to incomplete type
   bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops,
                                    ^
drivers/pci/host/pcie-designware.c:729:15: error: dereferencing pointer to incomplete type
      sys, &sys->resources);
               ^
drivers/pci/host/pcie-designware.c: At top level:
drivers/pci/host/pcie-designware.c:755:15: error: variable 'dw_pci' has initializer but incomplete type
 static struct hw_pci dw_pci = {
               ^
drivers/pci/host/pcie-designware.c:756:2: error: unknown field 'setup' specified in initializer
  .setup  = dw_pcie_setup,
  ^
drivers/pci/host/pcie-designware.c:756:2: warning: excess elements in struct initializer [enabled by default]
drivers/pci/host/pcie-designware.c:756:2: warning: (near initialization for 'dw_pci' [enabled by default]
drivers/pci/host/pcie-designware.c:757:2: error: unknown field 'scan' specified in initializer
  .scan  = dw_pcie_scan_bus,
  ^
drivers/pci/host/pcie-designware.c:757:2: warning: excess elements in struct initializer [enabled by default]
drivers/pci/host/pcie-designware.c:757:2: warning: (near initialization for 'dw_pci' [enabled by default]
drivers/pci/host/pcie-designware.c:758:2: error: unknown field 'map_irq' specified in initializer
  .map_irq = dw_pcie_map_irq,
  ^
drivers/pci/host/pcie-designware.c:758:2: warning: excess elements in struct initializer [enabled by default]
drivers/pci/host/pcie-designware.c:758:2: warning: (near initialization for 'dw_pci' [enabled by default]
drivers/pci/host/pcie-designware.c:759:2: error: unknown field 'add_bus' specified in initializer
  .add_bus = dw_pcie_add_bus,
  ^
drivers/pci/host/pcie-designware.c:759:2: warning: excess elements in struct initializer [enabled by default]
drivers/pci/host/pcie-designware.c:759:2: warning: (near initialization for 'dw_pci' [enabled by default]
cc1: some warnings being treated as errors
make[3]: *** [drivers/pci/host/pcie-designware.o] Error 1


> >
> >>
> >> Thanks for reviewing this, will fix in v2.
> >>
> >> Do you find porting to the new API straight forward?
> >>
> >

^ permalink raw reply

* Re: [PATCH 1/3] mmc: add support for power-on sequencing through DT
From: Ulf Hansson @ 2014-02-13  8:56 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Tomasz Figa, Tomasz Figa, Olof Johansson, linux-mmc, devicetree,
	Russell King - ARM Linux, linux-arm-kernel@lists.infradead.org,
	robh+dt, mark.rutland, Pawel Moll, Ian Campbell, Kumar Gala,
	Chris Ball, Sascha Hauer, Fabio Estevam
In-Reply-To: <201401281148.10670.arnd@arndb.de>

On 28 January 2014 11:48, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 28 January 2014, Ulf Hansson wrote:
>> On 28 January 2014 01:59, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>> > On 27.01.2014 11:19, Ulf Hansson wrote:
>> >> There is already a host capability that I think we could use to handle
>> >> this. MMC_CAP_NONREMOVABLE, the corresponding DT binding string is
>> >> "non-removable", and it may be set per host device.
>> >>
>> >> Using this cap means the mmc_rescan process that runs to detect new
>> >> cards, will only be executed once and during boot. So, we need to make
>> >> sure all resources and powers are provided to the card at this point.
>> >> Otherwise the card will not be detected.
>> >
>> > I don't quite like this requirement, especially if you consider
>> > multi-platform kernels where a lot of drivers is going to be provided as
>> > modules. WLAN drivers are especially good candidates. This means that even
>> > if the card is powered off at boot-up, if user (or init system) loads
>> > appropriate module, which powers the chip on, MMC core must be able to
>> > notice this.
>>
>> To be able to detect the card, the WLAN driver doesn't have to be
>> probed, only the "power controller" driver. I suppose this is were it
>> becomes a bit tricky.
>>
>> Somehow the mmc core needs to be involved in the probe process of the
>> power controller driver. Could perhaps the power controller bus be
>> located in the mmc core and thus the power controller driver needs to
>> register itself by using a new API from the mmc core? Similar how SDIO
>> func driver's register themselves.
>
> I think there is another option, which does have its own pros and cons:
> We could move all the power handling back into the sdio function driver
> if we allow a secondary detection path using DT rather than the probing
> of the SDIO bus. Essentially you'd have to list the class/vendor/device
> ID for each function that cannot be autodetected in DT, and have the
> SDIO core pretend that it found the device just by looking at the
> device nodes, and register the struct sdio_func so it can be bound to
> the driver. The driver then does all the power handling in a device
> specific way. At some point the hardware gets registered at the
> mmc host, and the sdio core connects the bus state to the already present
> sdio_func, possibly notifying the function driver that it has become
> usable.

It seems like an option we could try.

There are some tricky parts that needs to be taken care of by the
mmc/sdio core, regarding the probe/removal and the suspend/resume
sequence, but I suppose it should be possible.

A minor concern is how do we handle devices that are fully powered at
boot? Unless the sdio func driver will be loaded we can't power off
them, right? Do we need to cover this case, do you think?

>
> Obviously, this can only work for CAP_NONREMOVABLE devices, but those
> are exactly the ones we are worried about here. The advantage is that
> the power sequencing for a particular device can then be in device
> specific code and can have an arbitrarily complex in the driver without
> needing the mmc code to handle all possible corner cases.

Agree!

I think a removable SDIO card won't l need this additional power
controller mechanism.

Kind regards
Uffe

>
>         Arnd
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Tanmay Inamdar @ 2014-02-13  8:36 UTC (permalink / raw)
  To: Jingoo Han
  Cc: Liviu Dudau, Arnd Bergmann,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linaro-kernel,
	linux-pci, Will Deacon, LKML, Catalin Marinas, Bjorn Helgaas,
	LAKML
In-Reply-To: <000201cf2893$0f5e3710$2e1aa530$%han-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

On Thu, Feb 13, 2014 at 12:10 AM, Jingoo Han <jg1.han-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> wrote:
> On Thursday, February 06, 2014 7:18 PM, Liviu Dudau wrote:
>> On Wed, Feb 05, 2014 at 10:26:27PM +0000, Tanmay Inamdar wrote:
>> > Hello Liviu,
>> >
>> > I did not get the first email of this particular patch on any of
>> > subscribed mailing lists (don't know why), hence replying here.
>>
>> Strange, it shows in the MARC and GMANE archive for linux-pci, probably
>> a hickup on your receiving side?
>>
>> >
>> > +struct pci_host_bridge *
>> > +pci_host_bridge_of_init(struct device *parent, int busno, struct pci_ops *ops,
>> > + void *host_data, struct list_head *resources)
>> > +{
>> > + struct pci_bus *root_bus;
>> > + struct pci_host_bridge *bridge;
>> > +
>> > + /* first parse the host bridge bus ranges */
>> > + if (pci_host_bridge_of_get_ranges(parent->of_node, resources))
>> > + return NULL;
>> > +
>> > + /* then create the root bus */
>> > + root_bus = pci_create_root_bus(parent, busno, ops, host_data, resources);
>> > + if (!root_bus)
>> > + return NULL;
>> > +
>> > + bridge = to_pci_host_bridge(root_bus->bridge);
>> > +
>> > + return bridge;
>> > +}
>> >
>> > You are keeping the domain_nr inside pci_host_bridge structure. In
>> > above API, domain_nr is required in 'pci_find_bus' function called
>> > from 'pci_create_root_bus'. Since the bridge is allocated after
>> > creating root bus, 'pci_find_bus' always gets domain_nr as 0. This
>> > will cause problem for scanning multiple domains.
>>
>> Good catch. I was switching between creating a pci_controller in arch/arm64 and
>> adding the needed bits in pci_host_bridge. After internal review I've decided to
>> add the domain_nr to pci_host_bridge, but forgot to update the code everywhere.
>
> Hi Liviu Dudau,
>
> One more thing,
> I am reviewing and compiling your patch.
> Would you consider adding 'struct pci_sys_data' and 'struct hw_pci'?
>
> Currently, 4 PCIe Host drivers (pci-mvebu.c, pci-tegra.c,
> pci-rcar-gen2.c, pcie-designware.c) are using 'struct pci_sys_data'
> and 'struct hw_pci' in their drivers. Without this, it makes build
> errors.
>
> In arm32, 'struct pci_sys_data' and 'struct hw_pci' is defined
> in "arch/arm/include/asm/mach/pci.h".
>
> Tanmay Inamdar,
> Your 'APM X-Gene PCIe' patch also needs 'struct pci_sys_data' and
> 'struct hw_pci'. With Liviu Dudau's patch, it will make build
> errors. Would you check this?

X-Gene PCIe host driver is dependent on arm64 PCI patch. My previous
approach was based on 32bit arm PCI support. With Liviu's approach, I
will have to make changes in host driver to get rid of hw_pci and
pci_sys_data which are no longer required.

IMO it should not cause build errors for PCI host drivers dependent on
architectures other than arm64. Can you post the error?

>
> Thank you.
>
> Best regards,
> Jingoo Han
>
>>
>> Thanks for reviewing this, will fix in v2.
>>
>> Do you find porting to the new API straight forward?
>>
>
--
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 1/2] ARM: shmobile: r8a7778/r8a7779 dtsi: Improve and correct HSPI bindings
From: Geert Uytterhoeven @ 2014-02-13  8:31 UTC (permalink / raw)
  To: Kuninori Morimoto
  Cc: Simon Horman, Kuninori Morimoto,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-spi,
	Linux-sh list, Geert Uytterhoeven, Mark Brown
In-Reply-To: <87zjlvbi7l.wl%kuninori.morimoto.gx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Hi Morimoto-san,

On Thu, Feb 13, 2014 at 8:11 AM, Kuninori Morimoto
<kuninori.morimoto.gx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> could you test this series as Geert does not have access to a bockw board?
>>
>> On Tue, Feb 11, 2014 at 09:56:47AM +0100, Geert Uytterhoeven wrote:
>> > From: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
>> >
>> > Binding documentation:
>> >   - Add future-proof "renesas,hspi-<soctype>" compatible values,
>> >   - Add "interrupt-parent", "#address-cells" and "#size-cells" properties,
>> >   - Add reference to pinctrl documentation,
>> >   - Add example bindings.
>> >
>> > r8a7778 and r8a7779 dtsi:
>> >   - Add "renesas,hspi-r8a7778" resp. "renesas,hspi-r8a7779" compatible
>> >     values,
>> >   - Correct reference to parent interrupt controller
>> >     (use "interrupt-parent" instead of "interrupt-controller"),
>> >   - Add missing "#address-cells" and "#size-cells" properties, which are
>> >     needed when populating the SPI buses.
>> >
>> > Signed-off-by: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
>> > Cc: Mark Brown <broonie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> > ---
>
> I tested this patch, and it works well.
> But there are some notes
>
> 1) m25p80 driver DT support seems strange ??
>
>    ${LINUX}/Documentation/devicetree/bindings/mtd/m25p80.txt
>    has explain about DT of m25p80 driver, but,
>    ${LINUX}/drivers/mtd/devices/m25p80.c
>    doesn't have driver :: of_match_table.
>    but, it is using of_property_read_bool() on probe.
>    Is it out-of-tree support ?? I'm not sure,
>    anyway, m25p80 driver didn't probe.

It probes based on the values in m25p_ids[].

See drivers/of/base.c:of_modalias_node():

 * Based on the value of the compatible property, this routine will attempt
 * to choose an appropriate modalias value for a particular device tree node.
 * It does this by stripping the manufacturer prefix (as delimited by a ',')
 * from the first entry in the compatible list property.

Which is used by drivers/spi/spi.c:of_register_spi_devices().

>    So, I quick-hacked this issue in my local environment.

Was there anything else you needed to do, besides adding support for
s25fl008k to m25p80.c?

> 2) it needs Geert's this patch
>
>    Subject: [PATCH] mtd: m25p80: add support for the Spansion s25fl008k chip
>    Date:        Tue, 11 Feb 2014 09:51:18 +0100
>
>    Kernel will hung-up without this patch

Hang up? Not just ignoring the device?

> For HSPI / BockW point of view
>
> Tested-by: Kuninori Morimoto <kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>

Thanks!

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 linux-spi" 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: sunxi: dt: Convert to the new i2c compatibles
From: Wolfram Sang @ 2014-02-13  8:26 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1391680285-16668-3-git-send-email-maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1814 bytes --]


Why is the devicetree list not on CC? (Added now)

On Thu, Feb 06, 2014 at 10:51:25AM +0100, Maxime Ripard wrote:
> Switch the device tree to the new compatibles introduced in the i2c drivers
> to have a common pattern accross all Allwinner SoCs.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  arch/arm/boot/dts/sun4i-a10.dtsi  |  6 +++---
>  arch/arm/boot/dts/sun5i-a10s.dtsi |  6 +++---
>  arch/arm/boot/dts/sun5i-a13.dtsi  |  6 +++---
>  arch/arm/boot/dts/sun7i-a20.dtsi  | 10 +++++-----
>  4 files changed, 14 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
> index 28273f9..ac65c8a 100644
> --- a/arch/arm/boot/dts/sun4i-a10.dtsi
> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
> @@ -518,7 +518,7 @@
>  		};
>  
>  		i2c0: i2c@01c2ac00 {
> -			compatible = "allwinner,sun4i-i2c";
> +			compatible = "allwinner,sun4i-a10-i2c";

Can't we have:

	compatible = "allwinner,sun4i-a10-i2c", "allwinner,sun4i-i2c";

? And keep the old "allwinner,sun4i-i2c" and extend it with a SoC
specific a10 compatible entry when a distinction is needed?

> diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
> index 6de40b6..537072c 100644
> --- a/arch/arm/boot/dts/sun5i-a13.dtsi
> +++ b/arch/arm/boot/dts/sun5i-a13.dtsi
> @@ -377,7 +377,7 @@
>  		};
>  
>  		i2c0: i2c@01c2ac00 {
> -			compatible = "allwinner,sun4i-i2c";
> +			compatible = "allwinner,sun4i-a10-i2c";

For non-a10, That should be at least

	compatible = "allwinner,sun4i-a13-i2c", "allwinner,sun4i-a10-i2c";

or

	compatible = "allwinner,sun4i-a13-i2c", "allwinner,sun4i-i2c";

depending on the outcome above.

Or is my knowledge outdated already?


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Jingoo Han @ 2014-02-13  8:18 UTC (permalink / raw)
  To: 'Liviu Dudau', 'Tanmay Inamdar'
  Cc: 'Arnd Bergmann', devicetree, 'linaro-kernel',
	'linux-pci', 'Will Deacon', 'LKML',
	'Catalin Marinas', 'Bjorn Helgaas',
	'LAKML', 'Jingoo Han'
In-Reply-To: <000201cf2893$0f5e3710$2e1aa530$%han@samsung.com>

On 

> -----Original Message-----
> From: Jingoo Han [mailto:jg1.han@samsung.com]
> Sent: Thursday, February 13, 2014 5:10 PM
> To: 'Liviu Dudau'; 'Tanmay Inamdar'
> Cc: 'Arnd Bergmann'; devicetree@vger.kernel.org; 'linaro-kernel'; 'linux-pci'; 'Will Deacon'; 'LKML';
> 'Catalin Marinas'; 'Bjorn Helgaas'; 'LAKML'; 'Jingoo Han'
> Subject: Re: [PATCH] pci: Add support for creating a generic host_bridge from device tree
> 
> On Thursday, February 06, 2014 7:18 PM, Liviu Dudau wrote:
> > On Wed, Feb 05, 2014 at 10:26:27PM +0000, Tanmay Inamdar wrote:
> > > Hello Liviu,
> > >
> > > I did not get the first email of this particular patch on any of
> > > subscribed mailing lists (don't know why), hence replying here.
> >
> > Strange, it shows in the MARC and GMANE archive for linux-pci, probably
> > a hickup on your receiving side?
> >
> > >
> > > +struct pci_host_bridge *
> > > +pci_host_bridge_of_init(struct device *parent, int busno, struct pci_ops *ops,
> > > + void *host_data, struct list_head *resources)
> > > +{
> > > + struct pci_bus *root_bus;
> > > + struct pci_host_bridge *bridge;
> > > +
> > > + /* first parse the host bridge bus ranges */
> > > + if (pci_host_bridge_of_get_ranges(parent->of_node, resources))
> > > + return NULL;
> > > +
> > > + /* then create the root bus */
> > > + root_bus = pci_create_root_bus(parent, busno, ops, host_data, resources);
> > > + if (!root_bus)
> > > + return NULL;
> > > +
> > > + bridge = to_pci_host_bridge(root_bus->bridge);
> > > +
> > > + return bridge;
> > > +}
> > >
> > > You are keeping the domain_nr inside pci_host_bridge structure. In
> > > above API, domain_nr is required in 'pci_find_bus' function called
> > > from 'pci_create_root_bus'. Since the bridge is allocated after
> > > creating root bus, 'pci_find_bus' always gets domain_nr as 0. This
> > > will cause problem for scanning multiple domains.
> >
> > Good catch. I was switching between creating a pci_controller in arch/arm64 and
> > adding the needed bits in pci_host_bridge. After internal review I've decided to
> > add the domain_nr to pci_host_bridge, but forgot to update the code everywhere.
> 
> Hi Liviu Dudau,
> 
> One more thing,
> I am reviewing and compiling your patch.
> Would you consider adding 'struct pci_sys_data' and 'struct hw_pci'?
> 
> Currently, 4 PCIe Host drivers (pci-mvebu.c, pci-tegra.c,
> pci-rcar-gen2.c, pcie-designware.c) are using 'struct pci_sys_data'
> and 'struct hw_pci' in their drivers. Without this, it makes build
> errors.
> 
> In arm32, 'struct pci_sys_data' and 'struct hw_pci' is defined
> in "arch/arm/include/asm/mach/pci.h".
> 
> Tanmay Inamdar,
> Your 'APM X-Gene PCIe' patch also needs 'struct pci_sys_data' and
> 'struct hw_pci'. With Liviu Dudau's patch, it will make build
> errors. Would you check this?

I mean the patch '[PATCH] arm64: Add architecture support for PCI'.
With this patch, it makes build errors in PCIe Host drivers such as
pcie-designware.c.

Best regards,
Jingoo Han

^ permalink raw reply

* Re: [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Jingoo Han @ 2014-02-13  8:10 UTC (permalink / raw)
  To: 'Liviu Dudau', 'Tanmay Inamdar'
  Cc: 'Arnd Bergmann', devicetree, 'linaro-kernel',
	'linux-pci', 'Will Deacon', 'LKML',
	'Catalin Marinas', 'Bjorn Helgaas',
	'LAKML', 'Jingoo Han'
In-Reply-To: <20140206101814.GA4993@e106497-lin.cambridge.arm.com>

On Thursday, February 06, 2014 7:18 PM, Liviu Dudau wrote:
> On Wed, Feb 05, 2014 at 10:26:27PM +0000, Tanmay Inamdar wrote:
> > Hello Liviu,
> >
> > I did not get the first email of this particular patch on any of
> > subscribed mailing lists (don't know why), hence replying here.
> 
> Strange, it shows in the MARC and GMANE archive for linux-pci, probably
> a hickup on your receiving side?
> 
> >
> > +struct pci_host_bridge *
> > +pci_host_bridge_of_init(struct device *parent, int busno, struct pci_ops *ops,
> > + void *host_data, struct list_head *resources)
> > +{
> > + struct pci_bus *root_bus;
> > + struct pci_host_bridge *bridge;
> > +
> > + /* first parse the host bridge bus ranges */
> > + if (pci_host_bridge_of_get_ranges(parent->of_node, resources))
> > + return NULL;
> > +
> > + /* then create the root bus */
> > + root_bus = pci_create_root_bus(parent, busno, ops, host_data, resources);
> > + if (!root_bus)
> > + return NULL;
> > +
> > + bridge = to_pci_host_bridge(root_bus->bridge);
> > +
> > + return bridge;
> > +}
> >
> > You are keeping the domain_nr inside pci_host_bridge structure. In
> > above API, domain_nr is required in 'pci_find_bus' function called
> > from 'pci_create_root_bus'. Since the bridge is allocated after
> > creating root bus, 'pci_find_bus' always gets domain_nr as 0. This
> > will cause problem for scanning multiple domains.
> 
> Good catch. I was switching between creating a pci_controller in arch/arm64 and
> adding the needed bits in pci_host_bridge. After internal review I've decided to
> add the domain_nr to pci_host_bridge, but forgot to update the code everywhere.

Hi Liviu Dudau,

One more thing,
I am reviewing and compiling your patch.
Would you consider adding 'struct pci_sys_data' and 'struct hw_pci'?

Currently, 4 PCIe Host drivers (pci-mvebu.c, pci-tegra.c,
pci-rcar-gen2.c, pcie-designware.c) are using 'struct pci_sys_data'
and 'struct hw_pci' in their drivers. Without this, it makes build
errors.

In arm32, 'struct pci_sys_data' and 'struct hw_pci' is defined
in "arch/arm/include/asm/mach/pci.h".

Tanmay Inamdar,
Your 'APM X-Gene PCIe' patch also needs 'struct pci_sys_data' and
'struct hw_pci'. With Liviu Dudau's patch, it will make build
errors. Would you check this?

Thank you.

Best regards,
Jingoo Han

> 
> Thanks for reviewing this, will fix in v2.
> 
> Do you find porting to the new API straight forward?
> 

^ permalink raw reply

* Re: [RFC] dt: bindings: add bindings for Broadcom bcm43xx sdio devices
From: Chen-Yu Tsai @ 2014-02-13  7:41 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: Rob Herring, devicetree, linux-kernel, Tomasz Figa
In-Reply-To: <1392059868-8782-1-git-send-email-arend@broadcom.com>

On Tue, Feb 11, 2014 at 3:17 AM, Arend van Spriel <arend@broadcom.com> wrote:
> The Broadcom bcm43xx sdio devices are fullmac devices that may be
> integrated in ARM platforms. Currently, the brcmfmac driver for
> these devices support use of platform data. This patch specifies
> the bindings that allow this platform data to be expressed in the
> devicetree.
>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Cc: Tomasz Figa <tomasz.figa@gmail.com>
> Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
> Signed-off-by: Arend van Spriel <arend@broadcom.com>
> ---
> This devicetree binding proposal is intended for platforms with
> Broadcom wireless device in MMC sdio slot. These devices may
> have their own interrupt and power line. Also the SDIO drive
> strength is often hardware dependent and expressed in this
> binding.

Hi,

I believe the interrupts and drive-strength properties are Ok.
However, letting the platform driver power up the wifi chip does
not guarantee proper ordering, does it? I mean, what if the MMC
bus was probed before the (non-removable) chip was switched on?

Being able to tie that to the mmc controller would be better IMO.
I think this was discussed in Olof's "mmc: add support for
power-on sequencing through DT" thread.


Thanks!
ChenYu

>
> Not sure if this should go in staging or not. Feel free to
> comment on this proposal.
>
> Regards,
> Arend

^ permalink raw reply

* [PATCH][v2] powerpc/fsl: Add/update miscellaneous missing bindings
From: Harninder Rai @ 2014-02-13  7:29 UTC (permalink / raw)
  To: scottwood-KZfg59tc24xl57MIdRCFDg,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Harninder Rai

Missing bindings were found on running checkpatch.pl on bsc9132
device tree. This patch add/update the following

- Add bindings for L2 cache controller
- Add bindings for memory controller
- Update bindings for USB controller

Signed-off-by: Harninder Rai <harninder.rai-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
Changes since base version:
Incorporated Scott's comments
- Rename l2cc.txt to l2cache.txt
- Add information about ePAPR compliance
- Add missing "cache" in compatible
- Miscellaneous minors

 .../devicetree/bindings/powerpc/fsl/l2cache.txt    |   26 ++++++++++++++++++++
 .../devicetree/bindings/powerpc/fsl/mem-ctrlr.txt  |   16 ++++++++++++
 Documentation/devicetree/bindings/usb/fsl-usb.txt  |    2 +
 3 files changed, 44 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/powerpc/fsl/l2cache.txt
 create mode 100644 Documentation/devicetree/bindings/powerpc/fsl/mem-ctrlr.txt

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/l2cache.txt b/Documentation/devicetree/bindings/powerpc/fsl/l2cache.txt
new file mode 100644
index 0000000..79ef4a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/l2cache.txt
@@ -0,0 +1,26 @@
+Freescale L2 Cache Controller
+
+L2 cache is present in Freescale's QorIQ and QorIQ Qonverge platforms.
+The cache bindings explained below are ePAPR compliant
+
+Required Properties:
+
+- compatible	: Should include "fsl,chip-l2-cache-controller" and "cache"
+		  where chip is the processor (bsc9132, npc8572 etc.)
+- reg		: Address and size of L2 cache controller registers
+- cache-size	: Size of the entire L2 cache
+- interrupts	: Error interrupt of L2 controller
+
+Optional Properties:
+
+- cache-line-size : Size of L2 cache lines
+
+Example:
+
+	L2: l2-cache-controller@20000 {
+		compatible = "fsl,bsc9132-l2-cache-controller", "cache";
+		reg = <0x20000 0x1000>;
+		cache-line-size = <32>; // 32 bytes
+		cache-size = <0x40000>; // L2,256K
+		interrupts = <16 2 1 0>;
+	};
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mem-ctrlr.txt b/Documentation/devicetree/bindings/powerpc/fsl/mem-ctrlr.txt
new file mode 100644
index 0000000..70b42bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/mem-ctrlr.txt
@@ -0,0 +1,16 @@
+Freescale DDR memory controller
+
+Properties:
+
+- compatible	: Should include "fsl,chip-memory-controller" where
+		  chip is the processor (bsc9132, mpc8572 etc.)
+- reg		: Address and size of DDR controller registers
+- interrupts	: Error interrupt of DDR controller
+
+Example:
+
+	memory-controller@2000 {
+		compatible = "fsl,bsc9132-memory-controller";
+		reg = <0x2000 0x1000>;
+		interrupts = <16 2 1 8>;
+	};
diff --git a/Documentation/devicetree/bindings/usb/fsl-usb.txt b/Documentation/devicetree/bindings/usb/fsl-usb.txt
index bd5723f..afa5809 100644
--- a/Documentation/devicetree/bindings/usb/fsl-usb.txt
+++ b/Documentation/devicetree/bindings/usb/fsl-usb.txt
@@ -9,6 +9,8 @@ Required properties :
  - compatible : Should be "fsl-usb2-mph" for multi port host USB
    controllers, or "fsl-usb2-dr" for dual role USB controllers
    or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
+   Wherever applicable, the IP version of the USB controller should
+   also be mentioned (for eg. fsl-usb2-dr-v2.2 for bsc9132).
  - phy_type : For multi port host USB controllers, should be one of
    "ulpi", or "serial". For dual role USB controllers, should be
    one of "ulpi", "utmi", "utmi_wide", or "serial".
-- 
1.7.6.GIT


--
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

* Re: [PATCH v5 4/8] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs
From: Chen-Yu Tsai @ 2014-02-13  7:24 UTC (permalink / raw)
  To: linux-sunxi
  Cc: devicetree, Ulf Hansson, Laurent Pinchart, Mike Turquette,
	Simon Baatz, Hans de Goede, Emilio López,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Chris Ball,
	linux-kernel, H Hartley Sweeten, Tejun Heo, Maxime Ripard,
	Guennadi Liakhovetski, linux-arm-kernel
In-Reply-To: <20140211193358.4568.45603.stgit-GPtPHOohwllnsqa/0SyWJQ@public.gmane.org>

Hi,

On Wed, Feb 12, 2014 at 3:33 AM, David Lanzendörfer
<david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org> wrote:
> This is based on the driver Allwinner ships in their Android kernel sources.
>
> Initial porting to upstream kernels done by David Lanzendörfer, additional
> fixes and cleanups by Hans de Goede.
>
> It uses dma in bus-master mode using a built-in designware idmac controller,
> which is identical to the one found in the mmc-dw hosts.
> The rest of the host is not identical to mmc-dw.
>
> Signed-off-by: David Lanzendörfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org>
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  drivers/mmc/host/Kconfig     |    7
>  drivers/mmc/host/Makefile    |    2
>  drivers/mmc/host/sunxi-mmc.c |  872 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/mmc/host/sunxi-mmc.h |  239 ++++++++++++
>  4 files changed, 1120 insertions(+)
>  create mode 100644 drivers/mmc/host/sunxi-mmc.c
>  create mode 100644 drivers/mmc/host/sunxi-mmc.h
>
[..]
> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
> new file mode 100644
> index 0000000..5fc4634
> --- /dev/null
> +++ b/drivers/mmc/host/sunxi-mmc.c
> @@ -0,0 +1,872 @@
> +/*
> + * Driver for sunxi SD/MMC host controllers
> + * (C) Copyright 2014-2015 Reuuimlla Technology Co., Ltd.
> + * (C) Copyright 2014-2015 Aaron Maoye <leafy.myeh-jFKXxz0WcGyYHARAtoI1EgC/G2K4zDHf@public.gmane.org>
> + * (C) Copyright 2014-2015 O2S GmbH <www.o2s.ch>
> + * (C) Copyright 2014-2015 David Lanzendörfer <david.lanzendoerfer@o2s.ch>
> + * (C) Copyright 2014-2015 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +
> +#include <linux/clk.h>
> +#include <linux/clk-private.h>
> +#include <linux/clk/sunxi.h>
> +
> +#include <linux/gpio.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/scatterlist.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <linux/of_address.h>
> +#include <linux/of_gpio.h>
> +#include <linux/of_platform.h>
> +
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/sd.h>
> +#include <linux/mmc/sdio.h>
> +#include <linux/mmc/mmc.h>
> +#include <linux/mmc/core.h>
> +#include <linux/mmc/card.h>
> +#include <linux/mmc/slot-gpio.h>
> +
> +#include "sunxi-mmc.h"
> +
> +static int sunxi_mmc_init_host(struct mmc_host *mmc)
> +{
> +       u32 rval;
> +       struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
> +       int ret;
> +
> +       ret =  clk_prepare_enable(smc_host->clk_ahb);
> +       if (ret) {
> +               dev_err(mmc_dev(smc_host->mmc), "AHB clk err %d\n", ret);
> +               return ret;
> +       }
> +       ret =  clk_prepare_enable(smc_host->clk_mod);
> +       if (ret) {
> +               dev_err(mmc_dev(smc_host->mmc), "MOD clk err %d\n", ret);
> +               clk_disable_unprepare(smc_host->clk_ahb);
> +               return ret;
> +       }
> +
> +       /* reset controller */
> +       rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HARDWARE_RESET;
> +       mci_writel(smc_host, REG_GCTRL, rval);
> +
> +       mci_writel(smc_host, REG_FTRGL, 0x20070008);
> +       mci_writel(smc_host, REG_TMOUT, 0xffffffff);
> +       mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask);
> +       mci_writel(smc_host, REG_RINTR, 0xffffffff);
> +       mci_writel(smc_host, REG_DBGC, 0xdeb);
> +       mci_writel(smc_host, REG_FUNS, 0xceaa0000);
> +       mci_writel(smc_host, REG_DLBA, smc_host->sg_dma);
> +       rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTERRUPT_ENABLE_BIT;
> +       rval &= ~SDXC_ACCESS_DONE_DIRECT;
> +       mci_writel(smc_host, REG_GCTRL, rval);
> +
> +       return 0;
> +}
> +
> +static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host)
> +{
> +       mci_writel(smc_host, REG_GCTRL, SDXC_HARDWARE_RESET);
> +       clk_disable_unprepare(smc_host->clk_ahb);
> +       clk_disable_unprepare(smc_host->clk_mod);
> +}
> +
> +/* /\* UHS-I Operation Modes */
> +/*  * DS               25MHz   12.5MB/s        3.3V */
> +/*  * HS               50MHz   25MB/s          3.3V */
> +/*  * SDR12    25MHz   12.5MB/s        1.8V */
> +/*  * SDR25    50MHz   25MB/s          1.8V */
> +/*  * SDR50    100MHz  50MB/s          1.8V */
> +/*  * SDR104   208MHz  104MB/s         1.8V */
> +/*  * DDR50    50MHz   50MB/s          1.8V */
> +/*  * MMC Operation Modes */
> +/*  * DS               26MHz   26MB/s          3/1.8/1.2V */
> +/*  * HS               52MHz   52MB/s          3/1.8/1.2V */
> +/*  * HSDDR    52MHz   104MB/s         3/1.8/1.2V */
> +/*  * HS200    200MHz  200MB/s         1.8/1.2V */
> +/*  * */
> +/*  * Spec. Timing */
> +/*  * SD3.0 */
> +/*  * Fcclk    Tcclk   Fsclk   Tsclk   Tis     Tih     odly  RTis     RTih */
> +/*  * 400K     2.5us   24M     41ns    5ns     5ns     1     2209ns   41ns */
> +/*  * 25M      40ns    600M    1.67ns  5ns     5ns     3     14.99ns  5.01ns */
> +/*  * 50M      20ns    600M    1.67ns  6ns     2ns     3     14.99ns  5.01ns */
> +/*  * 50MDDR   20ns    600M    1.67ns  6ns     0.8ns   2     6.67ns   3.33ns */
> +/*  * 104M     9.6ns   600M    1.67ns  3ns     0.8ns   1     7.93ns   1.67ns */
> +/*  * 208M     4.8ns   600M    1.67ns  1.4ns   0.8ns   1     3.33ns   1.67ns */
> +
> +/*  * 25M      40ns    300M    3.33ns  5ns     5ns     2     13.34ns   6.66ns */
> +/*  * 50M      20ns    300M    3.33ns  6ns     2ns     2     13.34ns   6.66ns */
> +/*  * 50MDDR   20ns    300M    3.33ns  6ns     0.8ns   1     6.67ns    3.33ns */
> +/*  * 104M     9.6ns   300M    3.33ns  3ns     0.8ns   0     7.93ns    1.67ns */
> +/*  * 208M     4.8ns   300M    3.33ns  1.4ns   0.8ns   0     3.13ns    1.67ns */
> +
> +/*  * eMMC4.5 */
> +/*  * 400K     2.5us   24M     41ns    3ns     3ns     1     2209ns    41ns */
> +/*  * 25M      40ns    600M    1.67ns  3ns     3ns     3     14.99ns   5.01ns */
> +/*  * 50M      20ns    600M    1.67ns  3ns     3ns     3     14.99ns   5.01ns */
> +/*  * 50MDDR   20ns    600M    1.67ns  2.5ns   2.5ns   2     6.67ns    3.33ns */
> +/*  * 200M     5ns     600M    1.67ns  1.4ns   0.8ns   1     3.33ns    1.67ns */
> +/*  *\/ */
> +
> +static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
> +                                   struct mmc_data *data)
> +{
> +       struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
> +       struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma;
> +       int i, max_len = (1 << host->idma_des_size_bits);
> +
> +       for (i = 0; i < data->sg_len; i++) {
> +               pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN |
> +                                SDXC_IDMAC_DES0_DIC;
> +
> +               if (data->sg[i].length == max_len)
> +                       pdes[i].buf_size = 0; /* 0 == max_len */
> +               else
> +                       pdes[i].buf_size = data->sg[i].length;
> +
> +               pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]);
> +               pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1];
> +       }
> +
> +       pdes[0].config |= SDXC_IDMAC_DES0_FD;
> +       pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD;
> +
> +       wmb(); /* Ensure idma_des hit main mem before we start the idmac */
> +}
> +
> +static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data)
> +{
> +       if (data->flags & MMC_DATA_WRITE)
> +               return DMA_TO_DEVICE;
> +       else
> +               return DMA_FROM_DEVICE;
> +}
> +
> +static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host,
> +                                struct mmc_data *data)
> +{
> +       u32 dma_len;
> +       u32 i;
> +       u32 temp;
> +       struct scatterlist *sg;
> +
> +       dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len,
> +                            sunxi_mmc_get_dma_dir(data));
> +       if (dma_len == 0) {
> +               dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n");
> +               return -ENOMEM;
> +       }
> +
> +       for_each_sg(data->sg, sg, data->sg_len, i) {
> +               if (sg->offset & 3 || sg->length & 3) {
> +                       dev_err(mmc_dev(smc_host->mmc),
> +                               "unaligned scatterlist: os %x length %d\n",
> +                               sg->offset, sg->length);
> +                       return -EINVAL;
> +               }
> +       }
> +
> +       sunxi_mmc_init_idma_des(smc_host, data);
> +
> +       temp = mci_readl(smc_host, REG_GCTRL);
> +       temp |= SDXC_DMA_ENABLE_BIT;
> +       mci_writel(smc_host, REG_GCTRL, temp);
> +       temp |= SDXC_DMA_RESET;
> +       mci_writel(smc_host, REG_GCTRL, temp);
> +       mci_writel(smc_host, REG_DMAC, SDXC_IDMAC_SOFT_RESET);
> +
> +       if (!(data->flags & MMC_DATA_WRITE))
> +               mci_writel(smc_host, REG_IDIE, SDXC_IDMAC_RECEIVE_INTERRUPT);
> +
> +       mci_writel(smc_host, REG_DMAC, SDXC_IDMAC_FIX_BURST | SDXC_IDMAC_IDMA_ON);
> +
> +       return 0;
> +}
> +
> +static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host,
> +                                      struct mmc_request *req)
> +{
> +       u32 cmd_val = SDXC_START | SDXC_RESPONSE_EXPIRE | SDXC_STOP_ABORT_CMD
> +                       | SDXC_CHECK_RESPONSE_CRC | MMC_STOP_TRANSMISSION;
> +       u32 ri = 0;
> +       unsigned long expire = jiffies + msecs_to_jiffies(1000);
> +
> +       mci_writel(host, REG_CARG, 0);
> +       mci_writel(host, REG_CMDR, cmd_val);
> +
> +       do {
> +               ri = mci_readl(host, REG_RINTR);
> +       } while (!(ri & (SDXC_COMMAND_DONE | SDXC_INTERRUPT_ERROR_BIT)) &&
> +                time_before(jiffies, expire));
> +
> +       if (ri & SDXC_INTERRUPT_ERROR_BIT) {
> +               dev_err(mmc_dev(host->mmc), "send stop command failed\n");
> +               if (req->stop)
> +                       req->stop->resp[0] = -ETIMEDOUT;
> +       } else {
> +               if (req->stop)
> +                       req->stop->resp[0] = mci_readl(host, REG_RESP0);
> +       }
> +
> +       mci_writel(host, REG_RINTR, 0xffff);
> +}
> +
> +static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host)
> +{
> +       struct mmc_command *cmd = smc_host->mrq->cmd;
> +       struct mmc_data *data = smc_host->mrq->data;
> +
> +       /* For some cmds timeout is normal with sd/mmc cards */
> +       if ((smc_host->int_sum & SDXC_INTERRUPT_ERROR_BIT) == SDXC_RESPONSE_TIMEOUT &&
> +                       (cmd->opcode == SD_IO_SEND_OP_COND || cmd->opcode == SD_IO_RW_DIRECT))
> +               return;
> +
> +       dev_err(mmc_dev(smc_host->mmc),
> +               "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n",
> +               smc_host->mmc->index, cmd->opcode,
> +               data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "",
> +               smc_host->int_sum & SDXC_RESPONSE_ERROR     ? " RE"     : "",
> +               smc_host->int_sum & SDXC_RESPONSE_CRC_ERROR  ? " RCE"    : "",
> +               smc_host->int_sum & SDXC_DATA_CRC_ERROR  ? " DCE"    : "",
> +               smc_host->int_sum & SDXC_RESPONSE_TIMEOUT ? " RTO"    : "",
> +               smc_host->int_sum & SDXC_DATA_TIMEOUT ? " DTO"    : "",
> +               smc_host->int_sum & SDXC_FIFO_RUN_ERROR  ? " FE"     : "",
> +               smc_host->int_sum & SDXC_HARD_WARE_LOCKED ? " HL"     : "",
> +               smc_host->int_sum & SDXC_START_BIT_ERROR ? " SBE"    : "",
> +               smc_host->int_sum & SDXC_END_BIT_ERROR   ? " EBE"    : ""
> +               );
> +}
> +
> +static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host)
> +{
> +       struct mmc_request *mrq;
> +       unsigned long iflags;
> +
> +       spin_lock_irqsave(&host->lock, iflags);
> +
> +       mrq = host->mrq;
> +       if (!mrq) {
> +               spin_unlock_irqrestore(&host->lock, iflags);
> +               dev_err(mmc_dev(host->mmc), "no request to finalize\n");
> +               return;
> +       }
> +
> +       if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) {
> +               sunxi_mmc_dump_errinfo(host);
> +               mrq->cmd->error = -ETIMEDOUT;
> +               if (mrq->data)
> +                       mrq->data->error = -ETIMEDOUT;
> +               if (mrq->stop)
> +                       mrq->stop->error = -ETIMEDOUT;
> +       } else {
> +               if (mrq->cmd->flags & MMC_RSP_136) {
> +                       mrq->cmd->resp[0] = mci_readl(host, REG_RESP3);
> +                       mrq->cmd->resp[1] = mci_readl(host, REG_RESP2);
> +                       mrq->cmd->resp[2] = mci_readl(host, REG_RESP1);
> +                       mrq->cmd->resp[3] = mci_readl(host, REG_RESP0);
> +               } else {
> +                       mrq->cmd->resp[0] = mci_readl(host, REG_RESP0);
> +               }
> +               if (mrq->data)
> +                       mrq->data->bytes_xfered =
> +                               mrq->data->blocks * mrq->data->blksz;
> +       }
> +
> +       if (mrq->data) {
> +               struct mmc_data *data = mrq->data;
> +               u32 temp;
> +
> +               mci_writel(host, REG_IDST, 0x337);
> +               mci_writel(host, REG_DMAC, 0);
> +               temp = mci_readl(host, REG_GCTRL);
> +               mci_writel(host, REG_GCTRL, temp|SDXC_DMA_RESET);
> +               temp &= ~SDXC_DMA_ENABLE_BIT;
> +               mci_writel(host, REG_GCTRL, temp);
> +               temp |= SDXC_FIFO_RESET;
> +               mci_writel(host, REG_GCTRL, temp);
> +               dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
> +                                    sunxi_mmc_get_dma_dir(data));
> +       }
> +
> +       mci_writel(host, REG_RINTR, 0xffff);
> +
> +       dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n",
> +               mrq->cmd->resp[0], mrq->cmd->resp[1],
> +               mrq->cmd->resp[2], mrq->cmd->resp[3]);
> +
> +       host->mrq = NULL;
> +       host->int_sum = 0;
> +       host->wait_dma = 0;
> +
> +       spin_unlock_irqrestore(&host->lock, iflags);
> +
> +       if (mrq->data && mrq->data->error) {
> +               dev_err(mmc_dev(host->mmc),
> +                       "data error, sending stop command\n");
> +               sunxi_mmc_send_manual_stop(host, mrq);
> +       }
> +
> +       mmc_request_done(host->mmc, mrq);
> +}
> +
> +static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id)
> +{
> +       struct sunxi_mmc_host *host = dev_id;
> +       u32 finalize = 0;
> +       u32 sdio_int = 0;
> +       u32 msk_int;
> +       u32 idma_int;
> +
> +       spin_lock(&host->lock);
> +
> +       idma_int  = mci_readl(host, REG_IDST);
> +       msk_int   = mci_readl(host, REG_MISTA);
> +
> +       dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n",
> +               host->mrq, msk_int, idma_int);
> +
> +       if (host->mrq) {
> +               if (idma_int & SDXC_IDMAC_RECEIVE_INTERRUPT)
> +                       host->wait_dma = 0;
> +
> +               host->int_sum |= msk_int;
> +
> +               /* Wait for COMMAND_DONE on RESPONSE_TIMEOUT before finishing the req */
> +               if ((host->int_sum & SDXC_RESPONSE_TIMEOUT) &&
> +                               !(host->int_sum & SDXC_COMMAND_DONE))
> +                       mci_writel(host, REG_IMASK,
> +                                  host->sdio_imask | SDXC_COMMAND_DONE);
> +               else if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT)
> +                       finalize = 1; /* Don't wait for dma on error */
> +               else if (host->int_sum & SDXC_INTERRUPT_DONE_BIT && !host->wait_dma)
> +                       finalize = 1; /* Done */
> +
> +               if (finalize) {
> +                       mci_writel(host, REG_IMASK, host->sdio_imask);
> +                       mci_writel(host, REG_IDIE, 0);
> +               }
> +       }
> +
> +       if (msk_int & SDXC_SDIO_INTERRUPT)
> +               sdio_int = 1;
> +
> +       mci_writel(host, REG_RINTR, msk_int);
> +       mci_writel(host, REG_IDST, idma_int);
> +
> +       spin_unlock(&host->lock);
> +
> +       if (finalize)
> +               tasklet_schedule(&host->tasklet);
> +
> +       if (sdio_int)
> +               mmc_signal_sdio_irq(host->mmc);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static void sunxi_mmc_tasklet(unsigned long data)
> +{
> +       struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data;
> +       sunxi_mmc_finalize_request(smc_host);
> +}
> +
> +static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
> +{
> +       unsigned long expire = jiffies + msecs_to_jiffies(2000);
> +       u32 rval;
> +
> +       rval = mci_readl(host, REG_CLKCR);
> +       rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON);
> +
> +       if (oclk_en)
> +               rval |= SDXC_CARD_CLOCK_ON;
> +
> +       if (!host->io_flag)
> +               rval |= SDXC_LOW_POWER_ON;
> +
> +       mci_writel(host, REG_CLKCR, rval);
> +
> +       rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER;
> +       if (host->voltage_switching)
> +               rval |= SDXC_VOLTAGE_SWITCH;
> +       mci_writel(host, REG_CMDR, rval);
> +
> +       do {
> +               rval = mci_readl(host, REG_CMDR);
> +       } while (time_before(jiffies, expire) && (rval & SDXC_START));
> +
> +       if (rval & SDXC_START) {
> +               dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
> +               host->ferror = 1;
> +       }
> +}
> +
> +static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host,
> +                                 u32 oclk_dly, u32 sclk_dly)
> +{
> +       unsigned long iflags;
> +       struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
> +
> +       spin_lock_irqsave(&smc_host->lock, iflags);
> +       clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
> +       spin_unlock_irqrestore(&smc_host->lock, iflags);
> +}
> +
> +struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = {
> +       { MMC_CLK_400K, 0, 7 },
> +       { MMC_CLK_25M, 0, 5 },
> +       { MMC_CLK_50M, 3, 5 },
> +       { MMC_CLK_50MDDR, 2, 4 },
> +       { MMC_CLK_50MDDR_8BIT, 2, 4 },
> +       { MMC_CLK_100M, 1, 4 },
> +       { MMC_CLK_200M, 1, 4 },
> +};
> +
> +static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
> +                                  unsigned int rate)
> +{
> +       u32 newrate;
> +       u32 src_clk;
> +       u32 oclk_dly;
> +       u32 sclk_dly;
> +       u32 temp;
> +       struct sunxi_mmc_clk_dly *dly = NULL;
> +
> +       newrate = clk_round_rate(smc_host->clk_mod, rate);
> +       if (smc_host->clk_mod_rate == newrate) {
> +               dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n",
> +                       rate, newrate);
> +               return;
> +       }
> +
> +       dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n",
> +               rate, newrate);
> +
> +       /* setting clock rate */
> +       clk_disable(smc_host->clk_mod);
> +       clk_set_rate(smc_host->clk_mod, newrate);
> +       clk_enable(smc_host->clk_mod);
> +       smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod);
> +       dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate);
> +
> +       sunxi_mmc_oclk_onoff(smc_host, 0);
> +       /* clear internal divider */
> +       temp = mci_readl(smc_host, REG_CLKCR);
> +       temp &= ~0xff;
> +       mci_writel(smc_host, REG_CLKCR, temp);
> +
> +       /* determine delays */
> +       if (rate <= 400000) {
> +               dly = &mmc_clk_dly[MMC_CLK_400K];
> +       } else if (rate <= 25000000) {
> +               dly = &mmc_clk_dly[MMC_CLK_25M];
> +       } else if (rate <= 50000000) {
> +               if (smc_host->ddr) {
> +                       if (smc_host->bus_width == 8)
> +                               dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT];
> +                       else
> +                               dly = &mmc_clk_dly[MMC_CLK_50MDDR];
> +               } else {
> +                       dly = &mmc_clk_dly[MMC_CLK_50M];
> +               }
> +       } else if (rate <= 104000000) {
> +               dly = &mmc_clk_dly[MMC_CLK_100M];
> +       } else if (rate <= 208000000) {
> +               dly = &mmc_clk_dly[MMC_CLK_200M];
> +       } else {
> +               dly = &mmc_clk_dly[MMC_CLK_50M];
> +       }
> +
> +       oclk_dly = dly->oclk_dly;
> +       sclk_dly = dly->sclk_dly;
> +
> +       src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod));
> +
> +       if (src_clk >= 300000000 && src_clk <= 400000000) {
> +               if (oclk_dly)
> +                       oclk_dly--;
> +               if (sclk_dly)
> +                       sclk_dly--;
> +       }
> +
> +       sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly);
> +       sunxi_mmc_oclk_onoff(smc_host, 1);
> +
> +       /* oclk_onoff sets various irq status bits, clear these */
> +       mci_writel(smc_host, REG_RINTR,
> +                  mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT);
> +}
> +
> +static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> +       struct sunxi_mmc_host *host = mmc_priv(mmc);
> +       u32 temp;
> +       s32 err;
> +
> +       /* Set the power state */
> +       switch (ios->power_mode) {
> +       case MMC_POWER_ON:
> +               break;
> +
> +       case MMC_POWER_UP:
> +               if (!IS_ERR(host->vmmc)) {
> +                       mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd);
> +                       udelay(200);
> +               }
> +
> +               err = sunxi_mmc_init_host(mmc);
> +               if (err) {
> +                       host->ferror = 1;
> +                       return;
> +               }
> +               enable_irq(host->irq);
> +
> +               dev_dbg(mmc_dev(host->mmc), "power on!\n");
> +               host->ferror = 0;
> +               break;
> +
> +       case MMC_POWER_OFF:
> +               dev_dbg(mmc_dev(host->mmc), "power off!\n");
> +               disable_irq(host->irq);
> +               sunxi_mmc_exit_host(host);
> +               if (!IS_ERR(host->vmmc))
> +                       mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
> +               host->ferror = 0;
> +               break;
> +       }
> +
> +       /* set bus width */
> +       switch (ios->bus_width) {
> +       case MMC_BUS_WIDTH_1:
> +               mci_writel(host, REG_WIDTH, SDXC_WIDTH1);
> +               host->bus_width = 1;
> +               break;
> +       case MMC_BUS_WIDTH_4:
> +               mci_writel(host, REG_WIDTH, SDXC_WIDTH4);
> +               host->bus_width = 4;
> +               break;
> +       case MMC_BUS_WIDTH_8:
> +               mci_writel(host, REG_WIDTH, SDXC_WIDTH8);
> +               host->bus_width = 8;
> +               break;
> +       }
> +
> +       /* set ddr mode */
> +       temp = mci_readl(host, REG_GCTRL);
> +       if (ios->timing == MMC_TIMING_UHS_DDR50) {
> +               temp |= SDXC_DDR_MODE;
> +               host->ddr = 1;
> +       } else {
> +               temp &= ~SDXC_DDR_MODE;
> +               host->ddr = 0;
> +       }
> +       mci_writel(host, REG_GCTRL, temp);
> +
> +       /* set up clock */
> +       if (ios->clock && ios->power_mode) {
> +               dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock);
> +               sunxi_mmc_clk_set_rate(host, ios->clock);
> +               usleep_range(50000, 55000);
> +       }
> +}
> +
> +static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
> +{
> +       struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
> +       unsigned long flags;
> +       u32 imask;
> +
> +       spin_lock_irqsave(&smc_host->lock, flags);
> +       imask = mci_readl(smc_host, REG_IMASK);
> +       if (enable) {
> +               smc_host->sdio_imask = SDXC_SDIO_INTERRUPT;
> +               imask |= SDXC_SDIO_INTERRUPT;
> +       } else {
> +               smc_host->sdio_imask = 0;
> +               imask &= ~SDXC_SDIO_INTERRUPT;
> +       }
> +       mci_writel(smc_host, REG_IMASK, imask);
> +       spin_unlock_irqrestore(&smc_host->lock, flags);
> +}
> +
> +static void sunxi_mmc_hw_reset(struct mmc_host *mmc)
> +{
> +       struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
> +       mci_writel(smc_host, REG_HWRST, 0);
> +       udelay(10);
> +       mci_writel(smc_host, REG_HWRST, 1);
> +       udelay(300);
> +}
> +
> +static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +       struct sunxi_mmc_host *host = mmc_priv(mmc);
> +       struct mmc_command *cmd = mrq->cmd;
> +       struct mmc_data *data = mrq->data;
> +       unsigned long iflags;
> +       u32 imask = SDXC_INTERRUPT_ERROR_BIT;
> +       u32 cmd_val = SDXC_START | (cmd->opcode & 0x3f);
> +       u32 byte_cnt = 0;
> +       int ret;
> +
> +       if (!mmc_gpio_get_cd(mmc) || host->ferror) {
> +               dev_dbg(mmc_dev(host->mmc), "no medium present\n");
> +               mrq->cmd->error = -ENOMEDIUM;
> +               mmc_request_done(mmc, mrq);
> +               return;
> +       }
> +
> +       if (data) {
> +               byte_cnt = data->blksz * data->blocks;
> +               mci_writel(host, REG_BLKSZ, data->blksz);
> +               mci_writel(host, REG_BCNTR, byte_cnt);
> +               ret = sunxi_mmc_prepare_dma(host, data);
> +               if (ret < 0) {
> +                       dev_err(mmc_dev(host->mmc), "prepare DMA failed\n");
> +                       cmd->error = ret;
> +                       cmd->data->error = ret;
> +                       mmc_request_done(host->mmc, mrq);
> +                       return;
> +               }
> +       }
> +
> +       if (cmd->opcode == MMC_GO_IDLE_STATE) {
> +               cmd_val |= SDXC_SEND_INIT_SEQUENCE;
> +               imask |= SDXC_COMMAND_DONE;
> +       }
> +
> +       if (cmd->opcode == SD_SWITCH_VOLTAGE) {
> +               cmd_val |= SDXC_VOLTAGE_SWITCH;
> +               imask |= SDXC_VOLTAGE_CHANGE_DONE;
> +               host->voltage_switching = 1;
> +               sunxi_mmc_oclk_onoff(host, 1);
> +       }
> +
> +       if (cmd->flags & MMC_RSP_PRESENT) {
> +               cmd_val |= SDXC_RESPONSE_EXPIRE;
> +               if (cmd->flags & MMC_RSP_136)
> +                       cmd_val |= SDXC_LONG_RESPONSE;
> +               if (cmd->flags & MMC_RSP_CRC)
> +                       cmd_val |= SDXC_CHECK_RESPONSE_CRC;
> +
> +               if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) {
> +                       cmd_val |= SDXC_DATA_EXPIRE | SDXC_WAIT_PRE_OVER;
> +                       if (cmd->data->flags & MMC_DATA_STREAM) {
> +                               imask |= SDXC_AUTO_COMMAND_DONE;
> +                               cmd_val |= SDXC_SEQUENCE_MODE | SDXC_SEND_AUTO_STOP;
> +                       }
> +                       if (cmd->data->stop) {
> +                               imask |= SDXC_AUTO_COMMAND_DONE;
> +                               cmd_val |= SDXC_SEND_AUTO_STOP;
> +                       } else
> +                               imask |= SDXC_DATA_OVER;
> +
> +                       if (cmd->data->flags & MMC_DATA_WRITE)
> +                               cmd_val |= SDXC_WRITE;
> +                       else
> +                               host->wait_dma = 1;
> +               } else
> +                       imask |= SDXC_COMMAND_DONE;
> +       } else
> +               imask |= SDXC_COMMAND_DONE;
> +
> +       dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n",
> +               cmd_val & 0x3f, cmd_val, cmd->arg, imask,
> +               mrq->data ? mrq->data->blksz * mrq->data->blocks : 0);
> +
> +       spin_lock_irqsave(&host->lock, iflags);
> +       host->mrq = mrq;
> +       mci_writel(host, REG_IMASK, host->sdio_imask | imask);
> +       spin_unlock_irqrestore(&host->lock, iflags);
> +
> +       mci_writel(host, REG_CARG, cmd->arg);
> +       mci_writel(host, REG_CMDR, cmd_val);
> +}
> +
> +static const struct of_device_id sunxi_mmc_of_match[] = {
> +       { .compatible = "allwinner,sun4i-a10-mmc", },
> +       { .compatible = "allwinner,sun5i-a13-mmc", },
> +       { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
> +
> +static struct mmc_host_ops sunxi_mmc_ops = {
> +       .request         = sunxi_mmc_request,
> +       .set_ios         = sunxi_mmc_set_ios,
> +       .get_ro          = mmc_gpio_get_ro,
> +       .get_cd          = mmc_gpio_get_cd,
> +       .enable_sdio_irq = sunxi_mmc_enable_sdio_irq,
> +       .hw_reset        = sunxi_mmc_hw_reset,
> +};
> +
> +static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
> +                                     struct platform_device *pdev)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       int ret;
> +
> +       if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc"))
> +               host->idma_des_size_bits = 13;
> +       else
> +               host->idma_des_size_bits = 16;
> +
> +       host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc");
> +       if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER)
> +               return -EPROBE_DEFER;
> +
> +       host->reg_base = devm_ioremap_resource(&pdev->dev,
> +                             platform_get_resource(pdev, IORESOURCE_MEM, 0));
> +       if (IS_ERR(host->reg_base))
> +               return PTR_ERR(host->reg_base);
> +
> +       host->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
> +       if (IS_ERR(host->clk_ahb)) {
> +               dev_err(&pdev->dev, "Could not get ahb clock\n");
> +               return PTR_ERR(host->clk_ahb);
> +       }
> +
> +       host->clk_mod = devm_clk_get(&pdev->dev, "mod");
> +       if (IS_ERR(host->clk_mod)) {
> +               dev_err(&pdev->dev, "Could not get mod clock\n");
> +               return PTR_ERR(host->clk_mod);
> +       }
> +
> +       /* Make sure the controller is in a sane state before enabling irqs */
> +       ret = sunxi_mmc_init_host(host->mmc);
> +       if (ret)
> +               return ret;
> +
> +       host->irq = platform_get_irq(pdev, 0);
> +       ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0,
> +                              "sunxi-mci", host);
> +       if (ret == 0)
> +               disable_irq(host->irq);
> +
> +       /* And put it back in reset */
> +       sunxi_mmc_exit_host(host);
> +
> +       return ret;
> +}
> +
> +static int sunxi_mmc_probe(struct platform_device *pdev)
> +{
> +       struct sunxi_mmc_host *host;
> +       struct mmc_host *mmc;
> +       int ret;
> +
> +       mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev);
> +       if (!mmc) {
> +               dev_err(&pdev->dev, "mmc alloc host failed\n");
> +               return -ENOMEM;
> +       }
> +
> +       ret = mmc_of_parse(mmc);
> +       if (ret)
> +               goto error_free_host;
> +
> +       host = mmc_priv(mmc);
> +       host->mmc = mmc;
> +       spin_lock_init(&host->lock);
> +       tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host);
> +
> +       ret = sunxi_mmc_resource_request(host, pdev);
> +       if (ret)
> +               goto error_free_host;
> +
> +       host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
> +                                         &host->sg_dma, GFP_KERNEL);
> +       if (!host->sg_cpu) {
> +               dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n");
> +               ret = -ENOMEM;
> +               goto error_free_host;
> +       }
> +
> +       mmc->ops                = &sunxi_mmc_ops;
> +       mmc->max_blk_count      = 8192;
> +       mmc->max_blk_size       = 4096;
> +       mmc->max_segs           = PAGE_SIZE / sizeof(struct sunxi_idma_des);
> +       mmc->max_seg_size       = (1 << host->idma_des_size_bits);
> +       mmc->max_req_size       = mmc->max_seg_size * mmc->max_segs;
> +       /* 400kHz ~ 50MHz */
> +       mmc->f_min              =   400000;
> +       mmc->f_max              = 50000000;
> +       /* available voltages */
> +       if (!IS_ERR(host->vmmc))
> +               mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc);
> +       else
> +               mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
> +
> +       mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
> +               MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
> +               MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL |

I think you can drop MMC_CAP_NEEDS_POLL, now that you're using mmc core GPIO
functions, which use GPIO irqs when possible, and sets MMC_CAP_NEEDS_POLL if
that fails.


Cheers
ChenYu

> +               MMC_CAP_DRIVER_TYPE_A;
> +
> +       if (host->bus_width == 4)
> +               mmc->caps |= MMC_CAP_4_BIT_DATA;
> +
> +       mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
> +
> +       ret = mmc_add_host(mmc);
> +
> +       if (ret)
> +               goto error_free_dma;
> +
> +       dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq);
> +       platform_set_drvdata(pdev, mmc);
> +       return 0;
> +
> +error_free_dma:
> +       dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
> +error_free_host:
> +       mmc_free_host(mmc);
> +       return ret;
> +}
> +
> +static int sunxi_mmc_remove(struct platform_device *pdev)
> +{
> +       struct mmc_host *mmc = platform_get_drvdata(pdev);
> +       struct sunxi_mmc_host *host = mmc_priv(mmc);
> +
> +       mmc_remove_host(mmc);
> +       sunxi_mmc_exit_host(host);
> +       tasklet_disable(&host->tasklet);
> +       dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
> +       mmc_free_host(mmc);
> +
> +       return 0;
> +}
> +
> +static struct platform_driver sunxi_mmc_driver = {
> +       .driver = {
> +               .name   = "sunxi-mci",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(sunxi_mmc_of_match),
> +       },
> +       .probe          = sunxi_mmc_probe,
> +       .remove         = sunxi_mmc_remove,
> +};
> +module_platform_driver(sunxi_mmc_driver);
> +
> +MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org>");
> +MODULE_ALIAS("platform:sunxi-mmc");
[..]

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/groups/opt_out.

^ permalink raw reply

* Re: [PATCH 1/2] ARM: shmobile: r8a7778/r8a7779 dtsi: Improve and correct HSPI bindings
From: Kuninori Morimoto @ 2014-02-13  7:11 UTC (permalink / raw)
  To: Simon Horman
  Cc: Geert Uytterhoeven, Kuninori Morimoto,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA, linux-sh-u79uwXL29TY76Z2rM5mHXA,
	Geert Uytterhoeven, Mark Brown
In-Reply-To: <20140213055600.GF17183-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>


Hi Simon, Geert
Cc Mark

> could you test this series as Geert does not have access to a bockw board?
> 
> On Tue, Feb 11, 2014 at 09:56:47AM +0100, Geert Uytterhoeven wrote:
> > From: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
> > 
> > Binding documentation:
> >   - Add future-proof "renesas,hspi-<soctype>" compatible values,
> >   - Add "interrupt-parent", "#address-cells" and "#size-cells" properties,
> >   - Add reference to pinctrl documentation,
> >   - Add example bindings.
> > 
> > r8a7778 and r8a7779 dtsi:
> >   - Add "renesas,hspi-r8a7778" resp. "renesas,hspi-r8a7779" compatible
> >     values,
> >   - Correct reference to parent interrupt controller
> >     (use "interrupt-parent" instead of "interrupt-controller"),
> >   - Add missing "#address-cells" and "#size-cells" properties, which are
> >     needed when populating the SPI buses.
> > 
> > Signed-off-by: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
> > Cc: Mark Brown <broonie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > ---

I tested this patch, and it works well.
But there are some notes

1) m25p80 driver DT support seems strange ??

   ${LINUX}/Documentation/devicetree/bindings/mtd/m25p80.txt
   has explain about DT of m25p80 driver, but,
   ${LINUX}/drivers/mtd/devices/m25p80.c
   doesn't have driver :: of_match_table.
   but, it is using of_property_read_bool() on probe.
   Is it out-of-tree support ?? I'm not sure,
   anyway, m25p80 driver didn't probe.
   So, I quick-hacked this issue in my local environment.

2) it needs Geert's this patch

   Subject: [PATCH] mtd: m25p80: add support for the Spansion s25fl008k chip
   Date:	Tue, 11 Feb 2014 09:51:18 +0100

   Kernel will hung-up without this patch

For HSPI / BockW point of view

Tested-by: Kuninori Morimoto <kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" 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 0/14] Xilinx axi ethernet patches
From: Michal Simek @ 2014-02-13  7:00 UTC (permalink / raw)
  To: David Miller
  Cc: michal.simek, netdev, sthokal, devicetree, monstr, John.Linn,
	anirudh, linux-kernel, grant.likely, robh+dt, linux-arm-kernel
In-Reply-To: <20140212.191846.1464564509609498703.davem@davemloft.net>

On 02/13/2014 01:18 AM, David Miller wrote:
> From: Michal Simek <michal.simek@xilinx.com>
> Date: Wed, 12 Feb 2014 16:55:34 +0100
> 
>> I have exctracted patches which I have in our
>> xilinx git tree which are missing in the mainline.
>>
>> The first two patches fix compilation error and
>> warnings. Then 5 feature patches
>> and the rest is OF cleanup and with kernel-doc
>> and checkpatch problems.
> 
> You should not combine bug fix and feature patches.
> 
> Rather, you should submit bug fixes against the 'net' tree.  Then when
> those bug fixes get applied and propagate to the 'net-next' tree you
> can submit the feature patches and cleanups against the 'net-next'
> tree.

Ok. I will.

Thanks,
Michal

^ permalink raw reply

* [PATCH v3 3/3] Documentation: mfd: Add binding document for S2MPA01
From: Sachin Kamat @ 2014-02-13  6:37 UTC (permalink / raw)
  To: devicetree, linux-kernel
  Cc: mark.rutland, sbkim73, lee.jones, broonie, sachin.kamat
In-Reply-To: <1392273476-32736-1-git-send-email-sachin.kamat@linaro.org>

Added initial binding documentation for S2MPA01 MFD.

Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
---
Changes since v2:
* Re-worded as suggested by Mark Rutland
---
 Documentation/devicetree/bindings/mfd/s2mpa01.txt |   90 +++++++++++++++++++++
 1 file changed, 90 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/s2mpa01.txt

diff --git a/Documentation/devicetree/bindings/mfd/s2mpa01.txt b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
new file mode 100644
index 000000000000..c13d3d8c3947
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
@@ -0,0 +1,90 @@
+
+* Samsung S2MPA01 Voltage and Current Regulator
+
+The Samsung S2MPA01 is a multi-function device which includes high
+efficiency buck converters including Dual-Phase buck converter, various LDOs,
+and an RTC. It is interfaced to the host controller using an I2C interface.
+Each sub-block is addressed by the host system using different I2C slave
+addresses.
+
+Required properties:
+- compatible: Should be "samsung,s2mpa01-pmic".
+- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from s2mpa01 are delivered to.
+- interrupts: An interrupt specifier for the sole interrupt generated by the
+  device.
+
+Optional nodes:
+- regulators: The regulators of s2mpa01 that have to be instantiated should be
+  included in a sub-node named 'regulators'. Regulator nodes and constraints
+  included in this sub-node use the standard regulator bindings which are
+  documented elsewhere.
+
+Properties for BUCK regulator nodes:
+- regulator-ramp-delay: ramp delay in uV/us. May be 6250, 12500
+  (default), 25000, or 50000. May be 0 for disabling the ramp delay on
+  BUCK{1,2,3,4}.
+
+ In the absence of the regulator-ramp-delay property, the default ramp
+ delay will be used.
+
+  NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
+  for a particular group of BUCKs. So provide same regulator-ramp-delay=<value>.
+
+  The following BUCKs share ramp settings:
+  * 1 and 6
+  * 2 and 4
+  * 8, 9, and 10
+
+The following are the names of the regulators that the s2mpa01 PMIC block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of s2mpa01.
+
+	- LDOn
+		  - valid values for n are 1 to 26
+		  - Example: LDO1, LD02, LDO26
+	- BUCKn
+		  - valid values for n are 1 to 10.
+		  - Example: BUCK1, BUCK2, BUCK9
+
+Example:
+
+	s2mpa01_pmic@66 {
+		compatible = "samsung,s2mpa01-pmic";
+		reg = <0x66>;
+
+		regulators {
+			ldo1_reg: LDO1 {
+				regulator-name = "VDD_ALIVE";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "VDDQ_MMC2";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-always-on;
+			};
+
+			buck1_reg: BUCK1 {
+				regulator-name = "vdd_mif";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-ramp-delay = <50000>;
+			};
+		};
+	};
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 2/3] regulator: Add support for S2MPA01 regulator
From: Sachin Kamat @ 2014-02-13  6:37 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: mark.rutland-5wv7dgnIgG8, sbkim73-Sze3O3UU22JBDgjK7y7TUQ,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	sachin.kamat-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1392273476-32736-1-git-send-email-sachin.kamat-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Add support for S2MPA01 voltage and current regulator.

Signed-off-by: Sachin Kamat <sachin.kamat-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Acked-by: Mark Brown <broonie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
Changes since v2:
* Added missing of_node_put
* Used of_get_child_by_name
---
 drivers/regulator/Kconfig   |    7 +
 drivers/regulator/Makefile  |    1 +
 drivers/regulator/s2mpa01.c |  483 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 491 insertions(+)
 create mode 100644 drivers/regulator/s2mpa01.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6a7932822e37..8f8e6710bb45 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -416,6 +416,13 @@ config REGULATOR_RC5T583
 	  through regulator interface. The device supports multiple DCDC/LDO
 	  outputs which can be controlled by i2c communication.
 
+config REGULATOR_S2MPA01
+	tristate "Samsung S2MPA01 voltage regulator"
+	depends on MFD_SEC_CORE
+	help
+	 This driver controls Samsung S2MPA01 voltage output regulator
+	 via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
+
 config REGULATOR_S2MPS11
 	tristate "Samsung S2MPS11 voltage regulator"
 	depends on MFD_SEC_CORE
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 979f9ddcf259..b3ece84289cf 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
+obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c
new file mode 100644
index 000000000000..6ac6e8205a05
--- /dev/null
+++ b/drivers/regulator/s2mpa01.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ *		http://www.samsung.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mpa01.h>
+
+#define S2MPA01_REGULATOR_CNT ARRAY_SIZE(regulators)
+
+struct s2mpa01_info {
+	struct regulator_dev *rdev[S2MPA01_REGULATOR_MAX];
+
+	int ramp_delay24;
+	int ramp_delay3;
+	int ramp_delay5;
+	int ramp_delay16;
+	int ramp_delay7;
+	int ramp_delay8910;
+};
+
+static int get_ramp_delay(int ramp_delay)
+{
+	unsigned char cnt = 0;
+
+	ramp_delay /= 6250;
+
+	while (true) {
+		ramp_delay = ramp_delay >> 1;
+		if (ramp_delay == 0)
+			break;
+		cnt++;
+	}
+
+	if (cnt > 3)
+		cnt = 3;
+
+	return cnt;
+}
+
+static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+				   unsigned int old_selector,
+				   unsigned int new_selector)
+{
+	struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev);
+	unsigned int ramp_delay = 0;
+	int old_volt, new_volt;
+
+	switch (rdev->desc->id) {
+	case S2MPA01_BUCK2:
+	case S2MPA01_BUCK4:
+		ramp_delay = s2mpa01->ramp_delay24;
+		break;
+	case S2MPA01_BUCK3:
+		ramp_delay = s2mpa01->ramp_delay3;
+		break;
+	case S2MPA01_BUCK5:
+		ramp_delay = s2mpa01->ramp_delay5;
+		break;
+	case S2MPA01_BUCK1:
+	case S2MPA01_BUCK6:
+		ramp_delay = s2mpa01->ramp_delay16;
+		break;
+	case S2MPA01_BUCK7:
+		ramp_delay = s2mpa01->ramp_delay7;
+		break;
+	case S2MPA01_BUCK8:
+	case S2MPA01_BUCK9:
+	case S2MPA01_BUCK10:
+		ramp_delay = s2mpa01->ramp_delay8910;
+		break;
+	}
+
+	if (ramp_delay == 0)
+		ramp_delay = rdev->desc->ramp_delay;
+
+	old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector);
+	new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector);
+
+	return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
+}
+
+static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+	struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev);
+	unsigned int ramp_val, ramp_shift, ramp_reg = S2MPA01_REG_RAMP2;
+	unsigned int ramp_enable = 1, enable_shift = 0;
+	int ret;
+
+	switch (rdev->desc->id) {
+	case S2MPA01_BUCK1:
+		enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		if (ramp_delay > s2mpa01->ramp_delay16)
+			s2mpa01->ramp_delay16 = ramp_delay;
+		else
+			ramp_delay = s2mpa01->ramp_delay16;
+
+		ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT;
+		ramp_reg = S2MPA01_REG_RAMP1;
+		break;
+	case S2MPA01_BUCK2:
+		enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		if (ramp_delay > s2mpa01->ramp_delay24)
+			s2mpa01->ramp_delay24 = ramp_delay;
+		else
+			ramp_delay = s2mpa01->ramp_delay24;
+
+		ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT;
+		ramp_reg = S2MPA01_REG_RAMP1;
+		break;
+	case S2MPA01_BUCK3:
+		enable_shift = S2MPA01_BUCK3_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		s2mpa01->ramp_delay3 = ramp_delay;
+		ramp_shift = S2MPA01_BUCK3_RAMP_SHIFT;
+		ramp_reg = S2MPA01_REG_RAMP1;
+		break;
+	case S2MPA01_BUCK4:
+		enable_shift = S2MPA01_BUCK4_RAMP_EN_SHIFT;
+		if (!ramp_delay) {
+			ramp_enable = 0;
+			break;
+		}
+
+		if (ramp_delay > s2mpa01->ramp_delay24)
+			s2mpa01->ramp_delay24 = ramp_delay;
+		else
+			ramp_delay = s2mpa01->ramp_delay24;
+
+		ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT;
+		ramp_reg = S2MPA01_REG_RAMP1;
+		break;
+	case S2MPA01_BUCK5:
+		s2mpa01->ramp_delay5 = ramp_delay;
+		ramp_shift = S2MPA01_BUCK5_RAMP_SHIFT;
+		break;
+	case S2MPA01_BUCK6:
+		if (ramp_delay > s2mpa01->ramp_delay16)
+			s2mpa01->ramp_delay16 = ramp_delay;
+		else
+			ramp_delay = s2mpa01->ramp_delay16;
+
+		ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT;
+		break;
+	case S2MPA01_BUCK7:
+		s2mpa01->ramp_delay7 = ramp_delay;
+		ramp_shift = S2MPA01_BUCK7_RAMP_SHIFT;
+		break;
+	case S2MPA01_BUCK8:
+	case S2MPA01_BUCK9:
+	case S2MPA01_BUCK10:
+		if (ramp_delay > s2mpa01->ramp_delay8910)
+			s2mpa01->ramp_delay8910 = ramp_delay;
+		else
+			ramp_delay = s2mpa01->ramp_delay8910;
+
+		ramp_shift = S2MPA01_BUCK8910_RAMP_SHIFT;
+		break;
+	default:
+		return 0;
+	}
+
+	if (!ramp_enable)
+		goto ramp_disable;
+
+	if (enable_shift) {
+		ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
+					1 << enable_shift, 1 << enable_shift);
+		if (ret) {
+			dev_err(&rdev->dev, "failed to enable ramp rate\n");
+			return ret;
+		}
+	}
+
+	ramp_val = get_ramp_delay(ramp_delay);
+
+	return regmap_update_bits(rdev->regmap, ramp_reg, 0x3 << ramp_shift,
+				  ramp_val << ramp_shift);
+
+ramp_disable:
+	return regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
+				  1 << enable_shift, 0);
+}
+
+static struct regulator_ops s2mpa01_ldo_ops = {
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+};
+
+static struct regulator_ops s2mpa01_buck_ops = {
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.set_voltage_time_sel	= s2mpa01_regulator_set_voltage_time_sel,
+	.set_ramp_delay		= s2mpa01_set_ramp_delay,
+};
+
+#define regulator_desc_ldo1(num)	{		\
+	.name		= "LDO"#num,			\
+	.id		= S2MPA01_LDO##num,		\
+	.ops		= &s2mpa01_ldo_ops,		\
+	.type		= REGULATOR_VOLTAGE,		\
+	.owner		= THIS_MODULE,			\
+	.min_uV		= S2MPA01_LDO_MIN,		\
+	.uV_step	= S2MPA01_LDO_STEP1,		\
+	.n_voltages	= S2MPA01_LDO_N_VOLTAGES,	\
+	.vsel_reg	= S2MPA01_REG_L1CTRL + num - 1,	\
+	.vsel_mask	= S2MPA01_LDO_VSEL_MASK,	\
+	.enable_reg	= S2MPA01_REG_L1CTRL + num - 1,	\
+	.enable_mask	= S2MPA01_ENABLE_MASK		\
+}
+#define regulator_desc_ldo2(num)	{		\
+	.name		= "LDO"#num,			\
+	.id		= S2MPA01_LDO##num,		\
+	.ops		= &s2mpa01_ldo_ops,		\
+	.type		= REGULATOR_VOLTAGE,		\
+	.owner		= THIS_MODULE,			\
+	.min_uV		= S2MPA01_LDO_MIN,		\
+	.uV_step	= S2MPA01_LDO_STEP2,		\
+	.n_voltages	= S2MPA01_LDO_N_VOLTAGES,	\
+	.vsel_reg	= S2MPA01_REG_L1CTRL + num - 1,	\
+	.vsel_mask	= S2MPA01_LDO_VSEL_MASK,	\
+	.enable_reg	= S2MPA01_REG_L1CTRL + num - 1,	\
+	.enable_mask	= S2MPA01_ENABLE_MASK		\
+}
+
+#define regulator_desc_buck1_4(num)	{			\
+	.name		= "BUCK"#num,				\
+	.id		= S2MPA01_BUCK##num,			\
+	.ops		= &s2mpa01_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPA01_BUCK_MIN1,			\
+	.uV_step	= S2MPA01_BUCK_STEP1,			\
+	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
+	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
+	.vsel_reg	= S2MPA01_REG_B1CTRL2 + (num - 1) * 2,	\
+	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPA01_REG_B1CTRL1 + (num - 1) * 2,	\
+	.enable_mask	= S2MPA01_ENABLE_MASK			\
+}
+
+#define regulator_desc_buck5	{				\
+	.name		= "BUCK5",				\
+	.id		= S2MPA01_BUCK5,			\
+	.ops		= &s2mpa01_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPA01_BUCK_MIN2,			\
+	.uV_step	= S2MPA01_BUCK_STEP1,			\
+	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
+	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
+	.vsel_reg	= S2MPA01_REG_B5CTRL2,			\
+	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPA01_REG_B5CTRL1,			\
+	.enable_mask	= S2MPA01_ENABLE_MASK			\
+}
+
+#define regulator_desc_buck6_7(num)	{			\
+	.name		= "BUCK"#num,				\
+	.id		= S2MPA01_BUCK##num,			\
+	.ops		= &s2mpa01_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPA01_BUCK_MIN1,			\
+	.uV_step	= S2MPA01_BUCK_STEP1,			\
+	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
+	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
+	.vsel_reg	= S2MPA01_REG_B6CTRL2 + (num - 6) * 2,	\
+	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPA01_REG_B6CTRL1 + (num - 6) * 2,	\
+	.enable_mask	= S2MPA01_ENABLE_MASK			\
+}
+
+#define regulator_desc_buck8	{				\
+	.name		= "BUCK8",				\
+	.id		= S2MPA01_BUCK8,			\
+	.ops		= &s2mpa01_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPA01_BUCK_MIN2,			\
+	.uV_step	= S2MPA01_BUCK_STEP2,			\
+	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
+	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
+	.vsel_reg	= S2MPA01_REG_B8CTRL2,			\
+	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPA01_REG_B8CTRL1,			\
+	.enable_mask	= S2MPA01_ENABLE_MASK			\
+}
+
+#define regulator_desc_buck9	{				\
+	.name		= "BUCK9",				\
+	.id		= S2MPA01_BUCK9,			\
+	.ops		= &s2mpa01_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPA01_BUCK_MIN4,			\
+	.uV_step	= S2MPA01_BUCK_STEP2,			\
+	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
+	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
+	.vsel_reg	= S2MPA01_REG_B9CTRL2,			\
+	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPA01_REG_B9CTRL1,			\
+	.enable_mask	= S2MPA01_ENABLE_MASK			\
+}
+
+#define regulator_desc_buck10	{				\
+	.name		= "BUCK10",				\
+	.id		= S2MPA01_BUCK10,			\
+	.ops		= &s2mpa01_buck_ops,			\
+	.type		= REGULATOR_VOLTAGE,			\
+	.owner		= THIS_MODULE,				\
+	.min_uV		= S2MPA01_BUCK_MIN3,			\
+	.uV_step	= S2MPA01_BUCK_STEP2,			\
+	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
+	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
+	.vsel_reg	= S2MPA01_REG_B10CTRL2,			\
+	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
+	.enable_reg	= S2MPA01_REG_B10CTRL1,			\
+	.enable_mask	= S2MPA01_ENABLE_MASK			\
+}
+
+static struct regulator_desc regulators[] = {
+	regulator_desc_ldo2(1),
+	regulator_desc_ldo1(2),
+	regulator_desc_ldo1(3),
+	regulator_desc_ldo1(4),
+	regulator_desc_ldo1(5),
+	regulator_desc_ldo2(6),
+	regulator_desc_ldo1(7),
+	regulator_desc_ldo1(8),
+	regulator_desc_ldo1(9),
+	regulator_desc_ldo1(10),
+	regulator_desc_ldo2(11),
+	regulator_desc_ldo1(12),
+	regulator_desc_ldo1(13),
+	regulator_desc_ldo1(14),
+	regulator_desc_ldo1(15),
+	regulator_desc_ldo1(16),
+	regulator_desc_ldo1(17),
+	regulator_desc_ldo1(18),
+	regulator_desc_ldo1(19),
+	regulator_desc_ldo1(20),
+	regulator_desc_ldo1(21),
+	regulator_desc_ldo2(22),
+	regulator_desc_ldo2(23),
+	regulator_desc_ldo1(24),
+	regulator_desc_ldo1(25),
+	regulator_desc_ldo1(26),
+	regulator_desc_buck1_4(1),
+	regulator_desc_buck1_4(2),
+	regulator_desc_buck1_4(3),
+	regulator_desc_buck1_4(4),
+	regulator_desc_buck5,
+	regulator_desc_buck6_7(6),
+	regulator_desc_buck6_7(7),
+	regulator_desc_buck8,
+	regulator_desc_buck9,
+	regulator_desc_buck10,
+};
+
+static int s2mpa01_pmic_probe(struct platform_device *pdev)
+{
+	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
+	struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX];
+	struct device_node *reg_np = NULL;
+	struct regulator_config config = { };
+	struct s2mpa01_info *s2mpa01;
+	int i, ret;
+
+	s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL);
+	if (!s2mpa01)
+		return -ENOMEM;
+
+	for (i = 0; i < S2MPA01_REGULATOR_CNT; i++)
+		rdata[i].name = regulators[i].name;
+
+	if (iodev->dev->of_node) {
+		reg_np = of_get_child_by_name(iodev->dev->of_node,
+							"regulators");
+			if (!reg_np) {
+				dev_err(&pdev->dev,
+					"could not find regulators sub-node\n");
+				return -EINVAL;
+			}
+
+		of_regulator_match(&pdev->dev, reg_np, rdata,
+						S2MPA01_REGULATOR_MAX);
+		of_node_put(reg_np);
+	}
+
+	platform_set_drvdata(pdev, s2mpa01);
+
+	config.dev = &pdev->dev;
+	config.regmap = iodev->regmap_pmic;
+	config.driver_data = s2mpa01;
+
+	for (i = 0; i < S2MPA01_REGULATOR_MAX; i++) {
+		if (pdata)
+			config.init_data = pdata->regulators[i].initdata;
+		else
+			config.init_data = rdata[i].init_data;
+
+		if (reg_np)
+			config.of_node = rdata[i].of_node;
+
+		s2mpa01->rdev[i] = devm_regulator_register(&pdev->dev,
+						&regulators[i], &config);
+		if (IS_ERR(s2mpa01->rdev[i])) {
+			ret = PTR_ERR(s2mpa01->rdev[i]);
+			dev_err(&pdev->dev, "regulator init failed for %d\n",
+				i);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id s2mpa01_pmic_id[] = {
+	{ "s2mpa01-pmic", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, s2mpa01_pmic_id);
+
+static struct platform_driver s2mpa01_pmic_driver = {
+	.driver = {
+		.name = "s2mpa01-pmic",
+		.owner = THIS_MODULE,
+	},
+	.probe = s2mpa01_pmic_probe,
+	.id_table = s2mpa01_pmic_id,
+};
+
+module_platform_driver(s2mpa01_pmic_driver);
+
+/* Module information */
+MODULE_AUTHOR("Sangbeom Kim <sbkim73-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>");
+MODULE_AUTHOR("Sachin Kamat <sachin.kamat-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>");
+MODULE_DESCRIPTION("SAMSUNG S2MPA01 Regulator Driver");
+MODULE_LICENSE("GPL");
-- 
1.7.9.5

--
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 v3 1/3] mfd: Add support for S2MPA01 device
From: Sachin Kamat @ 2014-02-13  6:37 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: mark.rutland-5wv7dgnIgG8, sbkim73-Sze3O3UU22JBDgjK7y7TUQ,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	sachin.kamat-QSEj5FYQhm4dnm+yROfE0A

Add the necessary entries required for S2MPA01 multi-function
device. While at it also convert whitespaces to tabs in core.h.

Signed-off-by: Sachin Kamat <sachin.kamat-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Acked-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
No change in v3 since v2.
---
 drivers/mfd/sec-core.c              |   45 +++++++-
 include/linux/mfd/samsung/core.h    |   16 ++-
 include/linux/mfd/samsung/irq.h     |   50 +++++++++
 include/linux/mfd/samsung/s2mpa01.h |  192 +++++++++++++++++++++++++++++++++++
 4 files changed, 295 insertions(+), 8 deletions(-)
 create mode 100644 include/linux/mfd/samsung/s2mpa01.h

diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index a139798b8065..564265c57fd9 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -26,6 +26,7 @@
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/rtc.h>
+#include <linux/mfd/samsung/s2mpa01.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s5m8763.h>
 #include <linux/mfd/samsung/s5m8767.h>
@@ -69,18 +70,40 @@ static const struct mfd_cell s2mps11_devs[] = {
 	}
 };
 
+static const struct mfd_cell s2mpa01_devs[] = {
+	{
+		.name = "s2mpa01-pmic",
+	},
+};
+
 #ifdef CONFIG_OF
 static struct of_device_id sec_dt_match[] = {
 	{	.compatible = "samsung,s5m8767-pmic",
 		.data = (void *)S5M8767X,
-	},
-	{	.compatible = "samsung,s2mps11-pmic",
+	}, {
+		.compatible = "samsung,s2mps11-pmic",
 		.data = (void *)S2MPS11X,
+	}, {
+		.compatible = "samsung,s2mpa01-pmic",
+		.data = (void *)S2MPA01,
+	}, {
+		/* Sentinel */
 	},
-	{},
 };
 #endif
 
+static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S2MPA01_REG_INT1M:
+	case S2MPA01_REG_INT2M:
+	case S2MPA01_REG_INT3M:
+		return false;
+	default:
+		return true;
+	}
+}
+
 static bool s2mps11_volatile(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -111,6 +134,15 @@ static const struct regmap_config sec_regmap_config = {
 	.val_bits = 8,
 };
 
+static const struct regmap_config s2mpa01_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MPA01_REG_LDO_OVCB4,
+	.volatile_reg = s2mpa01_volatile,
+	.cache_type = REGCACHE_FLAT,
+};
+
 static const struct regmap_config s2mps11_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -229,6 +261,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
 	}
 
 	switch (sec_pmic->device_type) {
+	case S2MPA01:
+		regmap = &s2mpa01_regmap_config;
+		break;
 	case S2MPS11X:
 		regmap = &s2mps11_regmap_config;
 		break;
@@ -283,6 +318,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
 		ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
 				      ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
 		break;
+	case S2MPA01:
+		ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs,
+				      ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL);
+		break;
 	case S2MPS11X:
 		ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
 				      ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 55510444b9fd..ab8c9d2f944e 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -18,6 +18,7 @@ enum sec_device_type {
 	S5M8751X,
 	S5M8763X,
 	S5M8767X,
+	S2MPA01,
 	S2MPS11X,
 };
 
@@ -92,7 +93,7 @@ struct sec_platform_data {
 	int				buck3_default_idx;
 	int				buck4_default_idx;
 
-	int                             buck_ramp_delay;
+	int				buck_ramp_delay;
 
 	int				buck2_ramp_delay;
 	int				buck34_ramp_delay;
@@ -100,10 +101,15 @@ struct sec_platform_data {
 	int				buck16_ramp_delay;
 	int				buck7810_ramp_delay;
 	int				buck9_ramp_delay;
-
-	bool                            buck2_ramp_enable;
-	bool                            buck3_ramp_enable;
-	bool                            buck4_ramp_enable;
+	int				buck24_ramp_delay;
+	int				buck3_ramp_delay;
+	int				buck7_ramp_delay;
+	int				buck8910_ramp_delay;
+
+	bool				buck1_ramp_enable;
+	bool				buck2_ramp_enable;
+	bool				buck3_ramp_enable;
+	bool				buck4_ramp_enable;
 	bool				buck6_ramp_enable;
 
 	int				buck2_init;
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
index d43b4f9e7fb2..2ca965948cd4 100644
--- a/include/linux/mfd/samsung/irq.h
+++ b/include/linux/mfd/samsung/irq.h
@@ -13,6 +13,56 @@
 #ifndef __LINUX_MFD_SEC_IRQ_H
 #define __LINUX_MFD_SEC_IRQ_H
 
+enum s2mpa01_irq {
+	S2MPA01_IRQ_PWRONF,
+	S2MPA01_IRQ_PWRONR,
+	S2MPA01_IRQ_JIGONBF,
+	S2MPA01_IRQ_JIGONBR,
+	S2MPA01_IRQ_ACOKBF,
+	S2MPA01_IRQ_ACOKBR,
+	S2MPA01_IRQ_PWRON1S,
+	S2MPA01_IRQ_MRB,
+
+	S2MPA01_IRQ_RTC60S,
+	S2MPA01_IRQ_RTCA1,
+	S2MPA01_IRQ_RTCA0,
+	S2MPA01_IRQ_SMPL,
+	S2MPA01_IRQ_RTC1S,
+	S2MPA01_IRQ_WTSR,
+
+	S2MPA01_IRQ_INT120C,
+	S2MPA01_IRQ_INT140C,
+	S2MPA01_IRQ_LDO3_TSD,
+	S2MPA01_IRQ_B16_TSD,
+	S2MPA01_IRQ_B24_TSD,
+	S2MPA01_IRQ_B35_TSD,
+
+	S2MPA01_IRQ_NR,
+};
+
+#define S2MPA01_IRQ_PWRONF_MASK		(1 << 0)
+#define S2MPA01_IRQ_PWRONR_MASK		(1 << 1)
+#define S2MPA01_IRQ_JIGONBF_MASK	(1 << 2)
+#define S2MPA01_IRQ_JIGONBR_MASK	(1 << 3)
+#define S2MPA01_IRQ_ACOKBF_MASK		(1 << 4)
+#define S2MPA01_IRQ_ACOKBR_MASK		(1 << 5)
+#define S2MPA01_IRQ_PWRON1S_MASK	(1 << 6)
+#define S2MPA01_IRQ_MRB_MASK		(1 << 7)
+
+#define S2MPA01_IRQ_RTC60S_MASK		(1 << 0)
+#define S2MPA01_IRQ_RTCA1_MASK		(1 << 1)
+#define S2MPA01_IRQ_RTCA0_MASK		(1 << 2)
+#define S2MPA01_IRQ_SMPL_MASK		(1 << 3)
+#define S2MPA01_IRQ_RTC1S_MASK		(1 << 4)
+#define S2MPA01_IRQ_WTSR_MASK		(1 << 5)
+
+#define S2MPA01_IRQ_INT120C_MASK	(1 << 0)
+#define S2MPA01_IRQ_INT140C_MASK	(1 << 1)
+#define S2MPA01_IRQ_LDO3_TSD_MASK	(1 << 2)
+#define S2MPA01_IRQ_B16_TSD_MASK	(1 << 3)
+#define S2MPA01_IRQ_B24_TSD_MASK	(1 << 4)
+#define S2MPA01_IRQ_B35_TSD_MASK	(1 << 5)
+
 enum s2mps11_irq {
 	S2MPS11_IRQ_PWRONF,
 	S2MPS11_IRQ_PWRONR,
diff --git a/include/linux/mfd/samsung/s2mpa01.h b/include/linux/mfd/samsung/s2mpa01.h
new file mode 100644
index 000000000000..fbc63bc0d6a2
--- /dev/null
+++ b/include/linux/mfd/samsung/s2mpa01.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ *		http://www.samsung.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_S2MPA01_H
+#define __LINUX_MFD_S2MPA01_H
+
+/* S2MPA01 registers */
+enum s2mpa01_reg {
+	S2MPA01_REG_ID,
+	S2MPA01_REG_INT1,
+	S2MPA01_REG_INT2,
+	S2MPA01_REG_INT3,
+	S2MPA01_REG_INT1M,
+	S2MPA01_REG_INT2M,
+	S2MPA01_REG_INT3M,
+	S2MPA01_REG_ST1,
+	S2MPA01_REG_ST2,
+	S2MPA01_REG_PWRONSRC,
+	S2MPA01_REG_OFFSRC,
+	S2MPA01_REG_RTC_BUF,
+	S2MPA01_REG_CTRL1,
+	S2MPA01_REG_ETC_TEST,
+	S2MPA01_REG_RSVD1,
+	S2MPA01_REG_BU_CHG,
+	S2MPA01_REG_RAMP1,
+	S2MPA01_REG_RAMP2,
+	S2MPA01_REG_LDO_DSCH1,
+	S2MPA01_REG_LDO_DSCH2,
+	S2MPA01_REG_LDO_DSCH3,
+	S2MPA01_REG_LDO_DSCH4,
+	S2MPA01_REG_OTP_ADRL,
+	S2MPA01_REG_OTP_ADRH,
+	S2MPA01_REG_OTP_DATA,
+	S2MPA01_REG_MON1SEL,
+	S2MPA01_REG_MON2SEL,
+	S2MPA01_REG_LEE,
+	S2MPA01_REG_RSVD2,
+	S2MPA01_REG_RSVD3,
+	S2MPA01_REG_RSVD4,
+	S2MPA01_REG_RSVD5,
+	S2MPA01_REG_RSVD6,
+	S2MPA01_REG_TOP_RSVD,
+	S2MPA01_REG_DVS_SEL,
+	S2MPA01_REG_DVS_PTR,
+	S2MPA01_REG_DVS_DATA,
+	S2MPA01_REG_RSVD_NO,
+	S2MPA01_REG_UVLO,
+	S2MPA01_REG_LEE_NO,
+	S2MPA01_REG_B1CTRL1,
+	S2MPA01_REG_B1CTRL2,
+	S2MPA01_REG_B2CTRL1,
+	S2MPA01_REG_B2CTRL2,
+	S2MPA01_REG_B3CTRL1,
+	S2MPA01_REG_B3CTRL2,
+	S2MPA01_REG_B4CTRL1,
+	S2MPA01_REG_B4CTRL2,
+	S2MPA01_REG_B5CTRL1,
+	S2MPA01_REG_B5CTRL2,
+	S2MPA01_REG_B5CTRL3,
+	S2MPA01_REG_B5CTRL4,
+	S2MPA01_REG_B5CTRL5,
+	S2MPA01_REG_B5CTRL6,
+	S2MPA01_REG_B6CTRL1,
+	S2MPA01_REG_B6CTRL2,
+	S2MPA01_REG_B7CTRL1,
+	S2MPA01_REG_B7CTRL2,
+	S2MPA01_REG_B8CTRL1,
+	S2MPA01_REG_B8CTRL2,
+	S2MPA01_REG_B9CTRL1,
+	S2MPA01_REG_B9CTRL2,
+	S2MPA01_REG_B10CTRL1,
+	S2MPA01_REG_B10CTRL2,
+	S2MPA01_REG_L1CTRL,
+	S2MPA01_REG_L2CTRL,
+	S2MPA01_REG_L3CTRL,
+	S2MPA01_REG_L4CTRL,
+	S2MPA01_REG_L5CTRL,
+	S2MPA01_REG_L6CTRL,
+	S2MPA01_REG_L7CTRL,
+	S2MPA01_REG_L8CTRL,
+	S2MPA01_REG_L9CTRL,
+	S2MPA01_REG_L10CTRL,
+	S2MPA01_REG_L11CTRL,
+	S2MPA01_REG_L12CTRL,
+	S2MPA01_REG_L13CTRL,
+	S2MPA01_REG_L14CTRL,
+	S2MPA01_REG_L15CTRL,
+	S2MPA01_REG_L16CTRL,
+	S2MPA01_REG_L17CTRL,
+	S2MPA01_REG_L18CTRL,
+	S2MPA01_REG_L19CTRL,
+	S2MPA01_REG_L20CTRL,
+	S2MPA01_REG_L21CTRL,
+	S2MPA01_REG_L22CTRL,
+	S2MPA01_REG_L23CTRL,
+	S2MPA01_REG_L24CTRL,
+	S2MPA01_REG_L25CTRL,
+	S2MPA01_REG_L26CTRL,
+
+	S2MPA01_REG_LDO_OVCB1,
+	S2MPA01_REG_LDO_OVCB2,
+	S2MPA01_REG_LDO_OVCB3,
+	S2MPA01_REG_LDO_OVCB4,
+
+};
+
+/* S2MPA01 regulator ids */
+enum s2mpa01_regulators {
+	S2MPA01_LDO1,
+	S2MPA01_LDO2,
+	S2MPA01_LDO3,
+	S2MPA01_LDO4,
+	S2MPA01_LDO5,
+	S2MPA01_LDO6,
+	S2MPA01_LDO7,
+	S2MPA01_LDO8,
+	S2MPA01_LDO9,
+	S2MPA01_LDO10,
+	S2MPA01_LDO11,
+	S2MPA01_LDO12,
+	S2MPA01_LDO13,
+	S2MPA01_LDO14,
+	S2MPA01_LDO15,
+	S2MPA01_LDO16,
+	S2MPA01_LDO17,
+	S2MPA01_LDO18,
+	S2MPA01_LDO19,
+	S2MPA01_LDO20,
+	S2MPA01_LDO21,
+	S2MPA01_LDO22,
+	S2MPA01_LDO23,
+	S2MPA01_LDO24,
+	S2MPA01_LDO25,
+	S2MPA01_LDO26,
+
+	S2MPA01_BUCK1,
+	S2MPA01_BUCK2,
+	S2MPA01_BUCK3,
+	S2MPA01_BUCK4,
+	S2MPA01_BUCK5,
+	S2MPA01_BUCK6,
+	S2MPA01_BUCK7,
+	S2MPA01_BUCK8,
+	S2MPA01_BUCK9,
+	S2MPA01_BUCK10,
+
+	S2MPA01_REGULATOR_MAX,
+};
+
+#define S2MPA01_BUCK_MIN1	600000
+#define S2MPA01_BUCK_MIN2	800000
+#define S2MPA01_BUCK_MIN3	1000000
+#define S2MPA01_BUCK_MIN4	1500000
+#define S2MPA01_LDO_MIN		800000
+
+#define S2MPA01_BUCK_STEP1	6250
+#define S2MPA01_BUCK_STEP2	12500
+
+#define S2MPA01_LDO_STEP1	50000
+#define S2MPA01_LDO_STEP2	25000
+
+#define S2MPA01_LDO_VSEL_MASK	0x3F
+#define S2MPA01_BUCK_VSEL_MASK	0xFF
+#define S2MPA01_ENABLE_MASK	(0x03 << S2MPA01_ENABLE_SHIFT)
+#define S2MPA01_ENABLE_SHIFT	0x06
+#define S2MPA01_LDO_N_VOLTAGES	(S2MPA01_LDO_VSEL_MASK + 1)
+#define S2MPA01_BUCK_N_VOLTAGES (S2MPA01_BUCK_VSEL_MASK + 1)
+
+#define S2MPA01_RAMP_DELAY	12500	/* uV/us */
+
+#define S2MPA01_BUCK16_RAMP_SHIFT	4
+#define S2MPA01_BUCK24_RAMP_SHIFT	6
+#define S2MPA01_BUCK3_RAMP_SHIFT	4
+#define S2MPA01_BUCK5_RAMP_SHIFT	6
+#define S2MPA01_BUCK7_RAMP_SHIFT	2
+#define S2MPA01_BUCK8910_RAMP_SHIFT	0
+
+#define S2MPA01_BUCK1_RAMP_EN_SHIFT	3
+#define S2MPA01_BUCK2_RAMP_EN_SHIFT	2
+#define S2MPA01_BUCK3_RAMP_EN_SHIFT	1
+#define S2MPA01_BUCK4_RAMP_EN_SHIFT	0
+#define S2MPA01_PMIC_EN_SHIFT	6
+
+#endif /*__LINUX_MFD_S2MPA01_H */
-- 
1.7.9.5

--
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

* Re: [PATCH] export of_irq_count
From: Michal Simek @ 2014-02-13  6:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: delicious quinoa, Rob Herring, Grant Likely,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Dinh Nguyen,
	Yves Vandervennet, Alan Tull
In-Reply-To: <CAL_JsqLFAj_nCpuCg8qVchrfeSJ4HgOpt6ht9URkBuKZ6ztWow-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1573 bytes --]

On 02/12/2014 08:56 PM, Rob Herring wrote:
> On Wed, Feb 12, 2014 at 12:43 PM, delicious quinoa
> <delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Wed, Feb 12, 2014 at 12:32 PM, Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>> On Wed, Feb 12, 2014 at 11:34 AM, delicious quinoa
>>> <delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>> From: Alan Tull <atull-EIB2kfCEclfQT0dZR+AlfA@public.gmane.org>
>>>>
>>>> export of_irq_count so it can be used in drivers that are built
>>>> as modules.
>>>
>>> What drivers? Drivers generally should be using resources rather than
>>> this function directly.
>>
>> It's for the DesignWare GPIO driver I've been upstreaming.  The
>> DesignWare IP can be configured to be one irq for all the gpios or one
>> irq per gpio.  I want to support both cases.  So I need to know how
>> many irqs are specified in the device tree.
> 
> Okay. You should merge this as part of that then, so:
> 
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

I think we should be consistent and there are other methods how
to solve this. I have sent the same patch long time ago.
https://lkml.org/lkml/2013/5/30/265

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

^ permalink raw reply

* Re: [PATCH v2 3/3] Documentation: mfd: Add binding document for S2MPA01
From: Sachin Kamat @ 2014-02-13  6:17 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	sbkim73-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
	lgirdwood-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
In-Reply-To: <20140212181043.GB23630-NuALmloUBlrZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>

Hi Mark,

On 12 February 2014 23:40, Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org> wrote:
> Hi Sachin,
>
> Apologies for the delay on this.

No problem :). Thank you for your review. Please see my comments inline.

>
> On Thu, Jan 09, 2014 at 11:22:34AM +0000, Sachin Kamat wrote:
>> Added initial binding documentation for S2MPA01 MFD.
>>
>> Signed-off-by: Sachin Kamat <sachin.kamat-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>> * Re-organised as suggested by Mark Rutland.
>> ---
>>  Documentation/devicetree/bindings/mfd/s2mpa01.txt |   86 +++++++++++++++++++++
>>  1 file changed, 86 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mfd/s2mpa01.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/s2mpa01.txt b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
>> new file mode 100644
>> index 000000000000..70879b92b24b
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
>> @@ -0,0 +1,86 @@
>> +
>> +* Samsung S2MPA01 Voltage and Current Regulator
>> +
>> +The Samsung S2MPA01 is a multi-function device which includes high
>> +efficiency buck converters including Dual-Phase buck converter, various LDOs,
>> +and an RTC. It is interfaced to the host controller using an I2C interface.
>> +Each sub-block is addressed by the host system using different I2C slave
>> +addresses.
>> +
>> +Required properties:
>> +- compatible: Should be "samsung,s2mpa01-pmic".
>> +- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
>
> Is the slave address not per-instance in I2C? If not why must is be 0x66?

Mark Brown already replied to this. Thanks Mark.

>
>> +
>> +Optional properties:
>> +- interrupt-parent: Specifies the phandle of the interrupt controller to which
>> +  the interrupts from s2mpa01 are delivered to.
>> +- interrupts: Interrupt specifier for interrupt source (connected to SoC).
>
> The part in brackets can go. Assuming this is a single interrupt:

OK.

>
> - interrupts: An interrupt-specifier for the sole interrupt generated by
>   the device.
>
> If the interrupt has a name it would be nice to mention that. If there
> are more than one you should describe them.
>
>> +
>> +Optional nodes:
>> +- regulators: The regulators of s2mpa01 that have to be instantiated should be
>> +  included in a sub-node named 'regulators'. Regulator nodes and constraints
>> +  included in this sub-node use the standard regulator bindings which are
>> +  documented elsewhere.
>> +
>> +Properties for BUCK regulator nodes:
>> + regulator-ramp-delay for BUCKs = [6250/12500(default)/25000/50000] uV/us
>
> This could be made easier to read:
>
> - regulator-ramp-delay: ramp delay in uV/us. May be 6250, 12500
>   (default), 250000, or 50000. May be 0 for disabling the ramp delay on
>   BUCK{1,2,3,4}.

Yes. Will update.

>
>> +
>> + BUCK[1/2/3/4] supports disabling ramp delay on hardware, so explictly
>> + regulator-ramp-delay = <0> can be used for them to disable ramp delay.
>> + In the absence of the regulator-ramp-delay property, the default ramp
>> + delay will be used.
>
> Can be folded into the above, as in my example.

Right.

>
>> +
>> +  NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
>> +  for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
>
> Missing '=' before <value>?

Yes. Thanks for pointing out.

>
>> +  Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
>> +  BUCK[2, 4], and BUCK[8, 9, 10]
>
> The following BUCKs share ramp settings:
> * 1 and 6
> * 2 and 4
> * 8, 9, and 10

OK.
-- 
With warm regards,
Sachin
--
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 0/2] Add Ether DT support for R8A7791/Koelsch reference board
From: Simon Horman @ 2014-02-13  6:03 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: linux-sh, devicetree, magnus.damm, linux, linux-arm-kernel,
	robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak
In-Reply-To: <201402070110.18561.sergei.shtylyov@cogentembedded.com>

On Fri, Feb 07, 2014 at 01:10:17AM +0300, Sergei Shtylyov wrote:
> Hello.
> 
>    Here's the set of 2 patches against Simon Horman's 'renesas.git' repo,
> 'renesas-devel-v3.14-rc1-20140206v2' tag. Here we add the Ether device tree
> support working on the R8A7791/Koelsch reference board. The patchset requires
> the 'sh_eth' driver device tree support posted earlier in order to work.
> 
> [1/2] ARM: shmobile: r8a7791: add Ether DT support
> [2/2] ARM: shmobile: koelsch: add Ether DT support

Thanks. Please repost this series once the bindings have been accepted.

^ permalink raw reply

* Re: [PATCH 0/2] Add Ether DT support for R8A7790/Lager reference board
From: Simon Horman @ 2014-02-13  6:02 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: linux-sh, devicetree, magnus.damm, linux, linux-arm-kernel,
	robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak
In-Reply-To: <201402070054.39989.sergei.shtylyov@cogentembedded.com>

On Fri, Feb 07, 2014 at 12:54:38AM +0300, Sergei Shtylyov wrote:
> Hello.
> 
>    Here's the set of 2 patches against Simon Horman's 'renesas.git' repo,
> 'renesas-devel-v3.14-rc1-20140206v2' tag. Here we add the Ether device tree
> support working on the R8A7790/Lager reference board. The patchset requires the
> 'sh_eth' driver device tree support posted earlier in order to work.
> 
> [1/2] ARM: shmobile: r8a7790: add Ether DT support
> [2/2] ARM: shmobile: lager: add Ether DT support

Thanks. Please repost this series once the bindings have been accepted.

^ permalink raw reply

* Re: [PATCH 1/2] ARM: shmobile: r8a7778/r8a7779 dtsi: Improve and correct HSPI bindings
From: Simon Horman @ 2014-02-13  5:56 UTC (permalink / raw)
  To: Geert Uytterhoeven, Kuninori Morimoto
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-spi-u79uwXL29TY76Z2rM5mHXA, linux-sh-u79uwXL29TY76Z2rM5mHXA,
	Geert Uytterhoeven, Mark Brown
In-Reply-To: <1392109008-29941-1-git-send-email-geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>

Hi Morimoto-san,

could you test this series as Geert does not have access to a bockw board?

On Tue, Feb 11, 2014 at 09:56:47AM +0100, Geert Uytterhoeven wrote:
> From: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
> 
> Binding documentation:
>   - Add future-proof "renesas,hspi-<soctype>" compatible values,
>   - Add "interrupt-parent", "#address-cells" and "#size-cells" properties,
>   - Add reference to pinctrl documentation,
>   - Add example bindings.
> 
> r8a7778 and r8a7779 dtsi:
>   - Add "renesas,hspi-r8a7778" resp. "renesas,hspi-r8a7779" compatible
>     values,
>   - Correct reference to parent interrupt controller
>     (use "interrupt-parent" instead of "interrupt-controller"),
>   - Add missing "#address-cells" and "#size-cells" properties, which are
>     needed when populating the SPI buses.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
> Cc: Mark Brown <broonie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> Untested due to lack of hardware
> 
>  Documentation/devicetree/bindings/spi/sh-hspi.txt |   27 ++++++++++++++++++---
>  arch/arm/boot/dts/r8a7778.dtsi                    |   18 +++++++++-----
>  arch/arm/boot/dts/r8a7779.dtsi                    |   18 +++++++++-----
>  3 files changed, 48 insertions(+), 15 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/spi/sh-hspi.txt b/Documentation/devicetree/bindings/spi/sh-hspi.txt
> index 30b57b1c8a13..d43080eb6b3a 100644
> --- a/Documentation/devicetree/bindings/spi/sh-hspi.txt
> +++ b/Documentation/devicetree/bindings/spi/sh-hspi.txt
> @@ -1,7 +1,28 @@
>  Renesas HSPI.
>  
>  Required properties:
> -- compatible : 	"renesas,hspi"
> -- reg : Offset and length of the register set for the device
> -- interrupts : interrupt line used by HSPI
> +- compatible       : "renesas,hspi-<soctype>", "renesas,hspi" as fallback.
> +		     Examples of valid soctypes are "r8a7778" (R-Car M1),
> +		     and "r8a7779" (R-Car H1)
> +- reg              : Offset and length of the register set for the device
> +- interrupt-parent : The phandle for the interrupt controller that
> +		     services interrupts for this device
> +- interrupts       : Interrupt specifier
> +- #address-cells   : Must be <1>
> +- #size-cells      : Must be <0>
> +
> +Pinctrl properties might be needed, too.  See
> +Documentation/devicetree/bindings/pinctrl/renesas,*.
> +
> +Example:
> +
> +	hspi0: spi@fffc7000 {
> +		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
> +		reg = <0xfffc7000 0x18>;
> +		interrupt-parent = <&gic>;
> +		interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
>  
> diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
> index 85c5b3b99f5e..3c6fab5c9702 100644
> --- a/arch/arm/boot/dts/r8a7778.dtsi
> +++ b/arch/arm/boot/dts/r8a7778.dtsi
> @@ -204,26 +204,32 @@
>  	};
>  
>  	hspi0: spi@fffc7000 {
> -		compatible = "renesas,hspi";
> +		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
>  		reg = <0xfffc7000 0x18>;
> -		interrupt-controller = <&gic>;
> +		interrupt-parent = <&gic>;
>  		interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>  		status = "disabled";
>  	};
>  
>  	hspi1: spi@fffc8000 {
> -		compatible = "renesas,hspi";
> +		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
>  		reg = <0xfffc8000 0x18>;
> -		interrupt-controller = <&gic>;
> +		interrupt-parent = <&gic>;
>  		interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>  		status = "disabled";
>  	};
>  
>  	hspi2: spi@fffc6000 {
> -		compatible = "renesas,hspi";
> +		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
>  		reg = <0xfffc6000 0x18>;
> -		interrupt-controller = <&gic>;
> +		interrupt-parent = <&gic>;
>  		interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>  		status = "disabled";
>  	};
>  };
> diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
> index d0561d4c7c46..8b1a336ee401 100644
> --- a/arch/arm/boot/dts/r8a7779.dtsi
> +++ b/arch/arm/boot/dts/r8a7779.dtsi
> @@ -256,26 +256,32 @@
>  	};
>  
>  	hspi0: spi@fffc7000 {
> -		compatible = "renesas,hspi";
> +		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
>  		reg = <0xfffc7000 0x18>;
> -		interrupt-controller = <&gic>;
> +		interrupt-parent = <&gic>;
>  		interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>  		status = "disabled";
>  	};
>  
>  	hspi1: spi@fffc8000 {
> -		compatible = "renesas,hspi";
> +		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
>  		reg = <0xfffc8000 0x18>;
> -		interrupt-controller = <&gic>;
> +		interrupt-parent = <&gic>;
>  		interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>  		status = "disabled";
>  	};
>  
>  	hspi2: spi@fffc6000 {
> -		compatible = "renesas,hspi";
> +		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
>  		reg = <0xfffc6000 0x18>;
> -		interrupt-controller = <&gic>;
> +		interrupt-parent = <&gic>;
>  		interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>  		status = "disabled";
>  	};
>  };
> -- 
> 1.7.9.5
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" 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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox