* [PATCH RESEND 1/5 v6] gpio: Add a block GPIO API to gpiolib
From: Grant Likely @ 2012-10-31 18:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50915DBC.2000802@antcom.de>
Hi Roland
On Wed, Oct 31, 2012 at 6:19 PM, Roland Stigge <stigge@antcom.de> wrote:
> On 10/31/2012 04:00 PM, Grant Likely wrote:
>> For the API, I don't think it is a good idea at all to try and
>> abstract away gpios on multiple controllers. I understand that it
>> makes life a lot easier for userspace to abstract those details away,
>> but the problem is that it hides very important information about how
>> the system is actually constructed that is important to actually get
>> things to work. For example, say you have a gpio-connected device with
>> the constraint that GPIOA must change either before or at the same
>> time as GPIOB, but never after. If those GPIOs are on separate
>> controllers, then the order is completely undefined
>
> It is correct that it's not (yet) well documented and the API is also
> not very explicit about it, but the actual approach of the manipulation
> order is to let drivers handle gpios "as simultaneous as possible" and
> when not possible, do it in the _order of bits specified_ (either
> defined at the device tree level, or when created via
> block_gpio_create() directly).
The documentation is actually fine. I do understand that the intent is
"as simultaneous as possible", but I accept the point that the order
of specification affects the behaviour*. However, it still remains
that the method used by the ABI abstracts at the wrong level and that
blocking arbitrary GPIO pins into a single virtual GPIO register is a
bad idea.
*note that the current code doesn't implement that intended behaviour
either since the gpios are processed in the order of the controllers,
not the order of the bits.
> I'm not sure how far you tested the API in depth: You can already define
> a block that maps onto a subset of gpios on a controller and internally
> of course maps onto those set and clear operations. Whenever you need to
> manipulate a different subset (whether disjoint or overlapping), you can
> easily define _additional_ blocks. From my experience, this solves most
> of the real world problems when n-bit busses are bit banged over GPIOs.
> Doesn't this already solve this (in a different way, though)?
Blech! Requiring a new block for each possible combination of
write-at-once bits is a horrible ABI. That just strengthens my opinion
that the abstraction isn't right yet.
> Pin direction currently needs to be set up separately, analogous to
> requesting gpios. Need to document this better, right. The assumption is
> that I/O needs to be efficient primarily, before bloating the API with
> direction functions. Or should I add functions for this?
Since this is a userspace facing ABI, once it is merged it cannot be
changed in an incompatible way. I cannot merge it until there is at
least a plan for how to handle all of the reasonable use cases. That
means it must support set/clear or mask operations. Also, if it sticks
with the design of grouping pins from multiple controllers, then it
needs to handle explicitly constraining what order operations are
performed in at the time of the operation. At the time of setup
doesn't work since constraints between pins may not always be in the
same order.
I really think you should consider implementing a command stream type
of interface.
g.
^ permalink raw reply
* [PATCH v2 2/5] clk: Add support for fundamental zynq clks
From: Josh Cartwright @ 2012-10-31 18:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352400580.git.josh.cartwright@ni.com>
Provide simplified models for the necessary clocks on the zynq-7000
platform. Currently, the PLLs, the CPU clock network, and the basic
peripheral clock networks (for SDIO, SMC, SPI, QSPI, UART) are modelled.
OF bindings are also provided and documented.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
.../devicetree/bindings/clock/zynq-7000.txt | 55 +++
drivers/clk/clk-zynq.c | 383 +++++++++++++++++++++
include/linux/clk/zynq.h | 24 ++
3 files changed, 462 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/zynq-7000.txt
create mode 100644 drivers/clk/clk-zynq.c
create mode 100644 include/linux/clk/zynq.h
diff --git a/Documentation/devicetree/bindings/clock/zynq-7000.txt b/Documentation/devicetree/bindings/clock/zynq-7000.txt
new file mode 100644
index 0000000..23ae1db
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/zynq-7000.txt
@@ -0,0 +1,55 @@
+Device Tree Clock bindings for the Zynq 7000 EPP
+
+The Zynq EPP has several different clk providers, each with there own bindings.
+The purpose of this document is to document their usage.
+
+See clock_bindings.txt for more information on the generic clock bindings.
+See Chapter 25 of Zynq TRM for more information about Zynq clocks.
+
+== PLLs ==
+
+Used to describe the ARM_PLL, DDR_PLL, and IO_PLL.
+
+Required properties:
+- #clock-cells : shall be 0 (only one clock is output from this node)
+- compatible : "xlnx,zynq-pll"
+- reg : pair of u32 values, which are the address offsets within the SLCR
+ of the relevant PLL_CTRL register and PLL_CFG register respectively
+- clocks : phandle for parent clock. should be the phandle for ps_clk
+
+Optional properties:
+- clock-output-names : name of the output clock
+
+Example:
+ armpll: armpll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x100 0x110>;
+ clock-output-names = "armpll";
+ };
+
+== Peripheral clocks ==
+
+Describes clock node for the SDIO, SMC, SPI, QSPI, and UART clocks.
+
+Required properties:
+- #clock-cells : shall be 1
+- compatible : "xlnx,zynq-periph-clock"
+- reg : a single u32 value, describing the offset within the SLCR where
+ the CLK_CTRL register is found for this peripheral
+- clocks : phandle for parent clocks. should hold phandles for
+ the IO_PLL, ARM_PLL, and DDR_PLL in order
+- clock-output-names : names of the output clock(s). For peripherals that have
+ two output clocks (for example, the UART), two clocks
+ should be listed.
+
+Example:
+ uart_clk: uart_clk {
+ #clock-cells = <1>;
+ compatible = "xlnx,zynq-periph-clock";
+ clocks = <&iopll &armpll &ddrpll>;
+ reg = <0x154>;
+ clock-output-names = "uart0_ref_clk",
+ "uart1_ref_clk";
+ };
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c
new file mode 100644
index 0000000..de8b586
--- /dev/null
+++ b/drivers/clk/clk-zynq.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright <josh.cartwright@ni.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+
+static void __iomem *slcr_base;
+
+struct zynq_pll_clk {
+ struct clk_hw hw;
+ void __iomem *pll_ctrl;
+ void __iomem *pll_cfg;
+};
+
+#define to_zynq_pll_clk(hw) container_of(hw, struct zynq_pll_clk, hw)
+
+#define CTRL_PLL_FDIV(x) ((x) >> 12)
+
+static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
+ return parent_rate * CTRL_PLL_FDIV(ioread32(pll->pll_ctrl));
+}
+
+static const struct clk_ops zynq_pll_clk_ops = {
+ .recalc_rate = zynq_pll_recalc_rate,
+};
+
+static void __init zynq_pll_clk_setup(struct device_node *np)
+{
+ struct clk_init_data init;
+ struct zynq_pll_clk *pll;
+ const char *parent_name;
+ struct clk *clk;
+ u32 regs[2];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "reg", regs, ARRAY_SIZE(regs));
+ if (WARN_ON(ret))
+ return;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (WARN_ON(!pll))
+ return;
+
+ pll->pll_ctrl = slcr_base + regs[0];
+ pll->pll_cfg = slcr_base + regs[1];
+
+ of_property_read_string(np, "clock-output-names", &init.name);
+
+ init.ops = &zynq_pll_clk_ops;
+ parent_name = of_clk_get_parent_name(np, 0);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(ret))
+ return;
+}
+
+struct zynq_periph_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *gates[2];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_periph_clk(hw) container_of(hw, struct zynq_periph_clk, hw)
+
+static const u8 periph_clk_parent_map[] = {
+ 0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 3) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return parent_rate / PERIPH_CLK_CTRL_DIV(ioread32(periph->clk_ctrl));
+}
+
+static u8 zynq_periph_get_parent(struct clk_hw *hw)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return PERIPH_CLK_CTRL_SRC(ioread32(periph->clk_ctrl));
+}
+
+static const struct clk_ops zynq_periph_clk_ops = {
+ .recalc_rate = zynq_periph_recalc_rate,
+ .get_parent = zynq_periph_get_parent,
+};
+
+static void __init zynq_periph_clk_setup(struct device_node *np)
+{
+ struct zynq_periph_clk *periph;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ int clk_num = 0, err;
+ const char *name;
+ struct clk *clk;
+ u32 reg;
+ int i;
+
+ err = of_property_read_u32(np, "reg", ®);
+ if (WARN_ON(err))
+ return;
+
+ periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+ if (WARN_ON(!periph))
+ return;
+
+ periph->clk_ctrl = slcr_base + reg;
+ spin_lock_init(&periph->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_periph_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ periph->hw.init = &init;
+
+ clk = clk_register(NULL, &periph->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(err))
+ return;
+
+ err = of_property_read_string_index(np, "clock-output-names", 0,
+ &name);
+ if (WARN_ON(err))
+ return;
+
+ periph->gates[0] = clk_register_gate(NULL, name, np->name, 0,
+ periph->clk_ctrl, 0, 0,
+ &periph->clkact_lock);
+ if (WARN_ON(IS_ERR(periph->gates[0])))
+ return;
+ clk_num++;
+
+ /* some periph clks have 2 downstream gates */
+ err = of_property_read_string_index(np, "clock-output-names", 1,
+ &name);
+ if (err != -ENODATA) {
+ periph->gates[1] = clk_register_gate(NULL, name, np->name, 0,
+ periph->clk_ctrl, 1, 0,
+ &periph->clkact_lock);
+ if (WARN_ON(IS_ERR(periph->gates[1])))
+ return;
+ clk_num++;
+ }
+
+ periph->onecell_data.clks = periph->gates;
+ periph->onecell_data.clk_num = clk_num;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &periph->onecell_data);
+ if (WARN_ON(err))
+ return;
+}
+
+/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
+ * derivative rates depend on CLK_621_TRUE
+ */
+
+struct zynq_cpu_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *subclks[4];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_cpu_clk(hw) container_of(hw, struct zynq_cpu_clk, hw)
+
+static const u8 zynq_cpu_clk_parent_map[] = {
+ 1, 1, 2, 0
+};
+#define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
+#define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static u8 zynq_cpu_clk_get_parent(struct clk_hw *hw)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return CPU_CLK_SRCSEL(ioread32(cpuclk->clk_ctrl));
+}
+
+static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return parent_rate / CPU_CLK_CTRL_DIV(ioread32(cpuclk->clk_ctrl));
+}
+
+static const struct clk_ops zynq_cpu_clk_ops = {
+ .get_parent = zynq_cpu_clk_get_parent,
+ .recalc_rate = zynq_cpu_clk_recalc_rate,
+};
+
+struct zynq_cpu_subclk {
+ struct clk_hw hw;
+ void __iomem *clk_621;
+ enum {
+ CPU_SUBCLK_6X4X,
+ CPU_SUBCLK_3X2X,
+ CPU_SUBCLK_2X,
+ CPU_SUBCLK_1X,
+ } which;
+};
+
+#define CLK_621_TRUE(x) ((x) & 1)
+
+#define to_zynq_cpu_subclk(hw) container_of(hw, struct zynq_cpu_subclk, hw);
+
+static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long uninitialized_var(rate);
+ struct zynq_cpu_subclk *subclk;
+ bool is_621;
+
+ subclk = to_zynq_cpu_subclk(hw)
+ is_621 = CLK_621_TRUE(ioread32(subclk->clk_621));
+
+ switch (subclk->which) {
+ case CPU_SUBCLK_6X4X:
+ rate = parent_rate;
+ break;
+ case CPU_SUBCLK_3X2X:
+ rate = parent_rate / 2;
+ break;
+ case CPU_SUBCLK_2X:
+ rate = parent_rate / (is_621 ? 3 : 2);
+ break;
+ case CPU_SUBCLK_1X:
+ rate = parent_rate / (is_621 ? 6 : 4);
+ break;
+ };
+
+ return rate;
+}
+
+static const struct clk_ops zynq_cpu_subclk_ops = {
+ .recalc_rate = zynq_cpu_subclk_recalc_rate,
+};
+
+static struct clk *zynq_cpu_subclk_setup(struct device_node *np, u8 which,
+ void __iomem *clk_621)
+{
+ struct zynq_cpu_subclk *subclk;
+ struct clk_init_data init;
+ struct clk *clk;
+ int err;
+
+ err = of_property_read_string_index(np, "clock-output-names",
+ which, &init.name);
+ if (WARN_ON(err))
+ goto err_read_output_name;
+
+ subclk = kzalloc(sizeof(*subclk), GFP_KERNEL);
+ if (!subclk)
+ goto err_subclk_alloc;
+
+ subclk->clk_621 = clk_621;
+ subclk->which = which;
+
+ init.ops = &zynq_cpu_subclk_ops;
+ init.parent_names = &np->name;
+ init.num_parents = 1;
+
+ subclk->hw.init = &init;
+
+ clk = clk_register(NULL, &subclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ goto err_clk_register;
+
+ return clk;
+
+err_clk_register:
+ kfree(subclk);
+err_subclk_alloc:
+err_read_output_name:
+ return ERR_PTR(-EINVAL);
+}
+
+static void __init zynq_cpu_clk_setup(struct device_node *np)
+{
+ struct zynq_cpu_clk *cpuclk;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ void __iomem *clk_621;
+ struct clk *clk;
+ u32 reg[2];
+ int err;
+ int i;
+
+ err = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
+ if (WARN_ON(err))
+ return;
+
+ cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+ if (WARN_ON(!cpuclk))
+ return;
+
+ cpuclk->clk_ctrl = slcr_base + reg[0];
+ clk_621 = slcr_base + reg[1];
+ spin_lock_init(&cpuclk->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_cpu_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ cpuclk->hw.init = &init;
+
+ clk = clk_register(NULL, &cpuclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(err))
+ return;
+
+ for (i = 0; i < 4; i++) {
+ cpuclk->subclks[i] = zynq_cpu_subclk_setup(np, i, clk_621);
+ if (WARN_ON(IS_ERR(cpuclk->subclks[i])))
+ return;
+ }
+
+ cpuclk->onecell_data.clks = cpuclk->subclks;
+ cpuclk->onecell_data.clk_num = i;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &cpuclk->onecell_data);
+ if (WARN_ON(err))
+ return;
+}
+
+static const __initconst struct of_device_id zynq_clk_match[] = {
+ { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+ { .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, },
+ { .compatible = "xlnx,zynq-periph-clock",
+ .data = zynq_periph_clk_setup, },
+ { .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, },
+ {}
+};
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr)
+{
+ slcr_base = slcr;
+ of_clk_init(zynq_clk_match);
+}
diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
new file mode 100644
index 0000000..56be7cd
--- /dev/null
+++ b/include/linux/clk/zynq.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 National Instruments
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LINUX_CLK_ZYNQ_H_
+#define __LINUX_CLK_ZYNQ_H_
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr);
+
+#endif
--
1.8.0
^ permalink raw reply related
* [PATCH 5/8] ARM: zynq: add COMMON_CLK support
From: Josh Cartwright @ 2012-10-31 18:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351721190.git.josh.cartwright@ni.com>
Add support for COMMON_CLK, and provide simplified models for the
necessary clocks on the zynq-7000. Currently, the PLLs, the CPU clock
network, and the basic peripheral clock networks (for SDIO, SMC, SPI,
QSPI, UART) are modelled.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
.../devicetree/bindings/clock/zynq-7000.txt | 55 ++++
arch/arm/Kconfig | 1 +
arch/arm/boot/dts/zynq-7000.dtsi | 56 ++++
arch/arm/boot/dts/zynq-zc702.dts | 4 +
arch/arm/mach-zynq/common.c | 11 +
drivers/clk/Makefile | 1 +
drivers/clk/clk-zynq.c | 355 +++++++++++++++++++++
include/linux/clk/zynq.h | 24 ++
8 files changed, 507 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/zynq-7000.txt
create mode 100644 drivers/clk/clk-zynq.c
create mode 100644 include/linux/clk/zynq.h
diff --git a/Documentation/devicetree/bindings/clock/zynq-7000.txt b/Documentation/devicetree/bindings/clock/zynq-7000.txt
new file mode 100644
index 0000000..2e21fc1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/zynq-7000.txt
@@ -0,0 +1,55 @@
+Device Tree Clock bindings for the Zynq 7000 EPP
+
+The Zynq EPP has several different clk providers, each with there own bindings.
+The purpose of this document is to document their usage.
+
+See clock_bindings.txt for more information on the generic clock bindings.
+See Chapter 25 of Zynq TRM for more information about Zynq clocks.
+
+== PLLs ==
+
+Used to describe the ARM_PLL, DDR_PLL, and IO_PLL.
+
+Required properties:
+- #clock-cells : shall be 0 (only one clock is output from this node)
+- compatible : "xlnx,zynq-pll"
+- reg : pair of u32 values, which are the address offsets within the SLCR
+ of the relevant PLL_CTRL register and PLL_CFG register respectively
+- clocks : phandle for parent clock. should be the phandle for ps_clk
+
+Optional properties:
+- clock-output-names : name of the output clock
+
+Example:
+ armpll: armpll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x100 0x110>;
+ clock-output-names = "armpll";
+ };
+
+== Peripheral clocks ==
+
+Describes clock node for the SDIO, SMC, SPI, QSPI, and UART clocks.
+
+Required properties:
+- #clock-cells : shall be 1
+- compatible : "xlnx,zynq-periph-clock"
+- reg : a single u32 value, describing the offset within the SLCR where
+ the CLK_CTRL register is found for this peripheral
+- clocks : phandle for parent clocks. should hold phandles for
+ the IO_PLL, ARM_PLL, and DDR_PLL in order
+
+Optional properties:
+- clock-output-names : name of the output clock
+
+Example:
+ uart_clk: uart_clk {
+ #clock-cells = <1>;
+ compatible = "xlnx,zynq-periph-clock";
+ clocks = <&iopll &armpll &ddrpll>;
+ reg = <0x154>;
+ clock-output-names = "uart0_ref_clk",
+ "uart1_ref_clk";
+ };
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 21ed87b..ccfe0ab 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -959,6 +959,7 @@ config ARCH_ZYNQ
bool "Xilinx Zynq ARM Cortex A9 Platform"
select ARM_AMBA
select ARM_GIC
+ select COMMON_CLK
select CPU_V7
select GENERIC_CLOCKEVENTS
select ICST
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 8b30e59..bb3085c 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -53,5 +53,61 @@
interrupts = <0 50 4>;
clock = <50000000>;
};
+
+ slcr: slcr at f8000000 {
+ compatible = "xlnx,zynq-slcr";
+ reg = <0xF8000000 0x1000>;
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ps_clk: ps_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ /* clock-frequency set in board-specific file */
+ clock-output-names = "ps_clk";
+ };
+ armpll: armpll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x100 0x110>;
+ clock-output-names = "armpll";
+ };
+ ddrpll: ddrpll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x104 0x114>;
+ clock-output-names = "ddrpll";
+ };
+ iopll: iopll {
+ #clock-cells = <0>;
+ compatible = "xlnx,zynq-pll";
+ clocks = <&ps_clk>;
+ reg = <0x108 0x118>;
+ clock-output-names = "iopll";
+ };
+ uart_clk: uart_clk {
+ #clock-cells = <1>;
+ compatible = "xlnx,zynq-periph-clock";
+ clocks = <&iopll &armpll &ddrpll>;
+ reg = <0x154>;
+ clock-output-names = "uart0_ref_clk",
+ "uart1_ref_clk";
+ };
+ cpu_clk: cpu_clk {
+ #clock-cells = <1>;
+ compatible = "xlnx,zynq-cpu-clock";
+ clocks = <&iopll &armpll &ddrpll>;
+ reg = <0x120 0x1C4>;
+ clock-output-names = "cpu_6x4x",
+ "cpu_3x2x",
+ "cpu_2x",
+ "cpu_1x";
+ };
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
index e25a307..86f44d5 100644
--- a/arch/arm/boot/dts/zynq-zc702.dts
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -28,3 +28,7 @@
};
};
+
+&ps_clk {
+ clock-frequency = <33333330>;
+};
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 447904b..f0cb3e4 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -19,6 +19,8 @@
#include <linux/cpumask.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/clk/zynq.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/of.h>
@@ -96,6 +98,15 @@ static struct map_desc io_desc[] __initdata = {
static void __init xilinx_zynq_timer_init(void)
{
+ struct device_node *np;
+ void __iomem *slcr;
+
+ np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr");
+ slcr = of_iomap(np, 0);
+ WARN_ON(!slcr);
+
+ xilinx_zynq_clocks_init(slcr);
+
xttcpss_timer_init();
}
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b9..d35a34c 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -19,6 +19,7 @@ endif
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
+obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o
# Chip specific
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c
new file mode 100644
index 0000000..2afa84d
--- /dev/null
+++ b/drivers/clk/clk-zynq.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright <josh.cartwright@ni.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+
+static void __iomem *slcr_base;
+
+struct zynq_pll_clk {
+ struct clk_hw hw;
+ void __iomem *pll_ctrl;
+ void __iomem *pll_cfg;
+};
+
+#define to_zynq_pll_clk(hw) container_of(hw, struct zynq_pll_clk, hw)
+
+#define CTRL_PLL_FDIV(x) ((x)>>12)
+
+static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
+ return parent_rate * CTRL_PLL_FDIV(ioread32(pll->pll_ctrl));
+}
+
+static const struct clk_ops zynq_pll_clk_ops = {
+ .recalc_rate = zynq_pll_recalc_rate,
+};
+
+static void __init zynq_pll_clk_setup(struct device_node *np)
+{
+ struct clk_init_data init;
+ struct zynq_pll_clk *pll;
+ const char *parent_name;
+ struct clk *clk;
+ u32 regs[2];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "reg", regs, ARRAY_SIZE(regs));
+ WARN_ON(ret);
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ WARN_ON(!pll);
+
+ pll->pll_ctrl = slcr_base + regs[0];
+ pll->pll_cfg = slcr_base + regs[1];
+
+ of_property_read_string(np, "clock-output-names", &init.name);
+
+ init.ops = &zynq_pll_clk_ops;
+ parent_name = of_clk_get_parent_name(np, 0);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ WARN_ON(IS_ERR(clk));
+
+ ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ WARN_ON(ret);
+}
+
+struct zynq_periph_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *gates[2];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_periph_clk(hw) container_of(hw, struct zynq_periph_clk, hw)
+
+static const u8 periph_clk_parent_map[] = {
+ 0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x)&3)>>4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x)&0x3F00)>>8)
+
+static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return parent_rate / PERIPH_CLK_CTRL_DIV(ioread32(periph->clk_ctrl));
+}
+
+static u8 zynq_periph_get_parent(struct clk_hw *hw)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return PERIPH_CLK_CTRL_SRC(ioread32(periph->clk_ctrl));
+}
+
+static const struct clk_ops zynq_periph_clk_ops = {
+ .recalc_rate = zynq_periph_recalc_rate,
+ .get_parent = zynq_periph_get_parent,
+};
+
+static void __init zynq_periph_clk_setup(struct device_node *np)
+{
+ struct zynq_periph_clk *periph;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ struct clk *clk;
+ int err;
+ u32 reg;
+ int i;
+
+ err = of_property_read_u32(np, "reg", ®);
+ WARN_ON(err);
+
+ periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+ WARN_ON(!periph);
+
+ periph->clk_ctrl = slcr_base + reg;
+ spin_lock_init(&periph->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_periph_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ periph->hw.init = &init;
+
+ clk = clk_register(NULL, &periph->hw);
+ WARN_ON(IS_ERR(clk));
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ WARN_ON(err);
+
+ for (i = 0; i < 2; i++) {
+ const char *name;
+
+ err = of_property_read_string_index(np, "clock-output-names", i,
+ &name);
+ WARN_ON(err);
+
+ periph->gates[i] = clk_register_gate(NULL, name, np->name, 0,
+ periph->clk_ctrl, i, 0,
+ &periph->clkact_lock);
+ WARN_ON(IS_ERR(periph->gates[i]));
+ }
+
+ periph->onecell_data.clks = periph->gates;
+ periph->onecell_data.clk_num = i;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &periph->onecell_data);
+ WARN_ON(err);
+}
+
+/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
+ * derivative rates depend on CLK_621_TRUE
+ */
+
+struct zynq_cpu_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *subclks[4];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_cpu_clk(hw) container_of(hw, struct zynq_cpu_clk, hw)
+
+static const u8 zynq_cpu_clk_parent_map[] = {
+ 1, 1, 2, 0
+};
+#define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x)&0x30)>>4)])
+#define CPU_CLK_CTRL_DIV(x) (((x)&0x3F00)>>8)
+
+static u8 zynq_cpu_clk_get_parent(struct clk_hw *hw)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return CPU_CLK_SRCSEL(ioread32(cpuclk->clk_ctrl));
+}
+
+static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return parent_rate / CPU_CLK_CTRL_DIV(ioread32(cpuclk->clk_ctrl));
+}
+
+static const struct clk_ops zynq_cpu_clk_ops = {
+ .get_parent = zynq_cpu_clk_get_parent,
+ .recalc_rate = zynq_cpu_clk_recalc_rate,
+};
+
+struct zynq_cpu_subclk {
+ struct clk_hw hw;
+ void __iomem *clk_621;
+ enum {
+ CPU_SUBCLK_6X4X,
+ CPU_SUBCLK_3X2X,
+ CPU_SUBCLK_2X,
+ CPU_SUBCLK_1X,
+ } which;
+};
+
+#define CLK_621_TRUE(x) ((x)&1)
+
+#define to_zynq_cpu_subclk(hw) container_of(hw, struct zynq_cpu_subclk, hw);
+
+static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long uninitialized_var(rate);
+ struct zynq_cpu_subclk *subclk;
+ bool is_621;
+
+ subclk = to_zynq_cpu_subclk(hw)
+ is_621 = CLK_621_TRUE(ioread32(subclk->clk_621));
+
+ switch (subclk->which) {
+ case CPU_SUBCLK_6X4X:
+ rate = parent_rate;
+ break;
+ case CPU_SUBCLK_3X2X:
+ rate = parent_rate / 2;
+ break;
+ case CPU_SUBCLK_2X:
+ rate = parent_rate / (is_621 ? 3 : 2);
+ break;
+ case CPU_SUBCLK_1X:
+ rate = parent_rate / (is_621 ? 6 : 4);
+ break;
+ };
+
+ return rate;
+}
+
+static const struct clk_ops zynq_cpu_subclk_ops = {
+ .recalc_rate = zynq_cpu_subclk_recalc_rate,
+};
+
+static struct clk *zynq_cpu_subclk_setup(struct device_node *np, u8 which,
+ void __iomem *clk_621)
+{
+ struct zynq_cpu_subclk *subclk;
+ struct clk_init_data init;
+ struct clk *clk;
+ int err;
+
+ err = of_property_read_string_index(np, "clock-output-names",
+ which, &init.name);
+ if (WARN_ON(err))
+ goto err_read_output_name;
+
+ subclk = kzalloc(sizeof(*subclk), GFP_KERNEL);
+ if (!subclk)
+ goto err_subclk_alloc;
+
+ subclk->clk_621 = clk_621;
+ subclk->which = which;
+
+ init.ops = &zynq_cpu_subclk_ops;
+ init.parent_names = &np->name;
+ init.num_parents = 1;
+
+ subclk->hw.init = &init;
+
+ clk = clk_register(NULL, &subclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ goto err_clk_register;
+
+ return clk;
+
+err_clk_register:
+err_subclk_alloc:
+err_read_output_name:
+ return NULL;
+}
+
+static void __init zynq_cpu_clk_setup(struct device_node *np)
+{
+ struct zynq_cpu_clk *cpuclk;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ void __iomem *clk_621;
+ struct clk *clk;
+ u32 reg[2];
+ int err;
+ int i;
+
+ err = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
+ WARN_ON(err);
+
+ cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+ WARN_ON(!cpuclk);
+
+ cpuclk->clk_ctrl = slcr_base + reg[0];
+ clk_621 = slcr_base + reg[1];
+ spin_lock_init(&cpuclk->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_cpu_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ cpuclk->hw.init = &init;
+
+ clk = clk_register(NULL, &cpuclk->hw);
+ WARN_ON(IS_ERR(clk));
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ WARN_ON(err);
+
+ for (i = 0; i < 4; i++) {
+ cpuclk->subclks[i] = zynq_cpu_subclk_setup(np, i, clk_621);
+ WARN_ON(IS_ERR(cpuclk->subclks[i]));
+ }
+
+ cpuclk->onecell_data.clks = cpuclk->subclks;
+ cpuclk->onecell_data.clk_num = i;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &cpuclk->onecell_data);
+ WARN_ON(err);
+}
+
+static const __initconst struct of_device_id zynq_clk_match[] = {
+ { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+ { .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, },
+ { .compatible = "xlnx,zynq-periph-clock",
+ .data = zynq_periph_clk_setup, },
+ { .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, },
+ {}
+};
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr)
+{
+ slcr_base = slcr;
+ of_clk_init(zynq_clk_match);
+}
diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
new file mode 100644
index 0000000..56be7cd
--- /dev/null
+++ b/include/linux/clk/zynq.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 National Instruments
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LINUX_CLK_ZYNQ_H_
+#define __LINUX_CLK_ZYNQ_H_
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr);
+
+#endif
--
1.8.0
^ permalink raw reply related
* [PATCH v4 1/2] ARM: clk-imx27: Add missing clock for mx2-camera
From: Mauro Carvalho Chehab @ 2012-10-31 18:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <Pine.LNX.4.64.1210311442310.12173@axis700.grange>
Em Wed, 31 Oct 2012 14:53:47 +0100 (CET)
Guennadi Liakhovetski <g.liakhovetski@gmx.de> escreveu:
> On Wed, 31 Oct 2012, Fabio Estevam wrote:
>
> > Hi Sascha,
> >
> > On Wed, Oct 31, 2012 at 11:16 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > > Quoting yourself:
> > >
> > >> Forgot to comment: as patch 2 relies on this change, the better, IMHO, is
> > >> to send both via the same tree. If you decide to do so, please get arm
> > >> maintainer's ack, instead, and we can merge both via my tree.
> > >
> > > That's why Fabio resent these patches with my Ack. You are free to take
> > > these.
> >
> > I have just realized that this patch (1/2) will not apply against
> > media tree because it does not have commit 27b76486a3 (media:
> > mx2_camera: remove cpu_is_xxx by using platform_device_id), which
> > changes from mx2_camera.0 to imx27-camera.0.
>
> This is exactly the reason why I wasn't able to merge it. The problem was,
> that this "media: mx2_camera: remove cpu_is_xxx by using
> platform_device_id" patch non-trivially touched both arch/arm/ and
> drivers/media/ directories. And being patch 27/34 I didn't feel like
> asking the author to redo it again:-) This confirms, that it's better to
> avoid such overlapping patches whenever possible.
>
> > So it seems to be better to merge this via arm tree to avoid such conflict.
I agree with Fabio and Guennadi. There are so many changes happening at arm
that merging those two patches there will likely be easier for everybody.
Otherwise, I'll need to pull from some arm tree that never rebase, with
the needed patches, and coordinate with you during the merge window,
to be sure that patches will arrive there at the right order, from the
right tree.
Cheers,
Mauro
^ permalink raw reply
* [PATCH] arm: zynq: add system level control register manager
From: Daniel Borkmann @ 2012-10-31 18:36 UTC (permalink / raw)
To: linux-arm-kernel
This patch for the Xilinx Zynq ARM architecture adds management of system
level control register. The code is taken from the Xilinx-internal Linux
Git tree and cleaned up a bit for mainline integration. Besides others,
this patch is needed in order to integrate further drivers for Zynq such as
the Zynq xemacps networking device driver. The patch is aganst the latest
arm-soc tree.
Signed-off-by: Daniel Borkmann <daniel.borkmann@tik.ee.ethz.ch>
Cc: Michal Simek <michals@xilinx.com>
Cc: John Linn <john.linn@xilinx.com>
Cc: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mach-zynq/Makefile | 2 +-
arch/arm/mach-zynq/include/mach/slcr.h | 27 +
arch/arm/mach-zynq/slcr.c | 2166 ++++++++++++++++++++++++++++++++
3 files changed, 2194 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
index 397268c..69cac2a 100644
--- a/arch/arm/mach-zynq/Makefile
+++ b/arch/arm/mach-zynq/Makefile
@@ -3,4 +3,4 @@
#
# Common support
-obj-y := common.o timer.o
+obj-y := common.o timer.o slcr.o
diff --git a/arch/arm/mach-zynq/include/mach/slcr.h b/arch/arm/mach-zynq/include/mach/slcr.h
new file mode 100644
index 0000000..970f7f1
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/slcr.h
@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-zynq/include/mach/slcr.h
+ *
+ * Copyright (C) 2012 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_SLCR_H__
+#define __MACH_SLCR_H__
+
+extern void xslcr_write(u32 offset, u32 val);
+extern u32 xslcr_read(u32 offset);
+
+extern void xslcr_system_reset(void);
+
+extern void xslcr_init_preload_fpga(void);
+extern void xslcr_init_postload_fpga(void);
+
+#endif /* __MACH_SLCR_H__ */
diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c
new file mode 100644
index 0000000..4053417
--- /dev/null
+++ b/arch/arm/mach-zynq/slcr.c
@@ -0,0 +1,2166 @@
+/*
+ * Xilinx SLCR driver
+ *
+ * Copyright (c) 2011 Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ */
+
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <mach/slcr.h>
+
+#define DRIVER_NAME "xslcr"
+
+#define XSLCR_LOCK 0x4 /* SLCR lock register */
+#define XSLCR_UNLOCK 0x8 /* SCLR unlock register */
+#define XSLCR_APER_CLK_CTRL_OFFSET 0x12C /* AMBA Peripheral Clk Control */
+#define XSLCR_USB0_CLK_CTRL_OFFSET 0x130 /* USB 0 ULPI Clock Control */
+#define XSLCR_USB1_CLK_CTRL_OFFSET 0x134 /* USB 1 ULPI Clock Control */
+#define XSLCR_EMAC0_RCLK_CTRL_OFFSET 0x138 /* EMAC0 RX Clock Control */
+#define XSLCR_EMAC1_RCLK_CTRL_OFFSET 0x13C /* EMAC1 RX Clock Control */
+#define XSLCR_EMAC0_CLK_CTRL_OFFSET 0x140 /* EMAC0 Reference Clk Control */
+#define XSLCR_EMAC1_CLK_CTRL_OFFSET 0x144 /* EMAC1 Reference Clk Control */
+#define XSLCR_SMC_CLK_CTRL_OFFSET 0x148 /* SMC Reference Clock Control */
+#define XSLCR_QSPI_CLK_CTRL_OFFSET 0x14C /* QSPI Reference Clock Control */
+#define XSLCR_SDIO_CLK_CTRL_OFFSET 0x150 /* SDIO Reference Clock Control */
+#define XSLCR_UART_CLK_CTRL_OFFSET 0x154 /* UART Reference Clock Control */
+#define XSLCR_SPI_CLK_CTRL_OFFSET 0x158 /* SPI Reference Clock Control */
+#define XSLCR_CAN_CLK_CTRL_OFFSET 0x15C /* CAN Reference Clock Control */
+#define XSLCR_PSS_RST_CTRL_OFFSET 0x200 /* PSS Software Reset Control */
+#define XSLCR_DDR_RST_CTRL_OFFSET 0x204 /* DDR Software Reset Control */
+#define XSLCR_AMBA_RST_CTRL_OFFSET 0x208 /* AMBA Software Reset Control */
+#define XSLCR_DMAC_RST_CTRL_OFFSET 0x20C /* DMAC Software Reset Control */
+#define XSLCR_USB_RST_CTRL_OFFSET 0x210 /* USB Software Reset Control */
+#define XSLCR_EMAC_RST_CTRL_OFFSET 0x214 /* EMAC Software Reset Control */
+#define XSLCR_SDIO_RST_CTRL_OFFSET 0x218 /* SDIO Software Reset Control */
+#define XSLCR_SPI_RST_CTRL_OFFSET 0x21C /* SPI Software Reset Control */
+#define XSLCR_CAN_RST_CTRL_OFFSET 0x220 /* CAN Software Reset Control */
+#define XSLCR_I2C_RST_CTRL_OFFSET 0x224 /* I2C Software Reset Control */
+#define XSLCR_UART_RST_CTRL_OFFSET 0x228 /* UART Software Reset Control */
+#define XSLCR_GPIO_RST_CTRL_OFFSET 0x22C /* GPIO Software Reset Control */
+#define XSLCR_QSPI_RST_CTRL_OFFSET 0x230 /* QSpI Software Reset Control */
+#define XSLCR_SMC_RST_CTRL_OFFSET 0x234 /* SMC Software Reset Control */
+#define XSLCR_OCM_RST_CTRL_OFFSET 0x238 /* OCM Software Reset Control */
+#define XSLCR_DEVC_RST_CTRL_OFFSET 0x23C /* Dev Cfg SW Reset Control */
+#define XSLCR_FPGA_RST_CTRL_OFFSET 0x240 /* FPGA Software Reset Control */
+#define XSLCR_MIO_PIN_00_OFFSET 0x700 /* MIO PIN0 control register */
+#define XSLCR_LVL_SHFTR_EN_OFFSET 0x900 /* Level Shifters Enable */
+
+/* Bit masks for AMBA Peripheral Clock Control register */
+#define XSLCR_APER_CLK_CTRL_DMA0_MASK 0x00000001 /* DMA0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_USB0_MASK 0x00000004 /* USB0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_USB1_MASK 0x00000008 /* USB1 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_EMAC0_MASK 0x00000040 /* EMAC0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_EMAC1_MASK 0x00000080 /* EMAC1 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_SDI0_MASK 0x00000400 /* SDIO0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_SDI1_MASK 0x00000800 /* SDIO1 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_SPI0_MASK 0x00004000 /* SPI0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_SPI1_MASK 0x00008000 /* SPI1 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_CAN0_MASK 0x00010000 /* CAN0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_CAN1_MASK 0x00020000 /* CAN1 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_I2C0_MASK 0x00040000 /* I2C0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_I2C1_MASK 0x00080000 /* I2C1 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_UART0_MASK 0x00100000 /* UART0 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_UART1_MASK 0x00200000 /* UART1 AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_GPIO_MASK 0x00400000 /* GPIO AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_QSPI_MASK 0x00800000 /* QSPI AMBA Clock active */
+#define XSLCR_APER_CLK_CTRL_SMC_MASK 0x01000000 /* SMC AMBA Clock active */
+
+#define XSLCR_MIO_L0_SHIFT 1
+#define XSLCR_MIO_L1_SHIFT 2
+#define XSLCR_MIO_L2_SHIFT 3
+#define XSLCR_MIO_L3_SHIFT 5
+
+#define XSLCR_MIO_LMASK 0x000000FE
+
+#define XSLCR_MIO_PIN_XX_TRI_ENABLE 0x00000001
+
+/* The following constants define L0 Mux Peripheral Enables */
+#define XSLCR_MIO_PIN_EMAC_ENABLE (0x01 << XSLCR_MIO_L0_SHIFT)
+#define XSLCR_MIO_PIN_QSPI_ENABLE (0x01 << XSLCR_MIO_L0_SHIFT)
+
+/* The following constants define L1 Mux Enables */
+#define XSLCR_MIO_PIN_USB_ENABLE (0x01 << XSLCR_MIO_L1_SHIFT)
+#define XSLCR_MIO_PIN_TRACE_PORT_ENABLE (0x01 << XSLCR_MIO_L1_SHIFT)
+
+/* The following constants define L2 Mux Peripheral Enables */
+#define XSLCR_MIO_PIN_SRAM_NOR_ENABLE (0x01 << XSLCR_MIO_L2_SHIFT)
+#define XSLCR_MIO_PIN_NAND_ENABLE (0x02 << XSLCR_MIO_L2_SHIFT)
+
+/* The following constants define L3 Mux Peripheral Enables */
+#define XSLCR_MIO_PIN_GPIO_ENABLE (0x00 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_CAN_ENABLE (0x01 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_IIC_ENABLE (0x02 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_WDT_ENABLE (0x03 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_JTAG_ENABLE (0x03 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_SDIO_ENABLE (0x04 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_MDIO0_ENABLE (0x04 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_MDIO1_ENABLE (0x05 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_SPI_ENABLE (0x05 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_TTC_ENABLE (0x06 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_UART_ENABLE (0x07 << XSLCR_MIO_L3_SHIFT)
+
+/* The following constants define the number of pins associated with each
+ * peripheral */
+#define XSLCR_MIO_NUM_EMAC_PINS 12
+#define XSLCR_MIO_NUM_USB_PINS 12
+#define XSLCR_MIO_NUM_TRACE_DATA2_PINS 04
+#define XSLCR_MIO_NUM_TRACE_DATA4_PINS 06
+#define XSLCR_MIO_NUM_TRACE_DATA8_PINS 10
+#define XSLCR_MIO_NUM_TRACE_DATA16_PINS 18
+#define XSLCR_MIO_NUM_NAND_PINS (21+1)
+#define XSLCR_MIO_NUM_SMC_A25_PINS 01
+#define XSLCR_MIO_NUM_SMC_CS_PINS 01
+#define XSLCR_MIO_NUM_NAND_CS_PINS 01
+#define XSLCR_MIO_NUM_SRAM_NOR_PINS 38
+#define XSLCR_MIO_NUM_QSPI_PINS 05
+#define XSLCR_MIO_NUM_QSPI_SEL_PINS 01
+#define XSLCR_MIO_NUM_QSPI_FOC_PINS 01
+#define XSLCR_MIO_NUM_GPIO_PINS 01
+#define XSLCR_MIO_NUM_CAN_PINS 02
+#define XSLCR_MIO_NUM_IIC_PINS 02
+#define XSLCR_MIO_NUM_JTAG_PINS 04
+#define XSLCR_MIO_NUM_WDT_PINS 02
+#define XSLCR_MIO_NUM_MDIO_PINS 02
+#define XSLCR_MIO_NUM_SDIO_PINS 06
+#define XSLCR_MIO_NUM_SPI_PINS 06
+#define XSLCR_MIO_NUM_TTC_PINS 02
+#define XSLCR_MIO_NUM_UART_PINS 02
+
+/* The following two constants define the indices of the MIO peripherals
+ * EMAC0/1 in the array mio_periph_name */
+#define MIO_EMAC0 0
+#define MIO_EMAC1 1
+
+#define XSLCR_MDIO_PIN_0 52
+#define XSLCR_MIO_MAX_PIN 54
+
+#define xslcr_writereg(offset, val) __raw_writel(val, offset)
+#define xslcr_readreg(offset) __raw_readl(offset)
+
+/**
+ * struct xslcr - slcr device data.
+ * @regs: baseaddress of device.
+ * @io_lock: spinlock used for synchronization.
+ */
+struct xslcr {
+ void __iomem *regs;
+ spinlock_t io_lock;
+};
+
+static struct xslcr *slcr;
+
+/**
+ * xslcr_mio - Holds information required to enable/disable a MIO peripheral.
+ *
+ * @set_pins: Pointer to array of first pins in each pin set for this periph
+ * @max_sets: Max pin sets for this periph
+ * @numpins: Number of pins for this periph
+ * @enable_val: Enable value to assign a MIO pin to this periph
+ * @amba_clk_mask: AMBA peripheral clock enable mask for this periph
+ * @periph_clk_reg: Clock enable register offset for the periph
+ * @periph_clk_mask: Clock enable mask for the periph
+ */
+struct xslcr_mio {
+ const int *set_pins;
+ int max_sets;
+ int numpins;
+ u32 enable_val;
+ u32 amba_clk_mask;
+ u32 periph_clk_reg;
+ u32 periph_clk_mask;
+};
+
+/**
+ * xslcr_periph_reset - Holds information required to reset a peripheral.
+ *
+ * @reg_offset: offset of the reset reg for the peripheral
+ * @reset_mask: mask to reset the peripheral
+ */
+struct xslcr_periph_reset {
+ u32 reg_offset;
+ u32 reset_mask;
+};
+
+/* MIO peripheral names */
+static const char *mio_periph_name[] = {
+ "emac0",
+ "emac1",
+ "qspi0",
+ "qspi0_sel",
+ "qspi1",
+ "qspi1_sel",
+ "qspi_foc",
+ "trace_data2",
+ "trace_data4",
+ "trace_data8",
+ "trace_data16",
+ "usb0",
+ "usb1",
+ "smc_a25",
+ "smc_cs",
+ "sram_nor",
+ "nand",
+ "nand_cs",
+ "gpio00",
+ "gpio01",
+ "gpio02",
+ "gpio03",
+ "gpio04",
+ "gpio05",
+ "gpio06",
+ "gpio07",
+ "gpio08",
+ "gpio09",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+ "gpio24",
+ "gpio25",
+ "gpio26",
+ "gpio27",
+ "gpio28",
+ "gpio29",
+ "gpio30",
+ "gpio31",
+ "gpio32",
+ "gpio33",
+ "gpio34",
+ "gpio35",
+ "gpio36",
+ "gpio37",
+ "gpio38",
+ "gpio39",
+ "gpio40",
+ "gpio41",
+ "gpio42",
+ "gpio43",
+ "gpio44",
+ "gpio45",
+ "gpio46",
+ "gpio47",
+ "gpio48",
+ "gpio49",
+ "gpio50",
+ "gpio51",
+ "gpio52",
+ "gpio53",
+ "can0",
+ "can1",
+ "iic0",
+ "iic1",
+ "jtag",
+ "wdt",
+ "mdio0",
+ "sdio0",
+ "sdio1",
+ "mdio1",
+ "spi0",
+ "spi1",
+ "ttc0",
+ "ttc1",
+ "uart0",
+ "uart1",
+};
+
+/* Each bit in this array is a flag that indicates whether a mio peripheral
+ * is assigned. The order of bits in this array is same as the order of
+ * peripheral names in the array mio_periph_name */
+static u32 periph_status[2] = {0, 0};
+
+/* Each element in the following array holds the active pinset of a MIO
+ * peripheral. The order of peripherals in this array is same as the order of
+ * peripheral names in the array mio_periph_name */
+static u32 active_pinset[ARRAY_SIZE(mio_periph_name)];
+
+/* The following arrays contain the first pin in each pin set of a MIO
+ * corresponding peripheral.
+ */
+static const int emac0_pins[] = { 16 };
+static const int emac1_pins[] = { 28, 40 };
+static const int qspi0_pins[] = { 2 };
+static const int qspi0_sel_pins[] = { 1 };
+static const int qspi1_pins[] = { 9 };
+static const int qspi1_sel_pins[] = { 0 };
+static const int qspi_foc_pins[] = { 8 };
+static const int trace_data2_pins[] = { 12, 24 };
+static const int trace_data4_pins[] = { 10, 22 };
+static const int trace_data8_pins[] = { 10 };
+static const int trace_data16_pins[] = { 2 };
+static const int usb0_pins[] = { 28 };
+static const int usb1_pins[] = { 40 };
+static const int smc_a25_pins[] = { 1 };
+static const int smc_cs_pins[] = { 0, 1 };
+static const int sram_nor_pins[] = { 2 };
+static const int nand_pins[] = { 2 };
+static const int nand_cs_pins[] = { 0 };
+static const int gpio00_pins[] = { 0 };
+static const int gpio01_pins[] = { 1 };
+static const int gpio02_pins[] = { 2 };
+static const int gpio03_pins[] = { 3 };
+static const int gpio04_pins[] = { 4 };
+static const int gpio05_pins[] = { 5 };
+static const int gpio06_pins[] = { 6 };
+static const int gpio07_pins[] = { 7 };
+static const int gpio08_pins[] = { 8 };
+static const int gpio09_pins[] = { 9 };
+static const int gpio10_pins[] = { 10 };
+static const int gpio11_pins[] = { 11 };
+static const int gpio12_pins[] = { 12 };
+static const int gpio13_pins[] = { 13 };
+static const int gpio14_pins[] = { 14 };
+static const int gpio15_pins[] = { 15 };
+static const int gpio16_pins[] = { 16 };
+static const int gpio17_pins[] = { 17 };
+static const int gpio18_pins[] = { 18 };
+static const int gpio19_pins[] = { 19 };
+static const int gpio20_pins[] = { 20 };
+static const int gpio21_pins[] = { 21 };
+static const int gpio22_pins[] = { 22 };
+static const int gpio23_pins[] = { 23 };
+static const int gpio24_pins[] = { 24 };
+static const int gpio25_pins[] = { 25 };
+static const int gpio26_pins[] = { 26 };
+static const int gpio27_pins[] = { 27 };
+static const int gpio28_pins[] = { 28 };
+static const int gpio29_pins[] = { 29 };
+static const int gpio30_pins[] = { 30 };
+static const int gpio31_pins[] = { 31 };
+static const int gpio32_pins[] = { 32 };
+static const int gpio33_pins[] = { 33 };
+static const int gpio34_pins[] = { 34 };
+static const int gpio35_pins[] = { 35 };
+static const int gpio36_pins[] = { 36 };
+static const int gpio37_pins[] = { 37 };
+static const int gpio38_pins[] = { 38 };
+static const int gpio39_pins[] = { 39 };
+static const int gpio40_pins[] = { 40 };
+static const int gpio41_pins[] = { 41 };
+static const int gpio42_pins[] = { 42 };
+static const int gpio43_pins[] = { 43 };
+static const int gpio44_pins[] = { 44 };
+static const int gpio45_pins[] = { 45 };
+static const int gpio46_pins[] = { 46 };
+static const int gpio47_pins[] = { 47 };
+static const int gpio48_pins[] = { 48 };
+static const int gpio49_pins[] = { 49 };
+static const int gpio50_pins[] = { 50 };
+static const int gpio51_pins[] = { 51 };
+static const int gpio52_pins[] = { 52 };
+static const int gpio53_pins[] = { 53 };
+static const int can0_pins[] = { 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50 };
+static const int can1_pins[] = { 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52 };
+static const int iic0_pins[] = { 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50 };
+static const int iic1_pins[] = { 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52 };
+static const int jtag0_pins[] = { 10, 22, 34, 46 };
+static const int wdt_pins[] = { 14, 26, 38, 50, 52 };
+static const int mdio0_pins[] = { 52 };
+static const int sdio0_pins[] = { 16, 28, 40 };
+static const int sdio1_pins[] = { 10, 22, 34, 46 };
+static const int mdio1_pins[] = { 52 };
+static const int spi0_pins[] = { 16, 28, 40 };
+static const int spi1_pins[] = { 10, 22, 34, 46 };
+static const int ttc0_pins[] = { 18, 30, 42 };
+static const int ttc1_pins[] = { 16, 28, 40 };
+static const int uart0_pins[] = { 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50 };
+static const int uart1_pins[] = { 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52 };
+
+/* The following array contains required info for enabling MIO peripherals and
+ * their clocks. The order of the structures in this array is same as the order
+ * of peripheral names in the array mio_periph_name */
+static const struct xslcr_mio mio_periphs[] = {
+ {
+ emac0_pins,
+ ARRAY_SIZE(emac0_pins),
+ XSLCR_MIO_NUM_EMAC_PINS,
+ XSLCR_MIO_PIN_EMAC_ENABLE,
+ XSLCR_APER_CLK_CTRL_EMAC0_MASK,
+ XSLCR_EMAC0_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ emac1_pins,
+ ARRAY_SIZE(emac1_pins),
+ XSLCR_MIO_NUM_EMAC_PINS,
+ XSLCR_MIO_PIN_EMAC_ENABLE,
+ XSLCR_APER_CLK_CTRL_EMAC1_MASK,
+ XSLCR_EMAC1_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ qspi0_pins,
+ ARRAY_SIZE(qspi0_pins),
+ XSLCR_MIO_NUM_QSPI_PINS,
+ XSLCR_MIO_PIN_QSPI_ENABLE,
+ XSLCR_APER_CLK_CTRL_QSPI_MASK,
+ XSLCR_QSPI_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ qspi0_sel_pins,
+ ARRAY_SIZE(qspi0_sel_pins),
+ XSLCR_MIO_NUM_QSPI_SEL_PINS,
+ XSLCR_MIO_PIN_QSPI_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ qspi1_pins,
+ ARRAY_SIZE(qspi1_pins),
+ XSLCR_MIO_NUM_QSPI_PINS,
+ XSLCR_MIO_PIN_QSPI_ENABLE,
+ XSLCR_APER_CLK_CTRL_QSPI_MASK,
+ XSLCR_QSPI_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ qspi1_sel_pins,
+ ARRAY_SIZE(qspi1_sel_pins),
+ XSLCR_MIO_NUM_QSPI_SEL_PINS,
+ XSLCR_MIO_PIN_QSPI_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ qspi_foc_pins,
+ ARRAY_SIZE(qspi_foc_pins),
+ XSLCR_MIO_NUM_QSPI_FOC_PINS,
+ XSLCR_MIO_PIN_QSPI_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ trace_data2_pins,
+ ARRAY_SIZE(trace_data2_pins),
+ XSLCR_MIO_NUM_TRACE_DATA2_PINS,
+ XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ trace_data4_pins,
+ ARRAY_SIZE(trace_data4_pins),
+ XSLCR_MIO_NUM_TRACE_DATA4_PINS,
+ XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ trace_data8_pins,
+ ARRAY_SIZE(trace_data8_pins),
+ XSLCR_MIO_NUM_TRACE_DATA8_PINS,
+ XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ trace_data16_pins,
+ ARRAY_SIZE(trace_data16_pins),
+ XSLCR_MIO_NUM_TRACE_DATA4_PINS,
+ XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ usb0_pins,
+ ARRAY_SIZE(usb0_pins),
+ XSLCR_MIO_NUM_USB_PINS,
+ XSLCR_MIO_PIN_USB_ENABLE,
+ XSLCR_APER_CLK_CTRL_USB0_MASK,
+ XSLCR_USB0_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ usb1_pins,
+ ARRAY_SIZE(usb1_pins),
+ XSLCR_MIO_NUM_USB_PINS,
+ XSLCR_MIO_PIN_USB_ENABLE,
+ XSLCR_APER_CLK_CTRL_USB1_MASK,
+ XSLCR_USB1_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ smc_a25_pins,
+ ARRAY_SIZE(smc_a25_pins),
+ XSLCR_MIO_NUM_SMC_A25_PINS,
+ XSLCR_MIO_PIN_SRAM_NOR_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ smc_cs_pins,
+ ARRAY_SIZE(smc_cs_pins),
+ XSLCR_MIO_NUM_SMC_CS_PINS,
+ XSLCR_MIO_PIN_SRAM_NOR_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ sram_nor_pins,
+ ARRAY_SIZE(sram_nor_pins),
+ XSLCR_MIO_NUM_SRAM_NOR_PINS,
+ XSLCR_MIO_PIN_SRAM_NOR_ENABLE,
+ XSLCR_APER_CLK_CTRL_SMC_MASK,
+ XSLCR_SMC_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ nand_pins,
+ ARRAY_SIZE(nand_pins),
+ XSLCR_MIO_NUM_NAND_PINS,
+ XSLCR_MIO_PIN_NAND_ENABLE,
+ XSLCR_APER_CLK_CTRL_SMC_MASK,
+ XSLCR_SMC_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ nand_cs_pins,
+ ARRAY_SIZE(nand_cs_pins),
+ XSLCR_MIO_NUM_NAND_CS_PINS,
+ XSLCR_MIO_PIN_NAND_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ gpio00_pins,
+ ARRAY_SIZE(gpio00_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio01_pins,
+ ARRAY_SIZE(gpio01_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio02_pins,
+ ARRAY_SIZE(gpio02_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio03_pins,
+ ARRAY_SIZE(gpio03_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio04_pins,
+ ARRAY_SIZE(gpio04_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio05_pins,
+ ARRAY_SIZE(gpio05_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio06_pins,
+ ARRAY_SIZE(gpio06_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio07_pins,
+ ARRAY_SIZE(gpio07_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio08_pins,
+ ARRAY_SIZE(gpio08_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio09_pins,
+ ARRAY_SIZE(gpio09_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio10_pins,
+ ARRAY_SIZE(gpio10_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio11_pins,
+ ARRAY_SIZE(gpio11_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio12_pins,
+ ARRAY_SIZE(gpio12_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio13_pins,
+ ARRAY_SIZE(gpio13_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio14_pins,
+ ARRAY_SIZE(gpio14_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio15_pins,
+ ARRAY_SIZE(gpio15_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio16_pins,
+ ARRAY_SIZE(gpio16_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio17_pins,
+ ARRAY_SIZE(gpio17_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio18_pins,
+ ARRAY_SIZE(gpio18_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio19_pins,
+ ARRAY_SIZE(gpio19_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio20_pins,
+ ARRAY_SIZE(gpio20_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio21_pins,
+ ARRAY_SIZE(gpio21_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio22_pins,
+ ARRAY_SIZE(gpio22_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio23_pins,
+ ARRAY_SIZE(gpio23_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio24_pins,
+ ARRAY_SIZE(gpio24_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio25_pins,
+ ARRAY_SIZE(gpio25_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio26_pins,
+ ARRAY_SIZE(gpio26_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio27_pins,
+ ARRAY_SIZE(gpio27_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio28_pins,
+ ARRAY_SIZE(gpio28_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio29_pins,
+ ARRAY_SIZE(gpio29_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio30_pins,
+ ARRAY_SIZE(gpio30_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio31_pins,
+ ARRAY_SIZE(gpio31_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio32_pins,
+ ARRAY_SIZE(gpio32_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio33_pins,
+ ARRAY_SIZE(gpio33_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio34_pins,
+ ARRAY_SIZE(gpio34_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio35_pins,
+ ARRAY_SIZE(gpio35_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio36_pins,
+ ARRAY_SIZE(gpio36_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio37_pins,
+ ARRAY_SIZE(gpio37_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio38_pins,
+ ARRAY_SIZE(gpio38_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio39_pins,
+ ARRAY_SIZE(gpio39_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio40_pins,
+ ARRAY_SIZE(gpio40_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio41_pins,
+ ARRAY_SIZE(gpio41_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio42_pins,
+ ARRAY_SIZE(gpio42_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio43_pins,
+ ARRAY_SIZE(gpio43_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio44_pins,
+ ARRAY_SIZE(gpio44_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio45_pins,
+ ARRAY_SIZE(gpio45_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio46_pins,
+ ARRAY_SIZE(gpio46_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio47_pins,
+ ARRAY_SIZE(gpio47_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio48_pins,
+ ARRAY_SIZE(gpio48_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio49_pins,
+ ARRAY_SIZE(gpio49_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio50_pins,
+ ARRAY_SIZE(gpio50_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio51_pins,
+ ARRAY_SIZE(gpio51_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio52_pins,
+ ARRAY_SIZE(gpio52_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ gpio53_pins,
+ ARRAY_SIZE(gpio53_pins),
+ XSLCR_MIO_NUM_GPIO_PINS,
+ XSLCR_MIO_PIN_GPIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_GPIO_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ can0_pins,
+ ARRAY_SIZE(can0_pins),
+ XSLCR_MIO_NUM_CAN_PINS,
+ XSLCR_MIO_PIN_CAN_ENABLE,
+ XSLCR_APER_CLK_CTRL_CAN0_MASK,
+ XSLCR_CAN_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ can1_pins,
+ ARRAY_SIZE(can1_pins),
+ XSLCR_MIO_NUM_CAN_PINS,
+ XSLCR_MIO_PIN_CAN_ENABLE,
+ XSLCR_APER_CLK_CTRL_CAN1_MASK,
+ XSLCR_CAN_CLK_CTRL_OFFSET,
+ 0x02,
+ }, {
+ iic0_pins,
+ ARRAY_SIZE(iic0_pins),
+ XSLCR_MIO_NUM_IIC_PINS,
+ XSLCR_MIO_PIN_IIC_ENABLE,
+ XSLCR_APER_CLK_CTRL_I2C0_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ iic1_pins,
+ ARRAY_SIZE(iic1_pins),
+ XSLCR_MIO_NUM_IIC_PINS,
+ XSLCR_MIO_PIN_IIC_ENABLE,
+ XSLCR_APER_CLK_CTRL_I2C1_MASK,
+ 0x00,
+ 0x00,
+ }, {
+ jtag0_pins,
+ ARRAY_SIZE(jtag0_pins),
+ XSLCR_MIO_NUM_JTAG_PINS,
+ XSLCR_MIO_PIN_JTAG_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ wdt_pins,
+ ARRAY_SIZE(wdt_pins),
+ XSLCR_MIO_NUM_WDT_PINS,
+ XSLCR_MIO_PIN_WDT_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ mdio0_pins,
+ ARRAY_SIZE(mdio0_pins),
+ XSLCR_MIO_NUM_MDIO_PINS,
+ XSLCR_MIO_PIN_MDIO0_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ sdio0_pins,
+ ARRAY_SIZE(sdio0_pins),
+ XSLCR_MIO_NUM_SDIO_PINS,
+ XSLCR_MIO_PIN_SDIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_SDI0_MASK,
+ XSLCR_SDIO_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ sdio1_pins,
+ ARRAY_SIZE(sdio1_pins),
+ XSLCR_MIO_NUM_SDIO_PINS,
+ XSLCR_MIO_PIN_SDIO_ENABLE,
+ XSLCR_APER_CLK_CTRL_SDI1_MASK,
+ XSLCR_SDIO_CLK_CTRL_OFFSET,
+ 0x02,
+ }, {
+ mdio1_pins,
+ ARRAY_SIZE(mdio1_pins),
+ XSLCR_MIO_NUM_MDIO_PINS,
+ XSLCR_MIO_PIN_MDIO1_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ spi0_pins,
+ ARRAY_SIZE(spi0_pins),
+ XSLCR_MIO_NUM_SPI_PINS,
+ XSLCR_MIO_PIN_SPI_ENABLE,
+ XSLCR_APER_CLK_CTRL_SPI0_MASK,
+ XSLCR_SPI_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ spi1_pins,
+ ARRAY_SIZE(spi1_pins),
+ XSLCR_MIO_NUM_SPI_PINS,
+ XSLCR_MIO_PIN_SPI_ENABLE,
+ XSLCR_APER_CLK_CTRL_SPI0_MASK,
+ XSLCR_SPI_CLK_CTRL_OFFSET,
+ 0x02,
+ }, {
+ ttc0_pins,
+ ARRAY_SIZE(ttc0_pins),
+ XSLCR_MIO_NUM_TTC_PINS,
+ XSLCR_MIO_PIN_TTC_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ ttc1_pins,
+ ARRAY_SIZE(ttc1_pins),
+ XSLCR_MIO_NUM_TTC_PINS,
+ XSLCR_MIO_PIN_TTC_ENABLE,
+ 0x00,
+ 0x00,
+ 0x00,
+ }, {
+ uart0_pins,
+ ARRAY_SIZE(uart0_pins),
+ XSLCR_MIO_NUM_UART_PINS,
+ XSLCR_MIO_PIN_UART_ENABLE,
+ XSLCR_APER_CLK_CTRL_UART0_MASK,
+ XSLCR_UART_CLK_CTRL_OFFSET,
+ 0x01,
+ }, {
+ uart1_pins,
+ ARRAY_SIZE(uart1_pins),
+ XSLCR_MIO_NUM_UART_PINS,
+ XSLCR_MIO_PIN_UART_ENABLE,
+ XSLCR_APER_CLK_CTRL_UART1_MASK,
+ XSLCR_UART_CLK_CTRL_OFFSET,
+ 0x02,
+ },
+};
+
+/* Peripherals that can be reset thru SLCR */
+static const char *reset_periph_name[] = {
+ "pss",
+ "ddr",
+ "sw_amba",
+ "dmac",
+ "usb0_amba",
+ "usb1_amba",
+ "usb0_usb",
+ "usb1_usb",
+ "eth0_mac",
+ "eth1_mac",
+ "eth0_rx",
+ "eth1_rx",
+ "eth0_ref",
+ "eth1_ref",
+ "sdio0_amba",
+ "sdio1_amba",
+ "sdio0_ref",
+ "sdio1_ref",
+ "spi0_amba",
+ "spi1_ambs",
+ "spi0_ref",
+ "spi1_ref",
+ "can0_amba",
+ "can1_amba",
+ "can0_ref",
+ "can1_ref",
+ "iic0_amba",
+ "iic1_amba",
+ "uart0_amba",
+ "uart1_amba",
+ "gpio_amba",
+ "qspi_amba",
+ "qspi_ref",
+ "smc_amba",
+ "smc_ref",
+ "ocm_amba",
+ "pcap2x",
+ "devc_amba",
+ "fpga0_out",
+ "fpga1_out",
+ "fpga2_out",
+ "fpga3_out",
+ "fpga_dma0",
+ "fpga_dma1",
+ "fpga_dma2",
+ "fpga_dma3",
+ "fpga_fmsw0",
+ "fpga_fmsw1",
+ "fpga_fssw0",
+ "fpga_fssw1",
+ "fpga_axds0",
+ "fpga_axds1",
+ "fpga_axds2",
+ "fpga_axds3",
+ "fpga_acp",
+};
+
+/* The following array contains the reset control register offset and the reset
+ * mask for all the peripherals. The order of the structures is same as the
+ * order of peripheral names in the array reset_periph_name */
+static const struct xslcr_periph_reset reset_info[] = {
+ { XSLCR_PSS_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_DDR_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_AMBA_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_DMAC_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_USB_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_USB_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_USB_RST_CTRL_OFFSET, 0x00000010 },
+ { XSLCR_USB_RST_CTRL_OFFSET, 0x00000020 },
+ { XSLCR_EMAC_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_EMAC_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_EMAC_RST_CTRL_OFFSET, 0x00000010 },
+ { XSLCR_EMAC_RST_CTRL_OFFSET, 0x00000020 },
+ { XSLCR_EMAC_RST_CTRL_OFFSET, 0x00000040 },
+ { XSLCR_EMAC_RST_CTRL_OFFSET, 0x00000080 },
+ { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000010 },
+ { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000020 },
+ { XSLCR_SPI_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_SPI_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_SPI_RST_CTRL_OFFSET, 0x00000004 },
+ { XSLCR_SPI_RST_CTRL_OFFSET, 0x00000008 },
+ { XSLCR_CAN_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_CAN_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_CAN_RST_CTRL_OFFSET, 0x00000004 },
+ { XSLCR_CAN_RST_CTRL_OFFSET, 0x00000008 },
+ { XSLCR_I2C_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_I2C_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_UART_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_UART_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_GPIO_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_QSPI_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_QSPI_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_SMC_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_SMC_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_OCM_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_DEVC_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_DEVC_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000001 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000002 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000004 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000008 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000100 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000200 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000400 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000800 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00001000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00002000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00010000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00020000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00100000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00200000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00400000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00800000 },
+ { XSLCR_FPGA_RST_CTRL_OFFSET, 0x01000000 },
+};
+
+/**
+ * xslcr_system_reset - Reset the entire system.
+ */
+void xslcr_system_reset(void)
+{
+ /* Unlock the SLCR then reset the system.
+ * Note that this seems to require raw i/o
+ * functions or there's a lockup?
+ */
+ xslcr_writereg(slcr->regs + 8, 0xDF0D);
+ xslcr_writereg(slcr->regs + XSLCR_PSS_RST_CTRL_OFFSET, 1);
+}
+
+/**
+ * xslcr_write - Write to a register in SLCR block
+ *
+ * @offset: Register offset in SLCR block
+ * @val: Value to write to the register
+ */
+void xslcr_write(u32 offset, u32 val)
+{
+ xslcr_writereg(slcr->regs + offset, val);
+}
+EXPORT_SYMBOL(xslcr_write);
+
+/**
+ * xslcr_read - Read a register in SLCR block
+ *
+ * @offset: Register offset in SLCR block
+ *
+ * return: Value read from the SLCR register
+ */
+u32 xslcr_read(u32 offset)
+{
+ return xslcr_readreg(slcr->regs + offset);
+}
+EXPORT_SYMBOL(xslcr_read);
+
+/**
+ * xslcr_init_preload_fpga - Disable communication from the PL to PS.
+ */
+void xslcr_init_preload_fpga(void)
+{
+ /* Assert FPGA top level output resets */
+ xslcr_write(XSLCR_FPGA_RST_CTRL_OFFSET, 0xF);
+ /* Disable level shifters */
+ xslcr_write(XSLCR_LVL_SHFTR_EN_OFFSET, 0x0);
+ /* Enable output level shifters */
+ xslcr_write(XSLCR_LVL_SHFTR_EN_OFFSET, 0xA);
+}
+EXPORT_SYMBOL(xslcr_init_preload_fpga);
+
+/**
+ * xslcr_init_postload_fpga - Re-enable communication from the PL to PS.
+ */
+void xslcr_init_postload_fpga(void)
+{
+ /* Enable level shifters */
+ xslcr_write(XSLCR_LVL_SHFTR_EN_OFFSET, 0xF);
+ /* Deassert AXI interface resets */
+ xslcr_write(XSLCR_FPGA_RST_CTRL_OFFSET, 0x0);
+}
+EXPORT_SYMBOL(xslcr_init_postload_fpga);
+
+/**
+ * xslcr_set_bit - Set a bit
+ *
+ * @data: Address of the data in which a bit is to be set
+ * @bit: Bit number to set
+ */
+static inline void xslcr_set_bit(u32 *data, unsigned int bit)
+{
+ unsigned long mask = 1UL << (bit & 31);
+ *(data + (bit >> 5)) |= mask;
+}
+
+/**
+ * xslcr_clear_bit - Clear a bit
+ *
+ * @data: Address of the data in which a bit is to be cleared
+ * @bit: Bit number to clear
+ */
+static inline void xslcr_clear_bit(u32 *data, unsigned int bit)
+{
+ unsigned long mask = 1UL << (bit & 31);
+ *(data + (bit >> 5)) &= ~mask;
+}
+
+/**
+ * xslcr_test_bit - Check if a bit is set
+ *
+ * @data: Address of the data in which a bit is to be checked
+ * @bit: Bit number to check
+ *
+ * return: True or false
+ */
+static inline int xslcr_test_bit(u32 *data, unsigned int bit)
+{
+ unsigned long mask = 1UL << (bit & 31);
+ return (*(data + (bit >> 5)) & mask) != 0;
+}
+
+/**
+ * xslcr_mio_isavailable - Check if a MIO pin is available for assignment.
+ *
+ * @pin MIO pin to be checked.
+ *
+ * return: -EBUSY if the pin is in use.
+ * 0 if the pin is not assigned.
+ */
+static int xslcr_mio_isavailable(u32 pin)
+{
+ u32 reg;
+
+ reg = xslcr_readreg(slcr->regs + XSLCR_MIO_PIN_00_OFFSET + (pin * 4));
+ if (reg & XSLCR_MIO_PIN_XX_TRI_ENABLE)
+ return 0;
+
+ return -EBUSY; /* pin is assigned */
+}
+
+/**
+ * xslcr_enable_mio_clock - Enable the clocks for a MIO peripheral.
+ *
+ * @mio_periph id used to look up the data needed to enable clocks for this
+ * peripheral.
+ *
+ * This function enables the AMBA clock and the peripheral clock for a
+ * peripheral. It also enables Rx clocks in case of EMAC0/EMAC1.
+ */
+static void xslcr_enable_mio_clock(int mio_periph)
+{
+ u32 clk_reg;
+ const struct xslcr_mio *mio_ptr;
+
+ mio_ptr = &mio_periphs[mio_periph];
+
+ /* enable AMBA clock and peripheral clock */
+ clk_reg = xslcr_readreg(slcr->regs + XSLCR_APER_CLK_CTRL_OFFSET);
+ clk_reg |= mio_ptr->amba_clk_mask;
+ xslcr_writereg((slcr->regs + XSLCR_APER_CLK_CTRL_OFFSET), clk_reg);
+
+ clk_reg = xslcr_readreg(slcr->regs + mio_ptr->periph_clk_reg);
+ clk_reg |= mio_ptr->periph_clk_mask;
+ xslcr_writereg((slcr->regs + mio_ptr->periph_clk_reg), clk_reg);
+
+ /* enable Rx clocks for EMAC0 and EMAC1 */
+ if (mio_periph == MIO_EMAC0)
+ xslcr_writereg((slcr->regs + XSLCR_EMAC0_RCLK_CTRL_OFFSET),
+ 0x01);
+ else if (mio_periph == MIO_EMAC1)
+ xslcr_writereg((slcr->regs + XSLCR_EMAC1_RCLK_CTRL_OFFSET),
+ 0x01);
+}
+
+/**
+ * xslcr_disable_mio_clock - Disable the clocks for a MIO peripheral.
+ *
+ * @mio_periph id used to look up the data needed to disable clocks
+ * for this peripheral.
+ *
+ * This function disables the AMBA clock and the peripheral clock for a
+ * peripheral. It also disables Rx clocks in case of EMAC0/EMAC1.
+ */
+static void xslcr_disable_mio_clock(int mio_periph)
+{
+ u32 clk_reg;
+ const struct xslcr_mio *mio_ptr;
+
+ mio_ptr = &mio_periphs[mio_periph];
+
+ /* disable AMBA clock and peripheral clock */
+ clk_reg = xslcr_readreg(slcr->regs + XSLCR_APER_CLK_CTRL_OFFSET);
+ clk_reg &= ~(mio_ptr->amba_clk_mask);
+ xslcr_writereg((slcr->regs + XSLCR_APER_CLK_CTRL_OFFSET), clk_reg);
+
+ clk_reg = xslcr_readreg(slcr->regs + mio_ptr->periph_clk_reg);
+ clk_reg &= ~(mio_ptr->periph_clk_mask);
+ xslcr_writereg((slcr->regs + mio_ptr->periph_clk_reg), clk_reg);
+
+ /* disable Rx clocks for EMAC0 and EMAC1 */
+ if (mio_periph == MIO_EMAC0)
+ xslcr_writereg((slcr->regs + XSLCR_EMAC0_RCLK_CTRL_OFFSET),
+ 0x00);
+ else if (mio_periph == MIO_EMAC1)
+ xslcr_writereg((slcr->regs + XSLCR_EMAC1_RCLK_CTRL_OFFSET),
+ 0x00);
+}
+
+/**
+ * xslcr_enable_mio_peripheral - Enable a MIO peripheral.
+ *
+ * @mio: id used to lookup the data needed to enable the peripheral.
+ *
+ * This function enables a MIO peripheral on a pinset previously set by the
+ * user, thru sysfs attribute 'pinset'.
+ *
+ * return: 0 if the peripheral is enabled on the given pin set.
+ * negative error if the peripheral is already enabled, if an
+ * invalid pinset is specified, or if the pins are assigned to a
+ * different peripheral.
+ */
+static int xslcr_enable_mio_peripheral(int mio)
+{
+ int pin_set, pin, i;
+ unsigned long flags;
+ const struct xslcr_mio *mio_ptr;
+
+ /* enable the peripheral only if it hasn't been already enabled */
+ if (xslcr_test_bit(periph_status, mio))
+ return -EBUSY;
+
+ /* get the pin set */
+ pin_set = active_pinset[mio];
+
+ mio_ptr = &mio_periphs[mio];
+ if (pin_set >= mio_ptr->max_sets) {
+ pr_err("%s: Invalid pinset\n", mio_periph_name[mio]);
+ return -EINVAL;
+ }
+
+ /* check whether all the pins in this pin set are unassigned */
+ pin = mio_ptr->set_pins[pin_set]; /* 1st pin */
+ for (i = 0; i < mio_ptr->numpins; i++) {
+ if (xslcr_mio_isavailable(pin + i)) {
+ pr_err("%s: One or more pins in pinset %d are busy\n",
+ mio_periph_name[mio], pin_set);
+ return -EBUSY;
+ }
+ }
+
+ spin_lock_irqsave(&slcr->io_lock, flags);
+
+ /* assign all pins in the set to this peripheral */
+ for (i = 0; i < mio_ptr->numpins; i++) {
+ /* update the MIO register */
+ xslcr_writereg((slcr->regs + ((pin + i) * 4) +
+ XSLCR_MIO_PIN_00_OFFSET),
+ mio_ptr->enable_val);
+ }
+
+ /* all the pins in the pinset are configured for this peripheral.
+ * enable clocks */
+ xslcr_enable_mio_clock(mio);
+ /* mark that the peripheral has been enabled */
+ xslcr_set_bit(periph_status, mio);
+
+ spin_unlock_irqrestore(&slcr->io_lock, flags);
+
+ pr_debug("Enabled peripheral %s on pinset %d\n",
+ mio_periph_name[mio], pin_set);
+ return 0;
+}
+
+/**
+ * xslcr_disable_mio_peripheral - Disable a MIO peripheral.
+ *
+ * @mio: id used to lookup the data needed to enable the peripheral.
+ *
+ * This function checks if a MIO peripheral is previously enabled on the pinset
+ * specified by the user, disables the peripheral and releases the MIO pins.
+ *
+ * return: 0 if the peripheral is disabled and MIO pins are released.
+ * negative error if the peripheral is already disabled, if an
+ * invalid peripheral is specified, or if the pins are assigned to
+ * a different peripheral.
+ */
+static int xslcr_disable_mio_peripheral(int mio)
+{
+ int pin_set, pin, i;
+ unsigned long flags;
+ const struct xslcr_mio *mio_ptr;
+ u32 reg;
+
+ /* disable the peripheral only if it has been already enabled */
+ if (!xslcr_test_bit(periph_status, mio))
+ return -EBUSY;
+
+ /* get the pin set */
+ pin_set = active_pinset[mio];
+
+ mio_ptr = &mio_periphs[mio];
+ if (pin_set >= mio_ptr->max_sets) {
+ pr_err("%s: Invalid pinset %d\n",
+ mio_periph_name[mio], pin_set);
+ return -EINVAL;
+ }
+
+ pin = mio_ptr->set_pins[pin_set]; /* 1st pin */
+
+ for (i = 0; i < mio_ptr->numpins; i++) {
+ /* check if each pin in the pin_set is assigned to this periph,
+ * to make sure the pins are not being released accidentally*/
+ reg = xslcr_readreg(slcr->regs + XSLCR_MIO_PIN_00_OFFSET +
+ (pin * 4));
+ reg &= XSLCR_MIO_LMASK;
+ if (reg != mio_ptr->enable_val) {
+ pr_err("%s: One or more pins in pinset %d are busy\n",
+ mio_periph_name[mio], pin_set);
+ return -EBUSY;
+ }
+ }
+
+ spin_lock_irqsave(&slcr->io_lock, flags);
+
+ /* release all pins in the set */
+ for (i = 0; i < mio_ptr->numpins; i++) {
+ /* update MIO register, set tri-state */
+ xslcr_writereg((slcr->regs + ((pin + i) * 4) +
+ XSLCR_MIO_PIN_00_OFFSET),
+ xslcr_readreg((slcr->regs + ((pin + i) * 4) +
+ XSLCR_MIO_PIN_00_OFFSET)) |
+ XSLCR_MIO_PIN_XX_TRI_ENABLE);
+ }
+
+ /* all the pins in the set are released. disable clocks */
+ xslcr_disable_mio_clock(mio);
+ /* mark that the peripheral has been disabled */
+ xslcr_clear_bit(periph_status, mio);
+
+ spin_unlock_irqrestore(&slcr->io_lock, flags);
+
+ pr_debug("Disabled peripheral %s on pinset %d\n",
+ mio_periph_name[mio], pin_set);
+ return 0;
+}
+
+static int __xslcr_get_mio_peripheral(struct device *dev)
+{
+ int mio;
+
+ /* check if a valid peripheral is specified */
+ for (mio = 0; mio < ARRAY_SIZE(mio_periph_name); mio++) {
+ if (sysfs_streq(dev_name(dev), mio_periph_name[mio]) == 1)
+ break;
+ }
+
+ if (mio == ARRAY_SIZE(mio_periph_name)) {
+ dev_err(dev, "Invalid peripheral specified\n");
+ return -EINVAL;
+ }
+
+ return mio;
+}
+
+/**
+ * xslcr_config_mio_peripheral - Enable/disable a MIO peripheral.
+ *
+ * @dev: pointer to the MIO device.
+ * @attr: pointer to the 'enable_pinset' device attribute descriptor.
+ * @buf: pointer to the buffer with user data.
+ * @size: size of the buf.
+ *
+ * This function parses the user data in buf and enables/disables the MIO
+ * peripheral specified by dev.
+ *
+ * return: >0 if the peripheral is enabled/disabled successfully.
+ * negative error if the peripheral configuration failed.
+ */
+static ssize_t xslcr_config_mio_peripheral(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int mio, ret;
+ unsigned long en;
+
+ mio = __xslcr_get_mio_peripheral(dev);
+ if (mio < 0)
+ return mio;
+
+ ret = strict_strtoul(buf, 10, &en);
+ if (ret || en > 1) {
+ dev_err(dev, "Invalid user argument\n");
+ return -EINVAL;
+ }
+
+ if (en == 1)
+ ret = xslcr_enable_mio_peripheral(mio);
+ else if (en == 0)
+ ret = xslcr_disable_mio_peripheral(mio);
+
+ return ret == 0 ? size : ret;
+}
+
+static DEVICE_ATTR(enable_pinset, 0644, NULL, xslcr_config_mio_peripheral);
+
+/**
+ * xslcr_store_pinset - Store a pinset for a MIO peripheral.
+ *
+ * @dev: pointer to the MIO device.
+ * @attr: pointer to the 'pinset' device attribute descriptor.
+ * @buf: pointer to the buffer with user data.
+ * @size: size of the buf.
+ *
+ * This function parses the user data in buf and stores the pinset for the MIO
+ * peripheral specified by dev. This pinset will be later used to enable or
+ * disable the MIO peripheral.
+ *
+ * return: 0 if the peripheral is enabled/disabled successfully.
+ * negative error if the peripheral configuration failed.
+ */
+static ssize_t xslcr_store_pinset(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int mio, ret;
+ unsigned long pin_set;
+
+ mio = __xslcr_get_mio_peripheral(dev);
+ if (mio < 0)
+ return mio;
+
+ /* get the pin set */
+ ret = strict_strtoul(buf, 10, &pin_set);
+ if (ret || pin_set >= mio_periphs[mio].max_sets) {
+ dev_err(dev, "Invalid pinset\n");
+ return -EINVAL;
+ }
+
+ /* store the pin set */
+ active_pinset[mio] = pin_set;
+
+ dev_dbg(dev, "Pinset=%d\n", (unsigned int) pin_set);
+
+ return size;
+}
+
+static DEVICE_ATTR(pinset, 0644, NULL, xslcr_store_pinset);
+
+/**
+ * xslcr_config_mio_clock - Enable/disable the clocks for a MIO peripheral.
+ *
+ * @dev: pointer to this device.
+ * @attr: pointer to the device attribute descriptor.
+ * @buf: pointer to the buffer with user data.
+ * @size: size of the buf.
+ *
+ * This function parses the user buffer and enables/disables the clocks of a MIO
+ * peripheral specified by the user.
+ *
+ * return: negative error if invalid arguments are specified or size of the buf
+ * if the clocks are enabled/disabled successfully.
+ */
+static ssize_t xslcr_config_mio_clock(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int mio, ret;
+ unsigned long flags, en;
+
+ mio = __xslcr_get_mio_peripheral(dev);
+ if (mio < 0)
+ return mio;
+
+ ret = strict_strtoul(buf, 10, &en);
+ if (ret || en > 1) {
+ dev_err(dev, "Invalid user argument\n");
+ return -EINVAL;
+ }
+
+ /* enable/disable the clocks */
+ spin_lock_irqsave(&slcr->io_lock, flags);
+
+ if (en == 1)
+ xslcr_enable_mio_clock(mio);
+ else if (en == 0)
+ xslcr_disable_mio_clock(mio);
+
+ spin_unlock_irqrestore(&slcr->io_lock, flags);
+
+ return size;
+}
+
+static DEVICE_ATTR(clock, 0644, NULL, xslcr_config_mio_clock);
+
+/**
+ * xslcr_get_periph_status - Get the current status of a MIO peripheral.
+ *
+ * @dev: pointer to this device.
+ * @attr: pointer to the device attribute descriptor.
+ * @buf: pointer to the buffer in which pin status is returned as a str.
+ *
+ * This function returns the current status of a MIO peripheral specified by the
+ * user.
+ *
+ * return: negative error if an invalid peripheral is specified or size of
+ * the buf, with the status of the peripheral.
+ */
+static ssize_t xslcr_get_periph_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int mio = __xslcr_get_mio_peripheral(dev);
+ if (mio < 0)
+ return mio;
+
+ return sprintf(buf, "%d\n", xslcr_test_bit(periph_status, mio));
+}
+
+static DEVICE_ATTR(status, 0644, xslcr_get_periph_status, NULL);
+
+/**
+ * xslcr_reset_periph - Reset a peripheral within PS.
+ *
+ * @dev: pointer to this device.
+ * @attr: pointer to the device attribute descriptor.
+ * @buf: pointer to the buffer with user data.
+ * @size: size of the buf.
+ *
+ * This function performs a software reset on the peripheral specified by the
+ * user.
+ *
+ * return: negative error if an invalid peripheral is specified or size of the
+ * buf if the peripheral is reset successfully.
+ */
+static ssize_t xslcr_reset_periph(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ u32 reg;
+ int i, ret;
+ unsigned long flags, rst;
+
+ /* check for a valid peripheral */
+ for (i = 0; i < ARRAY_SIZE(reset_periph_name); i++) {
+ if (sysfs_streq(dev_name(dev), reset_periph_name[i]) == 1)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(reset_periph_name)) {
+ dev_err(dev, "Invalid peripheral specified\n");
+ return -EINVAL;
+ }
+
+ ret = strict_strtoul(buf, 10, &rst);
+ if (ret) {
+ dev_err(dev, "Invalid user argument\n");
+ return -EINVAL;
+ }
+
+ /* reset the peripheral */
+ spin_lock_irqsave(&slcr->io_lock, flags);
+
+ /* read the register and modify only the specified bit */
+ reg = xslcr_readreg(slcr->regs + reset_info[i].reg_offset);
+ if (!rst)
+ reg &= ~(reset_info[i].reset_mask);
+ else
+ reg |= reset_info[i].reset_mask;
+ xslcr_writereg(slcr->regs + reset_info[i].reg_offset, reg);
+
+ spin_unlock_irqrestore(&slcr->io_lock, flags);
+
+ return size;
+}
+
+static DEVICE_ATTR(reset, 0644, NULL, xslcr_reset_periph);
+
+/**
+ * show_mio_pin_status - Get the status of all the MIO pins.
+ *
+ * @dev: pointer to this device.
+ * @attr: pointer to the device attribute descriptor.
+ * @buf: pointer to the buffer in which pin status is returned as a str.
+ *
+ * This function returns overall status of the MIO pins as a 64-bit mask. Bit
+ * positions with 1 indicate that the corresponding MIO pin has been assigned to
+ * a peripheral and bit positions with 0 indicate that the pin is free.
+ *
+ * return: length of the buffer containing the mio pin status.
+ */
+static ssize_t show_mio_pin_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u32 reg;
+ u64 pin_status = 0;
+ int i;
+
+ for (i = 0; i < 54; i++) {
+ /* read the MIO control register to determine if its free */
+ reg = xslcr_readreg((slcr->regs + (i * 4) +
+ XSLCR_MIO_PIN_00_OFFSET));
+ if (!(reg & XSLCR_MIO_PIN_XX_TRI_ENABLE))
+ xslcr_set_bit((u32 *)&pin_status, i);
+ }
+
+ return sprintf(buf, "0x%016Lx\n", pin_status);
+}
+
+static DEVICE_ATTR(mio_pin_status, 0644, show_mio_pin_status, NULL);
+
+/* MIO attributes */
+static const struct attribute *xslcr_mio_attrs[] = {
+ &dev_attr_enable_pinset.attr,
+ &dev_attr_pinset.attr,
+ &dev_attr_clock.attr,
+ &dev_attr_status.attr,
+ NULL,
+};
+
+static const struct attribute_group xslcr_mio_attr_group = {
+ .attrs = (struct attribute **) xslcr_mio_attrs,
+};
+
+/* MIO class */
+static struct class xslcr_mio_class = {
+ .name = "xslcr_mio",
+ .owner = THIS_MODULE,
+};
+
+/* Reset class */
+static struct class xslcr_reset_class = {
+ .name = "xslcr_reset",
+ .owner = THIS_MODULE,
+};
+
+/**
+ * match_dev - Match function for finding a device
+ *
+ * @dev: Device to find.
+ * @data: Device private data used for finding the device.
+ */
+static inline int match_dev(struct device *dev, void *data)
+{
+ return dev_get_drvdata(dev) == data;
+}
+
+/**
+ * xslcr_create_devices - Create devices and their sysfs files.
+ *
+ * @dev: pointer to the platform device structure.
+ * @xslcr_class:pointer to the class that the devices should be registered to.
+ * @buf: pointer to the array of device names.
+ * @nr: number of devices that should be created.
+ *
+ * This function creates devices for MIO peripherals or reset peripherals and
+ * registers them to their respective classes. It also creates sysfs files for
+ * each of these devices.
+ *
+ * return: 0 if all the devices and sysfs files are created successfully.
+ * negative error if the devices or their sysfs files can't be
+ * created.
+ */
+static int xslcr_create_devices(struct platform_device *pdev,
+ struct class *xslcr_class,
+ const char **periph, int nr)
+{
+ int i, ret;
+
+ for (i = 0; i < nr; i++) {
+ struct device *dev;
+
+ dev = device_create(xslcr_class, &pdev->dev, MKDEV(0, 0),
+ (void *)(periph[i]), periph[i], i);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+
+ dev_set_drvdata(dev, (void *) periph[i]);
+
+ if (xslcr_class == &xslcr_mio_class)
+ ret = sysfs_create_group(&dev->kobj,
+ &xslcr_mio_attr_group);
+ else
+ ret = device_create_file(dev, &dev_attr_reset);
+
+ if (ret != 0) {
+ device_unregister(dev);
+ dev_err(dev, "Failed to create sysfs attrs\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * xslcr_remove_devices - Remove devices and their sysfs files.
+ *
+ * @dev: pointer to the platform device structure.
+ * @xslcr_class:pointer to the class that the devices should be registered to.
+ * @buf: pointer to the array of device names.
+ * @nr: number of devices that should be created.
+ *
+ * This function removes devices and sysfs files created by xslcr_create_devices
+ * It also unregisters the class to which these devices were registered to.
+ *
+ * return: 0 if all the devices and sysfs files are removed successfully.
+ * negative error if the devices or their sysfs files can't be
+ * removed.
+ */
+static void xslcr_remove_devices(struct class *xslcr_class,
+ const char **periph, int nr)
+{
+ int i;
+
+ for (i = 0; i < nr; i++) {
+ struct device *dev;
+
+ dev = class_find_device(xslcr_class, NULL, (void *) periph[i],
+ match_dev);
+ if (dev) {
+ if (xslcr_class == &xslcr_mio_class) {
+ sysfs_remove_group(&dev->kobj,
+ &xslcr_mio_attr_group);
+ } else {
+ device_remove_file(dev, &dev_attr_reset);
+ }
+
+ put_device(dev);
+ device_unregister(dev);
+ }
+ }
+
+ class_unregister(xslcr_class);
+}
+
+/**
+ * xslcr_get_mio_status - Initialize periph_status
+ *
+ * Read all the MIO control registers and determine which MIO peripherals are
+ * enabled and initialize the global array .
+ */
+static void xslcr_get_mio_status(void)
+{
+ u32 mio_reg;
+ int i, j, k;
+ const struct xslcr_mio *mio_ptr;
+
+ for (i = 0; i < XSLCR_MIO_MAX_PIN; ) {
+ mio_reg = xslcr_readreg(slcr->regs + (i * 4) +
+ XSLCR_MIO_PIN_00_OFFSET);
+ if (mio_reg & XSLCR_MIO_PIN_XX_TRI_ENABLE) {
+ i++;
+ continue;
+ }
+
+ mio_reg &= XSLCR_MIO_LMASK;
+
+ for (j = 0; j < ARRAY_SIZE(mio_periphs); j++) {
+ if (mio_reg == mio_periphs[j].enable_val) {
+ mio_ptr = &mio_periphs[j];
+
+ for (k = 0; k < mio_ptr->max_sets; k++) {
+ if (i == mio_ptr->set_pins[k]) {
+ /* mark the periph as enabled */
+ xslcr_set_bit(periph_status, j);
+ active_pinset[j] = k;
+ i += mio_ptr->numpins;
+ goto next_periph;
+ }
+ }
+ }
+ }
+
+ /* Noone claims this pin */
+ printk(KERN_INFO "MIO pin %2d not assigned(%08x)\n", i,
+ xslcr_readreg(slcr->regs + (i * 4) +
+ XSLCR_MIO_PIN_00_OFFSET));
+ i++;
+next_periph:
+ continue;
+ }
+}
+
+/**
+ * xslcr_probe - Probe call for the device.
+ *
+ * @pdev: handle to the platform device structure.
+ *
+ * This fucntion allocates resources for the SLCR device and creates sysfs
+ * attributes for the functionality available in the SLCR block. User can
+ * write to these sysfs files to enable/diable mio peripherals/cocks, reset
+ * peripherals, etc.
+ *
+ * Return: 0 on success, negative error otherwise.
+ */
+static int __init xslcr_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource res;
+
+ res.start = 0xF8000000;
+ res.end = 0xF8000FFF;
+
+ if (slcr) {
+ dev_err(&pdev->dev, "Device Busy, only 1 slcr instance "
+ "supported.\n");
+ return -EBUSY;
+ }
+
+ if (!request_mem_region(res.start, res.end - res.start + 1,
+ DRIVER_NAME)) {
+ dev_err(&pdev->dev, "Couldn't lock memory region at %Lx\n",
+ (unsigned long long) res.start);
+ return -EBUSY;
+ }
+
+ slcr = kzalloc(sizeof(*slcr), GFP_KERNEL);
+ if (!slcr) {
+ dev_err(&pdev->dev, "Unable to allocate memory for driver "
+ "data\n");
+ ret = -ENOMEM;
+ goto err_release;
+ }
+
+ slcr->regs = ioremap(res.start, res.end - res.start + 1);
+ if (!slcr->regs) {
+ dev_err(&pdev->dev, "Unable to map I/O memory\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ /* init periph_status based on the data from MIO control registers */
+ xslcr_get_mio_status();
+
+ spin_lock_init(&slcr->io_lock);
+
+ ret = class_register(&xslcr_mio_class);
+ if (ret < 0)
+ goto err_iounmap;
+
+ ret = xslcr_create_devices(pdev, &xslcr_mio_class, mio_periph_name,
+ ARRAY_SIZE(mio_periph_name));
+ if (ret)
+ goto err_mio_class;
+
+ ret = class_register(&xslcr_reset_class);
+ if (ret < 0)
+ goto err_mio_class;
+
+ ret = xslcr_create_devices(pdev, &xslcr_reset_class, reset_periph_name,
+ ARRAY_SIZE(reset_periph_name));
+ if (ret)
+ goto err_rst_class;
+
+ ret = device_create_file(&pdev->dev, &dev_attr_mio_pin_status);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to create sysfs attr\n");
+ goto err_rst_class;
+ }
+
+ /* unlock the SLCR so that registers can be changed */
+ xslcr_writereg(slcr->regs + XSLCR_UNLOCK, 0xDF0D);
+
+ dev_info(&pdev->dev, "at 0x%08X mapped to 0x%08X\n", res.start,
+ (u32 __force)slcr->regs);
+
+ platform_set_drvdata(pdev, slcr);
+
+ return 0;
+
+err_rst_class:
+ xslcr_remove_devices(&xslcr_reset_class, reset_periph_name,
+ ARRAY_SIZE(reset_periph_name));
+err_mio_class:
+ xslcr_remove_devices(&xslcr_mio_class, mio_periph_name,
+ ARRAY_SIZE(mio_periph_name));
+err_iounmap:
+ iounmap(slcr->regs);
+err_free:
+ kfree(slcr);
+err_release:
+ release_mem_region(res.start, res.end - res.start + 1);
+ return ret;
+}
+
+/**
+ * xslcr_remove - Remove call for the device.
+ *
+ * @pdev: handle to the platform device structure.
+ *
+ * Unregister the device after releasing the resources.
+ * Returns 0 on success, otherwise negative error.
+ */
+static int __devexit xslcr_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct xslcr *id = platform_get_drvdata(pdev);
+
+ device_remove_file(&pdev->dev, &dev_attr_mio_pin_status);
+
+ xslcr_remove_devices(&xslcr_reset_class, reset_periph_name,
+ ARRAY_SIZE(reset_periph_name));
+ xslcr_remove_devices(&xslcr_mio_class, mio_periph_name,
+ ARRAY_SIZE(mio_periph_name));
+
+ iounmap(id->regs);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to locate mmio resource\n");
+ return -ENODEV;
+ }
+
+ release_mem_region(res->start, resource_size(res));
+
+ kfree(id);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver xslcr_driver = {
+ .probe = xslcr_probe,
+ .remove = __devexit_p(xslcr_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+struct platform_device xslcr_device = {
+ .name = "xslcr",
+ .dev.platform_data = NULL,
+};
+
+static int __init xslcr_init(void)
+{
+ int ret;
+
+ ret = platform_device_register(&xslcr_device);
+ if (ret < 0)
+ return ret;
+
+ ret = platform_driver_register(&xslcr_driver);
+ if (ret < 0 ) {
+ platform_device_unregister(&xslcr_device);
+ return ret;
+ }
+
+ return 0;
+}
+arch_initcall(xslcr_init);
+
+static void __exit xslcr_exit(void)
+{
+ platform_driver_unregister(&xslcr_driver);
+ platform_device_unregister(&xslcr_device);
+}
^ permalink raw reply related
* [PATCH v2 1/5] ARM: zynq: dts: split up device tree
From: Josh Cartwright @ 2012-10-31 18:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352400580.git.josh.cartwright@ni.com>
The purpose of the created zynq-7000.dtsi file is to describe the
hardware common to all Zynq 7000-based boards. Also, get rid of the
zynq-ep107 device tree, since it is not hardware anyone can purchase.
Add a zc702 dts file based on the zynq-7000.dtsi. Add it to the
dts/Makefile so it is built with the 'dtbs' target.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/boot/dts/Makefile | 1 +
.../boot/dts/{zynq-ep107.dts => zynq-7000.dtsi} | 19 +++-----------
arch/arm/boot/dts/zynq-zc702.dts | 30 ++++++++++++++++++++++
arch/arm/mach-zynq/common.c | 3 ++-
4 files changed, 36 insertions(+), 17 deletions(-)
rename arch/arm/boot/dts/{zynq-ep107.dts => zynq-7000.dtsi} (79%)
create mode 100644 arch/arm/boot/dts/zynq-zc702.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index f37cf9f..76ed11e 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -103,5 +103,6 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
wm8505-ref.dtb \
wm8650-mid.dtb
+dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb
endif
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-7000.dtsi
similarity index 79%
rename from arch/arm/boot/dts/zynq-ep107.dts
rename to arch/arm/boot/dts/zynq-7000.dtsi
index 5caf100..8b30e59 100644
--- a/arch/arm/boot/dts/zynq-ep107.dts
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -10,29 +10,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+/include/ "skeleton.dtsi"
-/dts-v1/;
/ {
- model = "Xilinx Zynq EP107";
- compatible = "xlnx,zynq-ep107";
- #address-cells = <1>;
- #size-cells = <1>;
- interrupt-parent = <&intc>;
-
- memory {
- device_type = "memory";
- reg = <0x0 0x10000000>;
- };
-
- chosen {
- bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
- linux,stdout-path = &uart0;
- };
+ compatible = "xlnx,zynq-7000";
amba {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
+ interrupt-parent = <&intc>;
ranges;
intc: interrupt-controller at f8f01000 {
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
new file mode 100644
index 0000000..e25a307
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 Xilinx
+ * Copyright (C) 2012 National Instruments Corp.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+ model = "Zynq ZC702 Development Board";
+ compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyPS1,115200 earlyprintk";
+ };
+
+};
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index f0eef84..5441323 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -115,7 +115,8 @@ static void __init xilinx_map_io(void)
}
static const char *xilinx_dt_match[] = {
- "xlnx,zynq-ep107",
+ "xlnx,zynq-zc702",
+ "xlnx,zynq-7000",
NULL
};
--
1.8.0
^ permalink raw reply related
* [PATCH 4/8] ARM: zynq: dts: split up device tree
From: Josh Cartwright @ 2012-10-31 18:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351721190.git.josh.cartwright@ni.com>
The purpose of the created zynq-7000.dtsi file is to describe the
hardware common to all Zynq 7000-based boards. Also, get rid of the
zynq-ep107 device tree, since it is not hardware anyone can purchase.
Add a zc702 dts file based on the zynq-7000.dtsi. Add it to the
dts/Makefile so it is built with the 'dtbs' target.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/boot/dts/Makefile | 1 +
.../boot/dts/{zynq-ep107.dts => zynq-7000.dtsi} | 19 +++-----------
arch/arm/boot/dts/zynq-zc702.dts | 30 ++++++++++++++++++++++
arch/arm/mach-zynq/common.c | 3 ++-
4 files changed, 36 insertions(+), 17 deletions(-)
rename arch/arm/boot/dts/{zynq-ep107.dts => zynq-7000.dtsi} (79%)
create mode 100644 arch/arm/boot/dts/zynq-zc702.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index f37cf9f..76ed11e 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -103,5 +103,6 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
wm8505-ref.dtb \
wm8650-mid.dtb
+dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb
endif
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-7000.dtsi
similarity index 79%
rename from arch/arm/boot/dts/zynq-ep107.dts
rename to arch/arm/boot/dts/zynq-7000.dtsi
index 5caf100..8b30e59 100644
--- a/arch/arm/boot/dts/zynq-ep107.dts
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -10,29 +10,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+/include/ "skeleton.dtsi"
-/dts-v1/;
/ {
- model = "Xilinx Zynq EP107";
- compatible = "xlnx,zynq-ep107";
- #address-cells = <1>;
- #size-cells = <1>;
- interrupt-parent = <&intc>;
-
- memory {
- device_type = "memory";
- reg = <0x0 0x10000000>;
- };
-
- chosen {
- bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
- linux,stdout-path = &uart0;
- };
+ compatible = "xlnx,zynq-7000";
amba {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
+ interrupt-parent = <&intc>;
ranges;
intc: interrupt-controller at f8f01000 {
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
new file mode 100644
index 0000000..e25a307
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 Xilinx
+ * Copyright (C) 2012 National Instruments Corp.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+ model = "Zynq ZC702 Development Board";
+ compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyPS1,115200 earlyprintk";
+ };
+
+};
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 0279ea7..447904b 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -115,7 +115,8 @@ static void __init xilinx_map_io(void)
}
static const char *xilinx_dt_match[] = {
- "xlnx,zynq-ep107",
+ "xlnx,zynq-zc702",
+ "xlnx,zynq-7000",
NULL
};
--
1.8.0
^ permalink raw reply related
* [PATCH 1/2] ARM: OMAP2+: move mailbox.h out of plat-omap headers
From: Tony Lindgren @ 2012-10-31 18:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5090E515.9050407@st.com>
* Loic PALLARDY <loic.pallardy@st.com> [121031 01:48]:
>
> Hi Omar,
>
> On 10/31/2012 08:22 AM, Omar Ramirez Luna wrote:
> >
> > As part of plat-omap code cleanup, I was planning to move omap-mailbox
> > framework to a newly drivers/mailbox folder, right now this code is
> > specific to OMAP platforms, but with some clean up it could be the
> > base for a generic framework. And living under drivers/mailbox could
> > give it some exposure for interested developers to give feedback and
> > propose changes.
> >
> > In the past there was a mailbox-like driver in mach-ux500, I was
> > hoping both could live under the same folder, however the platform
> > using it, was dropped a couple of kernel releases back and with it the
> > other similar mailbox implementation.
>
> On STE side, we are working on a mailbox driver which will rely on
> mailbox framework.
> However some modifications in current Omap mailbox framework are needed
> to fit STE HW specificities.
> - API naming should be generic (replace omap prefix by mailbox)
> - message type should be enhanced
> - fifo mechanism is linked to Omap maibox, not needed in STE case since
> it relies on cross interrupt + shared memory
> I already have modifications I'll send you to see how we can create a
> common and generic mailbox framework.
OK cool. How about Omar first posts the fixed minimal patches
to move things to live under drivers so can fix up omap for
ARCH_MULTIPLATFORM?
I can then put just those into an immutable branch that people
can pull in as needed, and you guys can continue from there with
the common mailbox framework (and I can continue work on the
core omap code independently of the mailbox framwork work).
Regards,
Tony
^ permalink raw reply
* [PATCH v3] Add device tree file for the armadeus apf27
From: Philippe Reynes @ 2012-10-31 17:56 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Philippe Reynes <tremyfr@yahoo.fr>
Signed-off-by: Eric Jarrige <eric.jarrige@armadeus.org>
---
v3: set 26M clock to 0 (not used)
v2: avoid enable again the watchdog
arch/arm/boot/dts/imx27-apf27.dts | 92 +++++++++++++++++++++++++++++++++++++
1 files changed, 92 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/imx27-apf27.dts
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
new file mode 100644
index 0000000..bf07d8d
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-apf27.dts
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 Philippe Reynes <tremyfr@yahoo.fr>
+ * Copyright 2012 Armadeus Systems <support@armadeus.com>
+ *
+ * Based on code which is: Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx27.dtsi"
+
+/ {
+ model = "Armadeus apf27";
+ compatible = "armadeus,imx27-apf27", "fsl,imx27";
+
+ memory {
+ reg = <0xa0000000 0x04000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ osc26m {
+ compatible = "fsl,imx-osc26m", "fixed-clock";
+ clock-frequency = <0>;
+ };
+ };
+
+ soc {
+ aipi at 10000000 {
+ serial at 1000a000 {
+ status = "okay";
+ };
+
+ ethernet at 1002b000 {
+ status = "okay";
+ };
+
+ };
+
+ nand at d8000000 {
+ status = "okay";
+ nand-bus-width = <16>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+
+ partition at 0 {
+ label = "u-boot";
+ reg = <0x0 0x100000>;
+ };
+
+ partition at 100000 {
+ label = "env";
+ reg = <0x100000 0x80000>;
+ };
+
+ partition at 180000 {
+ label = "env2";
+ reg = <0x180000 0x80000>;
+ };
+
+ partition at 200000 {
+ label = "firmware";
+ reg = <0x200000 0x80000>;
+ };
+
+ partition at 280000 {
+ label = "dtb";
+ reg = <0x280000 0x80000>;
+ };
+
+ partition at 300000 {
+ label = "kernel";
+ reg = <0x300000 0x500000>;
+ };
+
+ partition at 800000 {
+ label = "rootfs";
+ reg = <0x800000 0xf800000>;
+ };
+ };
+
+ };
+
+};
--
1.7.4.4
^ permalink raw reply related
* [PATCH RESEND 1/5 v6] gpio: Add a block GPIO API to gpiolib
From: Roland Stigge @ 2012-10-31 17:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdbpxR8hQ13R43T1X9be95rJNMdgNPXfT3bQOO_dZU4Fkg@mail.gmail.com>
Hi Linus,
thanks for your notes, comments below:
On 10/31/2012 03:06 PM, Linus Walleij wrote:
>> +struct gpio_block *gpio_block_create(unsigned *gpios, size_t size,
>> + const char *name)
>> +{
>> + struct gpio_block *block;
>> + struct gpio_block_chip *gbc;
>> + struct gpio_remap *remap;
>> + void *tmp;
>> + int i;
>> +
>> + if (size < 1 || size > sizeof(unsigned long) * 8)
>> + return ERR_PTR(-EINVAL);
>
> If the most GPIOs in a block is BITS_PER_LONG, why is the
> latter clause not size > BITS_PER_LONG?
Good catch, thanks! :-)
>> + for (i = 0; i < size; i++)
>> + if (!gpio_is_valid(gpios[i]))
>> + return ERR_PTR(-EINVAL);
>> +
>> + block = kzalloc(sizeof(struct gpio_block), GFP_KERNEL);
>> + if (!block)
>> + return ERR_PTR(-ENOMEM);
>
> If these were instead glued to a struct device you could do
> devm_kzalloc() here and have it garbage collected.
Good, will do.
> This is why
> https://blueprints.launchpad.net/linux-linaro/+spec/gpiochip-to-dev
> needs to happen. (Sorry for hyperlinking.)
>
>> + block->name = name;
>> + block->ngpio = size;
>> + block->gpio = kzalloc(sizeof(*block->gpio) * size, GFP_KERNEL);
>> + if (!block->gpio)
>> + goto err1;
>> +
>> + memcpy(block->gpio, gpios, sizeof(*block->gpio) * size);
>> +
>> + for (i = 0; i < size; i++) {
>> + struct gpio_chip *gc = gpio_to_chip(gpios[i]);
>> + int bit = gpios[i] - gc->base;
>> + int index = gpio_block_chip_index(block, gc);
>> +
>> + if (index < 0) {
>> + block->nchip++;
>> + tmp = krealloc(block->gbc,
>> + sizeof(struct gpio_block_chip) *
>> + block->nchip, GFP_KERNEL);
>
> Don't do this dynamic array business. Use a linked list instead.
OK, I checked the important spots where access to the two lists (gbc and
remap) happen (set and get functions), and the access is always
sequential, monotonic. So will use lists. Thanks.
> [...]
> /*
> * Maybe I'm a bit picky on comment style but I prefer
> * that the first line of a multi-line comment is blank.
> * Applies everywhere.
> */
As noted earlier in the discussion, current gpiolib.c's convention is
done first-line-not-blank. So I sticked to this (un)convention. But can
change this - you are not the first one pointing this out. :-)
>> + if (!tmp) {
>> + kfree(gbc->remap);
>> + goto err3;
>> + }
>> + gbc->remap = tmp;
>> + remap = &gbc->remap[gbc->nremap - 1];
>> + remap->offset = bit - i;
>> + remap->mask = 0;
>> + }
>> +
>> + /* represents the mask necessary for bit reordering between
>> + * gpio_block (i.e. as specified on gpio_block_get() and
>> + * gpio_block_set()) and gpio_chip domain (i.e. as specified on
>> + * the driver's .set_block() and .get_block())
>> + */
>> + remap->mask |= BIT(i);
>> + }
>> +
>> + return block;
>> +err3:
>> + for (i = 0; i < block->nchip - 1; i++)
>> + kfree(block->gbc[i].remap);
>> + kfree(block->gbc);
>> +err2:
>> + kfree(block->gpio);
>> +err1:
>> + kfree(block);
>> + return ERR_PTR(-ENOMEM);
>> +}
>> +EXPORT_SYMBOL_GPL(gpio_block_create);
>> +
>> +void gpio_block_free(struct gpio_block *block)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < block->nchip; i++)
>> + kfree(block->gbc[i].remap);
>> + kfree(block->gpio);
>> + kfree(block->gbc);
>> + kfree(block);
>> +}
>> +EXPORT_SYMBOL_GPL(gpio_block_free);
>
> So if we only had a real struct device inside the gpiochip all
> this boilerplate would go away, as devm_* take care of releasing
> the resources.
Right. I guess you mean struct gpio_block here which should have a dev?
(Having gpiochip as a dev also would be best, though.) :-)
We need a separate dev for struct gpio_block, since those can be defined
dynamically (i.e. often) during the lifespan of gpio and gpiochip, so
garbage collection would be deferred for too long.
Thanks,
Roland
^ permalink raw reply
* [PATCH v2 2/5] ARM: gic: remove direct use of gic_raise_softirq
From: viresh kumar @ 2012-10-31 17:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351695517-5636-3-git-send-email-robherring2@gmail.com>
On Wed, Oct 31, 2012 at 8:28 PM, Rob Herring <robherring2@gmail.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> In preparation of moving gic code to drivers/irqchip, remove the direct
> platform dependencies on gic_raise_softirq. Move the setup of
> smp_cross_call into the gic code. Now that all platforms are using IPI#0
> for core wakeup, create a common wakeup ipi function.
>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: David Brown <davidb@codeaurora.org>
> Cc: Daniel Walker <dwalker@fifo99.com>
> Cc: Bryan Huntsman <bryanh@codeaurora.org>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Paul Mundt <lethal@linux-sh.org>
> Cc: Magnus Damm <magnus.damm@gmail.com>
> Cc: Viresh Kumar <viresh.linux@gmail.com>
> Cc: Shiraz Hashim <shiraz.hashim@st.com>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> Cc: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> ---
> arch/arm/common/gic.c | 45 +++++++++++++++++++----------------
> arch/arm/include/asm/hardware/gic.h | 1 -
> arch/arm/include/asm/smp.h | 1 +
> arch/arm/kernel/smp.c | 5 ++++
> arch/arm/mach-exynos/platsmp.c | 4 +---
> arch/arm/mach-highbank/platsmp.c | 4 +---
> arch/arm/mach-imx/platsmp.c | 2 --
> arch/arm/mach-msm/platsmp.c | 4 +---
> arch/arm/mach-omap2/omap-smp.c | 4 +---
> arch/arm/mach-realview/platsmp.c | 2 --
> arch/arm/mach-shmobile/platsmp.c | 2 --
> arch/arm/mach-shmobile/smp-emev2.c | 2 +-
> arch/arm/mach-spear13xx/platsmp.c | 2 --
For SPEAr:
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
^ permalink raw reply
* [PATCH V4 3/4] ARM: tegra: dts: cardhu: enable SLINK4
From: Laxman Dewangan @ 2012-10-31 17:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50915563.40904@wwwdotorg.org>
On Wednesday 31 October 2012 10:14 PM, Stephen Warren wrote:
> On 10/31/2012 03:02 AM, Laxman Dewangan wrote:
>> Enable SLINK4 and connected device in Tegra30 based
>> platform Cardhu.
>> Setting maximum spi frequency to 25MHz.
>>
>> Spi serial flash is connected on CS1 of SLINK4 on
>> cardhu platform.
>> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
>> +winbond Winbond Electronics corp.
> That should really be a separate patch that goes through the devicetree
> branch. But I guess it's fairly trivial, so it's not a big deal.
>
Yes, I thought that it should be in separate change. I did same on
earlier for ISL29028 driver and found that this small change still not
get merged. Therefore I clubbed this together as it can go without any
issue.
I believe it is fine to merge vendor-prefix from any tree.
>
>> + spi-flash at 1 {
>> + compatible = "winbond,w25q32";
>> + spi-max-frequency =<20000000>;
>> + reg =<1>;
>> + };
> Since I have an Atmel flash on my board, I see:
>
> [ 1.282958] m25p80 spi32766.1: found at25df321a, expected w25q32
> [ 1.289103] m25p80 spi32766.1: at25df321a (4096 Kbytes)
>
> Is there any way around that (the first log line above)?
>
> I suppose the answer is that the DT should reflect the exact flash
> device that's on the board, and perhaps the bootloader should be
> adjusting the DT to reflect the correct value. That's probably complex.
>
> Do you have any idea whether Atmel or Winbond flash is more common, so
> we can at least minimize the number of times this message appears?
I observe that most of cardhu have the winbond. All SQA machine has
winbond. Also I believe on A04, it is winbond.
Better to go with winbond.
^ permalink raw reply
* [PATCH] ARM: mxs: Add support for the Armadeus Systems APF28Dev docking board
From: Gwenhael Goavec-Merou @ 2012-10-31 17:39 UTC (permalink / raw)
To: linux-arm-kernel
The APF28Dev is a docking board for an APF28 SOM
Signed-off-by: Gwenhael Goavec-Merou <gwenhael.goavec-merou@armadeus.com>
Signed-off-by: Julien Boibessot <julien.boibessot@armadeus.com>
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/imx28-apf28dev.dts | 92 ++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/imx28-apf28dev.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 9bca96f..b451a79 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -55,6 +55,7 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
imx23-olinuxino.dtb \
imx23-stmp378x_devb.dtb \
imx28-apf28.dtb \
+ imx28-apf28dev.dtb \
imx28-apx4devkit.dtb \
imx28-cfa10036.dtb \
imx28-cfa10049.dtb \
diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
new file mode 100644
index 0000000..dde09d4
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 Armadeus Systems - <support@armadeus.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* APF28Dev is a docking board for the APF28 SOM */
+/include/ "imx28-apf28.dts"
+
+/ {
+ model = "Armadeus Systems APF28Dev docking/development board";
+ compatible = "armadeus,imx28-apf28dev", "armadeus,imx28-apf28", "fsl,imx28";
+
+ apb at 80000000 {
+ apbh at 80000000 {
+ ssp0: ssp at 80010000 {
+ compatible = "fsl,imx28-mmc";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_4bit_pins_a
+ &mmc0_cd_cfg &mmc0_sck_cfg>;
+ bus-width = <4>;
+ status = "okay";
+ };
+ };
+
+ apbx at 80040000 {
+ lradc at 80050000 {
+ status = "okay";
+ };
+
+ pwm: pwm at 80064000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_pins_a &pwm4_pins_a>;
+ status = "okay";
+ };
+
+ usbphy0: usbphy at 8007c000 {
+ status = "okay";
+ };
+
+ usbphy1: usbphy at 8007e000 {
+ status = "okay";
+ };
+ };
+ };
+
+ ahb at 80080000 {
+ usb0: usb at 80080000 {
+ vbus-supply = <®_usb0_vbus>;
+ status = "okay";
+ };
+
+ usb1: usb at 80090000 {
+ status = "okay";
+ };
+
+ mac1: ethernet at 800f4000 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac1_pins_a>;
+ phy-reset-gpios = <&gpio0 23 0>;
+ status = "okay";
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_usb0_vbus: usb0_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb0_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 23 1>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ user {
+ label = "Heartbeat";
+ gpios = <&gpio0 21 0>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
--
1.7.8.6
^ permalink raw reply related
* [PATCH] ARM i.MX27: Fix low reference clock path
From: trem @ 2012-10-31 17:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351668533-32712-1-git-send-email-s.hauer@pengutronix.de>
On 31/10/12 08:28, Sascha Hauer wrote:
> The i.MX27 clock tree can either be driven from a 26MHz oscillator
> or from a 32768Hz oscillator. The latter was not properly implemented,
> the mux between these two pathes was missing. Add this mux and while
> at it rename the 'prem' (premultiplier) clk to 'fpm' (Frequency
> Pre-Multiplier) to better match the datasheet.
>
> Signed-off-by: Sascha Hauer<s.hauer@pengutronix.de>
Tested-by: Philippe Reynes <tremyfr@yahoo.fr>
> ---
> arch/arm/mach-imx/clk-imx27.c | 17 ++++++++++++++---
> 1 file changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
> index 3b6b640..f8d9129 100644
> --- a/arch/arm/mach-imx/clk-imx27.c
> +++ b/arch/arm/mach-imx/clk-imx27.c
> @@ -51,8 +51,10 @@
>
> static const char *vpu_sel_clks[] = { "spll", "mpll_main2", };
> static const char *cpu_sel_clks[] = { "mpll_main2", "mpll", };
> +static const char *mpll_sel_clks[] = { "fpm", "mpll_osc_sel", };
> +static const char *mpll_osc_sel_clks[] = { "ckih", "ckih_div1p5", };
> static const char *clko_sel_clks[] = {
> - "ckil", "prem", "ckih", "ckih",
> + "ckil", "fpm", "ckih", "ckih",
> "ckih", "mpll", "spll", "cpu_div",
> "ahb", "ipg", "per1_div", "per2_div",
> "per3_div", "per4_div", "ssi1_div", "ssi2_div",
> @@ -79,7 +81,8 @@ enum mx27_clks {
> vpu_ahb_gate, fec_ahb_gate, emma_ahb_gate, emi_ahb_gate, dma_ahb_gate,
> csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
> uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
> - uart2_ipg_gate, uart1_ipg_gate, clk_max
> + uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel,
> + mpll_sel, clk_max
> };
>
> static struct clk *clk[clk_max];
> @@ -91,7 +94,15 @@ int __init mx27_clocks_init(unsigned long fref)
> clk[dummy] = imx_clk_fixed("dummy", 0);
> clk[ckih] = imx_clk_fixed("ckih", fref);
> clk[ckil] = imx_clk_fixed("ckil", 32768);
> - clk[mpll] = imx_clk_pllv1("mpll", "ckih", CCM_MPCTL0);
> + clk[fpm] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1);
> + clk[ckih_div1p5] = imx_clk_fixed_factor("ckih_div1p5", "ckih", 2, 3);
> +
> + clk[mpll_osc_sel] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1,
> + mpll_osc_sel_clks,
> + ARRAY_SIZE(mpll_osc_sel_clks));
> + clk[mpll_sel] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks,
> + ARRAY_SIZE(mpll_sel_clks));
> + clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
> clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
> clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
>
^ permalink raw reply
* [PATCH V3 0/4] ARM: tegra: Enable SLINK controller driver
From: Laxman Dewangan @ 2012-10-31 17:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50914C82.5010704@wwwdotorg.org>
On Wednesday 31 October 2012 09:36 PM, Stephen Warren wrote:
> On 10/31/2012 02:51 AM, Laxman Dewangan wrote:
>
> I had forgotten about this from when I tested the older SPI driver that
> we ripped out; I had at least compared the registers between U-Boot and
> the kernel with that driver, so I'm pretty sure I didn't make that
> mistake with the old driver.
>
> So, I'll apply your patch series, and send one to add the flash device
> to the Cardhu .dts.
Great to hear that the spi driver work for you now.
Thanks,
Laxman
^ permalink raw reply
* [PATCH V4 0/4] ARM: tegra: Enable SLINK controller driver
From: Laxman Dewangan @ 2012-10-31 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50915203.8030505@wwwdotorg.org>
On Wednesday 31 October 2012 09:59 PM, Stephen Warren wrote:
> On 10/31/2012 03:02 AM, Laxman Dewangan wrote:
>> This series modify the dts file to add the slink addresses,
>> make AUXDATA in board dt files, enable slink4 for tegra30-cardhu and
>> enable slink controller defconfig.
> I don't appear to have received patch 1/4 this time around. I'll assume
> it's identical to V3, since I don't think anything needed to change there...
Yes, it is identical to V3, no change on the 1/4.
Only change in 3/4 and 4/4. I realize later that you already applied the
2/4 yesterday.
^ permalink raw reply
* [PATCH v2] fix DEBUG_LL DCC race condition
From: Johannes Stezenbach @ 2012-10-31 17:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121031170853.GA20498@sig21.net>
Trying to boot a kernel with I- and D-caches disabled
sometimes hangs when DEBUG_LL output to DCC is enabled.
Apparently the JTAG debugger sometimes reads the
DCC register before the current busyuart implementation
could see the wDTRfull flag, thus busyuart spins in an endless loop.
The reason seems to be a misunderstanding of the purpose
of the busyuart macro. For UART, waituart should wait
until flow control allows to send the character, or do
nothing. busyuart should wait until the FIFO is empty
(all data is sent).
For DCC, busyuart should wait until the JTAG debugger has
read the DCC register (wait for wDTRfull == 0 on ARMv6), and
waituart does nothing.
Signed-off-by: Johannes Stezenbach <js@sig21.net>
---
v2:
- update description
- waituart is empty (no flow control)
diff --git a/arch/arm/include/debug/icedcc.S b/arch/arm/include/debug/icedcc.S
index 43afcb0..30e18e5 100644
--- a/arch/arm/include/debug/icedcc.S
+++ b/arch/arm/include/debug/icedcc.S
@@ -21,13 +21,6 @@
.endm
.macro busyuart, rd, rx
-1001:
- mrc p14, 0, \rx, c0, c1, 0
- tst \rx, #0x20000000
- beq 1001b
- .endm
-
- .macro waituart, rd, rx
mov \rd, #0x2000000
1001:
subs \rd, \rd, #1
@@ -38,6 +31,9 @@
1002:
.endm
+ .macro waituart, rd, rx
+ .endm
+
#elif defined(CONFIG_CPU_XSCALE)
.macro senduart, rd, rx
@@ -45,13 +41,6 @@
.endm
.macro busyuart, rd, rx
-1001:
- mrc p14, 0, \rx, c14, c0, 0
- tst \rx, #0x10000000
- beq 1001b
- .endm
-
- .macro waituart, rd, rx
mov \rd, #0x10000000
1001:
subs \rd, \rd, #1
@@ -62,6 +51,9 @@
1002:
.endm
+ .macro waituart, rd, rx
+ .endm
+
#else
.macro senduart, rd, rx
@@ -69,14 +61,6 @@
.endm
.macro busyuart, rd, rx
-1001:
- mrc p14, 0, \rx, c0, c0, 0
- tst \rx, #2
- beq 1001b
-
- .endm
-
- .macro waituart, rd, rx
mov \rd, #0x2000000
1001:
subs \rd, \rd, #1
@@ -87,4 +71,7 @@
1002:
.endm
+ .macro waituart, rd, rx
+ .endm
+
#endif /* CONFIG_CPU_V6 */
^ permalink raw reply related
* [PATCH RESEND 1/5 v6] gpio: Add a block GPIO API to gpiolib
From: Roland Stigge @ 2012-10-31 17:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACxGe6vgryMPygc8SKFLKqP8Wq=pcGiJe_dPCiDC-evzf32UMA@mail.gmail.com>
Hi Grant,
thank you for your feedback!
Notes below.
On 10/31/2012 04:00 PM, Grant Likely wrote:
> Linus and I just sat down and talked about your changes. I think I
> understand what you need to do, but I've got concerns about the
> approach. I'm already not a big fan of the sysfs gpio interface
> design*, so you can understand that I'm not keen to extend the
> interface further. At the very least, I want to be really careful
> about the form that the extension takes.
>
> First off, thank you for writing good documentation. That makes it a
> lot easier to understand how the series is intended to be used, and I
> really appreciate it.
>
> For the API, I don't think it is a good idea at all to try and
> abstract away gpios on multiple controllers. I understand that it
> makes life a lot easier for userspace to abstract those details away,
> but the problem is that it hides very important information about how
> the system is actually constructed that is important to actually get
> things to work. For example, say you have a gpio-connected device with
> the constraint that GPIOA must change either before or at the same
> time as GPIOB, but never after. If those GPIOs are on separate
> controllers, then the order is completely undefined
It is correct that it's not (yet) well documented and the API is also
not very explicit about it, but the actual approach of the manipulation
order is to let drivers handle gpios "as simultaneous as possible" and
when not possible, do it in the _order of bits specified_ (either
defined at the device tree level, or when created via
block_gpio_create() directly).
I consider it a good thing to abstract things away if possible here, if
it is well documented what actually happens, which info should be
available from the definition and the possibilities of the drivers and
hardware actually used (the optional block gpio interface must be well
implemented in the respective driver, and when combining multiple gpio
controller chips, it should be clear that certain realtime timings on a
resulting virtual n-bit bus are not possible.)
> Second, the API appears a little naive in the way it approaches
> changing values. It makes the assumption that every gpio in the block
> will be written at the same time, which doesn't take into account that
> even within a block it is highly likely that only a subset of the
> gpios need to be manipulated. A lot of GPIO controllers implement
> separate 'set' and 'clear' registers for exactly this reason. The API
> needs to allow users to choose a subset for manipulation. The ABI
> needs to either have separate 'set' and 'clear' operations, or
> operations need to have both mask and value arguments. Similarly, how
> do users manipulate pin direction with this ABI?
I'm not sure how far you tested the API in depth: You can already define
a block that maps onto a subset of gpios on a controller and internally
of course maps onto those set and clear operations. Whenever you need to
manipulate a different subset (whether disjoint or overlapping), you can
easily define _additional_ blocks. From my experience, this solves most
of the real world problems when n-bit busses are bit banged over GPIOs.
Doesn't this already solve this (in a different way, though)?
Pin direction currently needs to be set up separately, analogous to
requesting gpios. Need to document this better, right. The assumption is
that I/O needs to be efficient primarily, before bloating the API with
direction functions. Or should I add functions for this?
As long as there is no consensus about mainlining this API, I will
maintain it further at
git://git.antcom.de/linux-2.6 blockgpio
because I need it in projects anyway. Will post updates that go in the
direction that you proposed.
Thanks!
Roland
^ permalink raw reply
* [PATCH v2 3/5] irqchip: Move ARM GIC to drivers/irqchip
From: Stephen Warren @ 2012-10-31 17:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <509146B8.2000305@gmail.com>
On 10/31/2012 09:41 AM, Rob Herring wrote:
> On 10/31/2012 10:09 AM, Russell King - ARM Linux wrote:
>> On Wed, Oct 31, 2012 at 09:58:35AM -0500, Rob Herring wrote:
>>> From: Rob Herring <rob.herring@calxeda.com>
>>>
>>> Now that we have drivers/irqchip, move GIC irqchip to drivers/irqchip. This
>>> is necessary to share the GIC with arm and arm64.
>>>
>>> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>>> Cc: Russell King <linux@arm.linux.org.uk>
>>> Cc: Thomas Gleixner <tglx@linutronix.de>
>>> ---
>>> arch/arm/common/Kconfig | 8 --------
>>> arch/arm/common/Makefile | 1 -
>>> drivers/irqchip/Kconfig | 8 ++++++++
>>> drivers/irqchip/Makefile | 1 +
>>> arch/arm/common/gic.c => drivers/irqchip/irq-gic.c | 0
>>> drivers/irqchip/irqchip.c | 10 ++++++++++
>>> drivers/irqchip/irqchip.h | 1 +
>>> 7 files changed, 20 insertions(+), 9 deletions(-)
>>> rename arch/arm/common/gic.c => drivers/irqchip/irq-gic.c (100%)
>>
>> What about its dependent arch/arm/include/asm/hardware/gic.h header,
>> which I believe after patch 1 becomes just a bunch of function calls,
>> and so no longer has any right to be in asm/hardware.
>>
>> Nothing should be moved out of arch/arm without its associated header
>> file also moving with it.
>
> What is left is only used within arch/arm and I expect we will get rid
> of the remaining users. So I didn't want to encourage any additional
> users by moving to include/linux.
>
> gic_secondary_init and gic_cascade_irq could be function ptrs.
> gic_of_init can be removed once users are converted to call irqchip_init
> instead. That leaves gic_init which are all the non-DT converted GIC
> users and will take some time to convert. I am puzzled by tegra and zynq
> which should be DT only already.
I imagine you're talking about:
/*
* Check if there is a devicetree present, since the GIC will be
* initialized elsewhere under DT.
*/
if (!of_have_populated_dt())
gic_init(0, 29, distbase,
IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
This is probably legacy code from when we weren't DT only, and I imagine
can simply be removed. There are probably other pieces of code we can go
through and remove now.
^ permalink raw reply
* [PATCH 1/8] ARM: zynq: move arm-specific sys_timer out of ttc
From: Josh Cartwright @ 2012-10-31 17:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1351721190.git.josh.cartwright@ni.com>
Move the sys_timer definition out of ttc driver and make it part of the
common zynq code. This is preparation for renaming and COMMON_CLK
support.
Signed-off-by: Josh Cartwright <josh.cartwright@ni.com>
---
arch/arm/mach-zynq/common.c | 13 +++++++++++++
arch/arm/mach-zynq/common.h | 4 +---
arch/arm/mach-zynq/timer.c | 10 +---------
3 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index ba8d14f..6f058258 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -25,6 +25,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/mach/time.h>
#include <asm/mach-types.h>
#include <asm/page.h>
#include <asm/hardware/gic.h>
@@ -93,6 +94,18 @@ static struct map_desc io_desc[] __initdata = {
};
+static void __init xilinx_zynq_timer_init(void)
+{
+ xttcpss_timer_init();
+}
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+static struct sys_timer xttcpss_sys_timer = {
+ .init = xilinx_zynq_timer_init,
+};
+
/**
* xilinx_map_io() - Create memory mappings needed for early I/O.
*/
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index a009644..954b91c 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -17,8 +17,6 @@
#ifndef __MACH_ZYNQ_COMMON_H__
#define __MACH_ZYNQ_COMMON_H__
-#include <asm/mach/time.h>
-
-extern struct sys_timer xttcpss_sys_timer;
+void __init xttcpss_timer_init(void);
#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
index c2c96cc..c93cbe5 100644
--- a/arch/arm/mach-zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -24,7 +24,6 @@
#include <linux/clockchips.h>
#include <linux/io.h>
-#include <asm/mach/time.h>
#include <mach/zynq_soc.h>
#include "common.h"
@@ -269,7 +268,7 @@ static struct clock_event_device xttcpss_clockevent = {
* Initializes the timer hardware and register the clock source and clock event
* timers with Linux kernal timer framework
**/
-static void __init xttcpss_timer_init(void)
+void __init xttcpss_timer_init(void)
{
xttcpss_timer_hardware_init();
clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
@@ -289,10 +288,3 @@ static void __init xttcpss_timer_init(void)
xttcpss_clockevent.cpumask = cpumask_of(0);
clockevents_register_device(&xttcpss_clockevent);
}
-
-/*
- * Instantiate and initialize the system timer structure
- */
-struct sys_timer xttcpss_sys_timer = {
- .init = xttcpss_timer_init,
-};
--
1.8.0
^ permalink raw reply related
* [PATCH] fix DEBUG_LL DCC race condition
From: Johannes Stezenbach @ 2012-10-31 17:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121031163615.GQ21164@n2100.arm.linux.org.uk>
On Wed, Oct 31, 2012 at 04:36:15PM +0000, Russell King - ARM Linux wrote:
> On Mon, Oct 29, 2012 at 04:18:32PM +0100, Johannes Stezenbach wrote:
> > Trying to boot a kernel with I- and D-caches disabled
> > sometimes hangs when DEBUG_LL output to DCC is enabled.
> > Apparently the JTAG debugger sometimes reads the
> > DCC register before busyuart could see the wDTRfull flag,
> > thus busyuart spins in an endless loop.
>
> This makes no sense. Why is busyuart spinning if it does _not_ see a
> full flag? busyuart is supposed to spin _if_ the UART has data to be
> sent. It's not supposed to spin if the data has been sent.
Maybe my wording didn't make it clear that the current code
spins if the data has been sent (which indeed does not
make sense). My fix changes it to spin _until_ the data has been send.
> > The reason seems to be a misunderstanding of the purpose
> > of the busyuart macro. For UART, waituart waits until
> > there is space in the FIFO, and busyuart waits until
> > the FIFO is empty (all data is sent).
> > For DCC, busyuart should be identical to waituart since
> > there is no FIFO.
>
> Not quite. waituart is supposed to check that the flow control allows
> the character to be sent _or_ it's supposed to do nothing. Look at
> the 8250 implementation debug-8250.S - this is the first implementation,
> authored by me, and therefore is the definitive implementation for this
> stuff.
OK, in the case of DCC "flow-control" would mean JTAG has
read the DCC register. So it seems correct that both
busyuart and waituart do the same: wait for empty DCC register.
But I agree that the double wait is superflous, waituart
could be changed to do nothing. This would be in line with
debug-8250.S which doesn't check for space in the FIFO
in waituart.
I'll send an updated patch.
Thanks,
Johannes
^ permalink raw reply
* [PATCH v2 5/9] document: devicetree: bind pinconf with pin-single
From: Haojian Zhuang @ 2012-10-31 16:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5085CC3F.30708@wwwdotorg.org>
On Tue, Oct 23, 2012 at 6:44 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 10/22/2012 10:08 AM, Haojian Zhuang wrote:
>> Add comments with pinconf & gpio range in the document of
>> pinctrl-single.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
>> ---
>> .../devicetree/bindings/pinctrl/pinctrl-single.txt | 52 ++++++++++++++++++++
>> arch/arm/boot/dts/pxa910.dtsi | 1 -
>> 2 files changed, 52 insertions(+), 1 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
>> index 2c81e45..6da2f13 100644
>> --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
>> +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
>> @@ -17,6 +17,36 @@ Optional properties:
>> - pinctrl-single,bit-per-mux : boolean to indicate that one register controls
>> more than one pin
>>
>> +- pinctrl-single,gpio-ranges : gpio range list
>> +
>> +- pinctrl-single,gpio : array with gpio range start, size & register
>> + offset
>> +
>> +- pinctrl-single,gpio-func : gpio function value in the pinmux register
>
> Some more explanation is needed here; some questions/comments:
>
> 1) Looking at the example, pinctrl-single,gpio-ranges is a property
> within the main pinctrl node, whereas pinctrl-single,gpio and
> pinctrl-single,gpio-func are properties within some other node. There's
> no explanation of this in the binding description itself, only in the
> example. Related to this, the documentation for
> pinctrl-single,gpio-ranges doesn't say what it's a list of; it needs to
> say that it's a list of phandles.
>
I'll add more comments.
> 2) pinctrl-single,gpio is listed as optional. Presumably it's not; every
> GPIO range node must have this property?
>
Yes, they must be included in GPIO range node. But if GPIO feature
isn't supported in the pinctrl device, pinctrl-single,gpio is still optional.
I'll add more comments on this.
> 3) Why is pinctrl-single,gpio-func optional? Presumably you always need
> to program the pinmux HW to select the GPIO function. Yet, the driver
> code in an earlier patch seems to deliberately do nothing if this
> property is missing. Shouldn't the DT parsing return an error instead?
>
pinctrl-single,gpio-func is optional for above reason.
> 4) I'm a little confused re: the data model. Is the idea that if
> pinctrl-single,gpio-ranges is specified, then the node describes a
> combined pin controller and GPIO HW? Are the pin IDs of the pin
> controller expected to match the pin IDs of the GPIO HW?
GPIO function is enabled by setting proper field in mux field of pinmux
register.
> I'm left wondering exactly which numbering space the values in
> pinctrl-single,gpio are; do they describe the pin controller IDs that
> this GPIO range describes, or do they describe the GPIO IDs that this
> range describes and attempt to map them back to pin controller IDs?
> Similarly, I'm not sure why there's a register offset here rather than
> say a pin controller pin ID number. Shouldn't the property be a list of
> <pin-controller-pin-ID GPIO-controller-GPIO-ID number-of-GPIOs>
>
Whatever it's pin ID or offset of pinmux register, they're nearly same.
We can calculate offset from pin ID, vice visa. If pin ID is more acceptable
by you and Tony, I can change it later.
>> +- pinctrl-single,power-source-mask : mask of setting power source in
>> + the pinmux register
>> +
>> +- pinctrl-single,power-source : value of setting power source field
>> + in the pinmux register
>> +
>> +- pinctrl-single,bias-mask : mask of setting bias value in the pinmux
>> + register
>> +
>> +- pinctrl-single,bias-disable : value of disabling bias in the pinmux
>> + register
>> +
>> +- pinctrl-single,bias-pull-down : value of setting bias pull down in
>> + the pinmux register
>> +
>> +- pinctrl-single,bias-pull-up : value of setting bias pull up in the
>> + pinmux register
>> +
>> +- pinctrl-single,bias : value of setting bias in the pinmux register
>> +
>> +- pinctrl-single,input-schmitt-mask : mask of setting input schmitt
>> + in the pinmux register
>
> I suppose it's OK that a generic pin controller binding would use the
> generic pin configuration config options. I'm still not convinced that
> the semantics of generic pin control make sense. Maybe if they're just
> arbitrary names for SoC-specific things it's fine though.
>
> Do these patches expose /all/ generic pin configuration options? It
> doesn't seem worth exposing only some of them and ignoring others.
>
I believe general pinconf can't support all cases in different silicons.
And we still have some common features that could be covered in general
pinconf. So we need a structure to support both pinconf & specific pinconf.
>> +/* third controller instance for pins in gpio domain */
>> +pmx_gpio: pinmux at d401e000 {
>> + compatible = "pinctrl-single";
>> + reg = <0xd401e000 0x0330>;
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>
> #gpio-cells would be needed here for a GPIO controller.
>
>> diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
>
>> - pinctrl-single,gpio-mask = <7>;
>
> I assume that's a mistake; the line shouldn't be removed in this
> documentation patch?
>
Yes, this part should be included in the previous patch. I'll fix it.
^ permalink raw reply
* [RFC 7/7] capebus: Documentation; capebus-summary
From: Pantelis Antoniou @ 2012-10-31 16:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351702333-8456-1-git-send-email-panto@antoniou-consulting.com>
Small summary of capebus.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
Documentation/capebus/capebus-summary | 40 +++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 Documentation/capebus/capebus-summary
diff --git a/Documentation/capebus/capebus-summary b/Documentation/capebus/capebus-summary
new file mode 100644
index 0000000..742e33c
--- /dev/null
+++ b/Documentation/capebus/capebus-summary
@@ -0,0 +1,40 @@
+Overview of Linux kernel Capebus support
+========================================
+
+30-Oct-2012
+
+What is Capebus?
+----------------
+Capebus is an abstract concept. There's no such thing as a vanilla physical
+capebus, what is there is a concept and a method on how various capebus
+based implementations can be made.
+
+Capebus is created to address the problem of many SoCs that can provide a
+multitude of hardware interfaces but in order to keep costs down the main
+boards only support a limited number of them. The rest are typically brought
+out to pin connectors on to which other boards, named capes are connected and
+allow those peripherals to be used.
+
+These capes connect to the SoC interfaces but might also contain various other
+parts that may need some kind of driver to work.
+
+Since SoCs have limited pins and pin muxing options, not all capes can work
+together so some kind of resource tracking (at least for the pins in use) is
+required.
+
+Before capebus all of this took place in the board support file, and frankly
+for boards with too many capes it was becoming unmanageable.
+
+Capebus provides a virtual bus, which along with a board specific controller,
+cape drivers can be written using the standard Linux device model.
+
+What kind of systems/boards capebus supports?
+---------------------------------------------
+
+The core capebus infrastructure is not depended on any specific board.
+However capebus needs a board controller to provide services to the cape devices
+it controls. Services like addressing and resource reservation are provided
+by the board controller.
+
+Capebus at the moment only support TI's Beaglebone platform.
+
--
1.7.12
^ permalink raw reply related
* [RFC 6/7] capebus: Document DT bindings
From: Pantelis Antoniou @ 2012-10-31 16:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351702333-8456-1-git-send-email-panto@antoniou-consulting.com>
Describe capebus DT bindings in detail.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
.../capebus/bone-capebus-slot-override.txt | 28 +++++++
.../devicetree/bindings/capebus/bone-capebus.txt | 50 +++++++++++
.../bindings/capebus/bone-geiger-cape.txt | 78 +++++++++++++++++
.../bindings/capebus/bone-generic-cape.txt | 97 ++++++++++++++++++++++
.../devicetree/bindings/capebus/da8xx-dt.txt | 31 +++++++
.../devicetree/bindings/capebus/i2c-dt.txt | 42 ++++++++++
.../devicetree/bindings/capebus/spi-dt.txt | 37 +++++++++
.../devicetree/bindings/capebus/ti-tscadc-dt.txt | 34 ++++++++
8 files changed, 397 insertions(+)
create mode 100644 Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt
create mode 100644 Documentation/devicetree/bindings/capebus/bone-capebus.txt
create mode 100644 Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt
create mode 100644 Documentation/devicetree/bindings/capebus/bone-generic-cape.txt
create mode 100644 Documentation/devicetree/bindings/capebus/da8xx-dt.txt
create mode 100644 Documentation/devicetree/bindings/capebus/i2c-dt.txt
create mode 100644 Documentation/devicetree/bindings/capebus/spi-dt.txt
create mode 100644 Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt
diff --git a/Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt b/Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt
new file mode 100644
index 0000000..733d977
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt
@@ -0,0 +1,28 @@
+* Beagle bone capebus slot override bindings
+
+The beagle bone capebus node can have slot override nodes. These nodes describe
+ an override that will take place in the specified slot.
+ Many boards during the prototype phase don't have an EEPROM (or are even
+ wired in such a way that an eeprom cannot be added). In that case you can
+ specify an override that will make everything work as if a real EEPROM was
+ there.
+
+Required properties:
+- compatible: Override node must have the form "bone-capebus-slot-override"
+- slot: Identifies the slot# to override.
+- board-name: The cape's name as if provided by the board-name EEPROM field
+
+Optional properties:
+- version: The cape's version as if provided by the version EEPROM field.
+- manufacturer: The cape's manufacturer as if provided by the manufacturer
+ EEPROM field.
+
+Example:
+
+override at 1 {
+ compatible = "bone-capebus-slot-override";
+ slot = <1>;
+ board-name = "Adafruit 1.8 Cape";
+ version = "00A0";
+ manufacturer = "Adafruit";
+};
diff --git a/Documentation/devicetree/bindings/capebus/bone-capebus.txt b/Documentation/devicetree/bindings/capebus/bone-capebus.txt
new file mode 100644
index 0000000..6d8a08d
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/bone-capebus.txt
@@ -0,0 +1,50 @@
+* Beagle bone capebus bindings
+
+The beaglebone capebus implementation is using a single capebus
+node contained in the root node. A beaglebone cape is identified
+at by reading an EEPROM at on of 4 possible addresses on the I2C2 bus.
+
+Required properties:
+- compatible: Every beaglebone compatible capebus node shall have the
+ form "bone-capebus";
+- slots: An array of phandles pointing to the I2C node of an EEPROM that
+ contains the cape information.
+
+Optional properties:
+
+The child nodes of the capebus node can contain either cape nodes
+or override nodes. Those cape nodes are described in their respective
+binding files.
+
+- override nodes: Describe an override that will take place in the specified
+ slot. Many boards during the prototype phase don't have an EEPROM (or are even
+ wired in such a way that an eeprom cannot be added). In that case you can
+ specify an override that will make everything work as if a real EEPROM was
+ there.
+
+Override node required properties:
+- compatible: For override node must have the form "bone-capebus-slot-override"
+- slot: Identifies the slot# to override.
+- board-name: The cape's name as if provided by the board-name EEPROM field
+
+Override node optional properties:
+- version: The cape's version as if provided by the version EEPROM field.
+- manufacturer: The cape's manufacturer as if provided by the manufacturer
+ EEPROM field.
+
+Example:
+
+capebus: capebus at 0 {
+ compatible = "bone-capebus";
+
+ slots = <&cape_eeprom_0 &cape_eeprom_1 &cape_eeprom_2 &cape_eeprom_3>;
+
+ [cape-nodes]
+ [override-nodes]
+
+ bone_adafruit_cape: cape at 5 {
+ compatible = "bone-generic-cape";
+ // read the bone-generic-cape bindings for the rest
+ ...
+ };
+};
diff --git a/Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt b/Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt
new file mode 100644
index 0000000..a2ed81c
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt
@@ -0,0 +1,78 @@
+* Beagle bone geiger cape
+
+ A geiger cape is your run of the mill particle detector measuring
+ ionizing radiation. It is also the first example of how a non-generic
+ cape can be supported by capebus.
+
+ The geiger cape can not be created via instantiation of a generic cape
+ since the component need to work together.
+
+Required properties:
+- compatible: Generic cape nodes must have the form "bone-geiger-cape"
+- board-name: The cape's name as if provided by the board-name EEPROM field
+- pwms: Pointer to the PWM we require
+- pwm-names: Name of the PWM.
+- pwm-frequency: Frequency of the PWM in Hz
+- pwm-duty-cycle: Duty cycle in percent
+- event-blink-delay: Blink delay of the event led
+- gpios: GPIO on which an event is detected
+- vsense-name: Name of the analog input for vsense
+- vsense-scale: Vsense scale to convert to mVolts
+- ti-tscadc-dt compatible node for the ADC configuration
+- gpio-leds compatible node for the LED configuration
+
+Optional properties:
+
+The geiger cape supports the standard pinctrl properties.
+
+Example:
+
+bone_geiger_cape: cape at 1 {
+ compatible = "bone-geiger-cape";
+ board-name = "Geiger Cape";
+
+ /* note that these can't be versioned... */
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_geiger_cape_pins>;
+
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "bone-geiger-cape";
+
+ pwm-frequency = <20000>; /* 20KHz */
+ pwm-duty-cycle = <60>; /* 60% */
+
+ event-blink-delay = <30>; /* 30ms */
+
+ gpios = <&gpio4 17 0>; /* pulse */
+
+ vsense-name = "AIN5"; /* analog vsense */
+ vsense-scale = <37325>; /* scaling */
+
+ tscadc {
+ compatible = "ti-tscadc-dt";
+
+ ti,hwmods = "adc_tsc";
+
+ adc-channels = <8>;
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_geiger_cape_led_pins>;
+
+ geiger-led0 {
+ label = "geiger:green:usr0";
+ gpios = <&gpio3 23 0>;
+ linux,default-trigger = "geiger-run";
+ default-state = "off";
+ };
+
+ geiger-led1 {
+ label = "geiger:red:usr1";
+ gpios = <&gpio3 25 0>;
+ linux,default-trigger = "geiger-event";
+ default-state = "off";
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/capebus/bone-generic-cape.txt b/Documentation/devicetree/bindings/capebus/bone-generic-cape.txt
new file mode 100644
index 0000000..71ad2f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/bone-generic-cape.txt
@@ -0,0 +1,97 @@
+* Beagle bone generic cape
+
+ A generic cape is one form of cape that doesn't require any per-cape
+ driver for it to function. It is enough for the cape's node to be
+ instantiated in the right manner and the functions that the cape provides
+ will be available to Linux. A large number of capes fall in this category
+ like LCD/DVI/VGA capes, audio capes, capes with a number of gpio buttons,
+ capes with standard I2C/SPI/W1 parts etc.
+ All that's required is to describe the parts of the cape in the DT and
+ how they utilize the SoC peripherals and it will work, without having
+ to write any other driver, or modify the board support package.
+
+ As a sidenote, a large part of the complexity of capes have to do
+ with version management. A cape as it goes through various steps of evolution
+ changes. These changes are codified by the version field on the EEPROM.
+ It is important that version management can be kept as simple as possible.
+
+ The generic concept works by instantiating the child nodes that are
+ contained in the cape node. By default nodes that are present in the
+ root of the node are activated for any version. Version nodes can
+ contain per-version changes. In the example the da8xx-dt node differs
+ in the way it's instantiated, and this is expressed by the version nodes.
+
+Required properties:
+- compatible: Generic cape nodes must have the form "bone-generic-cape"
+- board-name: The cape's name as if provided by the board-name EEPROM field
+
+Optional properties:
+- version: Only valid in a version node, and it contains the list of compatible
+ versions this node contains.
+
+The standard supported nodes of the generic cape are:
+
+gpio-leds, tps65217-backlight, gpio-keys, w1-gpio, pwm-backlight
+
+The following nodes are supported via a capebus specific bridge devices, and
+their bindings described in their respective files:
+
+ti-tscadc-dt, da8xx-dt, i2c-dt, spi-dt
+
+Example:
+
+bone_dvi_cape: cape at 0 {
+
+ compatible = "bone-generic-cape";
+ board-name = "BeagleBone DVI-D CAPE";
+
+ /* hacky, since this is not a proper DT platform device */
+ /* but until we have DT bindings... */
+ version at 00A0 {
+ version = "00A0";
+ dvi {
+ compatible = "da8xx-dt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
+ ti,hwmods = "lcdc";
+
+ disp-pll = <560000000>;
+ panel-type = "1024x768 at 60";
+ powerdn-gpio = <&gpio2 7 0>;
+ };
+ };
+
+ version at 00A1 {
+ version = "00A1", "01";
+ dvi {
+ compatible = "da8xx-dt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
+ ti,hwmods = "lcdc";
+
+ disp-pll = <560000000>;
+ panel-type = "1024x768 at 60";
+ powerdn-gpio = <&gpio2 31 0>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_led_pins>;
+
+ dvi-led0 {
+ label = "dvi:green:usr0";
+ gpios = <&gpio2 18 0>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ dvi-led1 {
+ label = "dvi:green:usr1";
+ gpios = <&gpio2 19 0>;
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/capebus/da8xx-dt.txt b/Documentation/devicetree/bindings/capebus/da8xx-dt.txt
new file mode 100644
index 0000000..0b84063
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/da8xx-dt.txt
@@ -0,0 +1,31 @@
+* DA8XX DT bindins
+
+ This is an adapter device for use in device tree cases, since the
+ drivers DT bindings are not yet ready. It is bound to get away once
+ they are in place. Note that there is no capebus prefix, since there's
+ not really any dependence on capebus; the drivers can be moved out of
+ capebus if need be.
+
+Required properties:
+- compatible: Must have the form "da8xx-dt"
+- ti,hwmods: Must have the form "lcdc" (until hwmod DT is complete)
+- disp-pll: PLL value
+- panel-type: Name of the panel type connected
+
+Optional properties:
+powerdn-gpio: GPIO controlling power
+
+Note that the pinctrl bindings are supported.
+
+Example:
+
+dvi {
+ compatible = "da8xx-dt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
+ ti,hwmods = "lcdc";
+
+ disp-pll = <560000000>;
+ panel-type = "1024x768 at 60";
+ powerdn-gpio = <&gpio2 7 0>;
+};
diff --git a/Documentation/devicetree/bindings/capebus/i2c-dt.txt b/Documentation/devicetree/bindings/capebus/i2c-dt.txt
new file mode 100644
index 0000000..79a042a
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/i2c-dt.txt
@@ -0,0 +1,42 @@
+* I2C DT bindings
+
+ This is an adapter device for use in device tree cases.
+ What we want to do is to add a number of I2C devices connected
+ to a specified i2c adapter node, and instantiate them on
+ successful cape match. Not only that, normally I2C adapters
+ are disabled in the DT tree, so in that case we enable them
+ first and then go about our business.
+
+Required properties:
+- compatible: Must have the form "i2c-dt"
+- parent: The phandle of the i2c adapter node
+- #address-cells: The same as the parent i2c adapter node
+- #size-cells: The same as the parent i2c adapter node
+
+Example:
+
+i2c2-devices {
+ compatible = "i2c-dt";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ parent = <&i2c2>;
+
+ /* Ambient light sensor */
+ tsl2550 at 39 {
+ compatible = "tsl,tsl2550";
+ reg = <0x39>;
+ };
+
+ /* Humidity Sensor */
+ sht21 at 40 {
+ compatible = "sensiron,sht21";
+ reg = <0x40>;
+ };
+
+ /* Barometric pressure sensor */
+ bmp085 at 77 {
+ compatible = "bosch,bmp085";
+ reg = <0x77>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/capebus/spi-dt.txt b/Documentation/devicetree/bindings/capebus/spi-dt.txt
new file mode 100644
index 0000000..fd70fc4
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/spi-dt.txt
@@ -0,0 +1,37 @@
+* SPI DT bindings
+
+ This is an adapter device for use in device tree cases.
+ What we want to do is to add a number of SPI devices connected
+ to a specified spi node, and instantiate them on
+ successful cape match. Not only that, normally SPI nodes
+ are disabled in the DT tree, so in that case we enable them
+ first and then go about our business.
+
+Required properties:
+- compatible: Must have the form "spi-dt"
+- parent: The phandle of the spi node
+- #address-cells: The same as the parent spi node
+- #size-cells: The same as the parent spi node
+
+Example:
+
+spi1-devices {
+ compatible = "spi-dt";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ parent = <&spi1>;
+
+ lcd at 0 {
+ compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
+ spi-max-frequency = <8000000>;
+ reg = <0>;
+ spi-cpol;
+ spi-cpha;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins>;
+ st7735-rst = <&gpio4 19 0>;
+ st7735-dc = <&gpio4 21 0>;
+ };
+
+};
diff --git a/Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt b/Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt
new file mode 100644
index 0000000..44ad4f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt
@@ -0,0 +1,34 @@
+* TI's TSCADC Device Tree adapter
+
+ This is an adapter device for use in device tree cases, since the
+ drivers DT bindings are not yet ready. It is bound to get away once
+ they are in place. Note that there is no capebus prefix, since there's
+ not really any dependence on capebus; the drivers can be moved out of
+ capebus if need be.
+
+Required properties:
+- compatible: Must have the form "ti-tscadc-dt"
+- ti,hwmods: Must have the form "adc_tsc" (until hwmod DT is complete)
+
+Optional properties:
+- adc-channels: Number of ADC channels the driver should provide.
+- tsc-wires: Number of touchscreen wires
+- tsc-x-plate-resistance: Touchscreen X plate resistance value
+- tsc-steps: Touchscreen steps
+
+Note if either adc-channels or tsc-wires are missing their respective
+values are set to 0.
+
+Example:
+
+tscadc {
+ compatible = "ti-tscadc-dt";
+
+ ti,hwmods = "adc_tsc";
+
+ tsc-wires = <4>;
+ tsc-x-plate-resistance = <200>;
+ tsc-steps = <6>;
+
+ adc-channels = <4>;
+};
--
1.7.12
^ permalink raw reply related
* [RFC 5/7] capebus: Beaglebone capebus DT update
From: Pantelis Antoniou @ 2012-10-31 16:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1351702333-8456-1-git-send-email-panto@antoniou-consulting.com>
Update the common beaglebone's DTS with the required DT
entries for all known working capes as of now.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
arch/arm/boot/dts/am335x-bone-common.dtsi | 689 ++++++++++++++++++++++++++++--
1 file changed, 659 insertions(+), 30 deletions(-)
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index 99240a5..46d5f27 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -51,6 +51,143 @@
0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
>;
};
+ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ >;
+ };
+
+ bone_dvi_cape_led_pins: pinmux_bone_dvi_cape_led_pins {
+ pinctrl-single,pins = <
+ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+ 0x4c 0x07 /* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
+ >;
+ };
+
+ bone_dvi_cape_dvi_00A0_pins: pinmux_bone_dvi_cape_dvi_00A0_pins {
+ pinctrl-single,pins = <
+ 0x1c 0x07 /* gpmc_ad7.gpio1_7, OUTPUT | MODE7 - DVIPDn */
+
+ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ >;
+ };
+
+ bone_dvi_cape_dvi_00A1_pins: pinmux_bone_dvi_cape_dvi_00A1_pins {
+ pinctrl-single,pins = <
+ 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - DVIPDn */
+
+ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ >;
+ };
+
+ bone_geiger_cape_led_pins: pinmux_bone_geiger_cape_led_pins {
+ pinctrl-single,pins = <
+ 0xe4 0x07 /* lcd_hsync.gpio2_23, OUTPUT | MODE7 */
+ 0xec 0x07 /* lcd_ac_bias_en.gpio2_25, OUTPUT | MODE7 */
+ >;
+ };
+
+ bone_geiger_cape_pins: pinmux_bone_geiger_cape_pins {
+ pinctrl-single,pins = <
+ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+ /* 0x19c 0x34 */ /* mcasp0_ahclkr.eCAP2_in_PWM2_out, OMAP_MUX_MODE4 | INPUT_PULLUP */
+ 0x19c 0x37 /* mcasp0_ahclkr.gpio3_17, OMAP_MUX_MODE4 | INPUT_PULLUP */
+ >;
+ };
+
+ bone_lcd3_cape_led_00A0_pins: pinmux_bone_lcd3_cape_led_00A0_pins {
+ pinctrl-single,pins = <
+ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+ 0x4c 0x07 /* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
+ >;
+ };
+
+ bone_lcd3_cape_lcd_pins: pinmux_bone_lcd3_cape_lcd_pins {
+ pinctrl-single,pins = <
+ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ >;
+ };
+
+ bone_lcd3_cape_keys_00A0_pins: pinmux_bone_lcd3_cape_keys_00A0_pins {
+ pinctrl-single,pins = <
+ 0x040 0x2f /* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+ 0x044 0x2f /* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+ 0x1a4 0x2f /* mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+ 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+ 0x164 0x2f /* ecap0_in_pwm0_out.gpio0_7, INPUT | PULLDIS | MODE7 */
+ >;
+ };
+
+ pwm_bl_pins: pinmux_pwm_bl_pins {
+ pinctrl-single,pins = <
+ 0x4c 0x06 /* gpmc_a3.ehrpwm1b, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+ // 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+ >;
+ };
+
+ weather_cape_w1_pins: pinmux_weather_cape_w1_pins {
+ pinctrl-single,pins = <
+ 0x0c 0x37 /* gpmc_ad3.gpio1_3, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7 - w1-gpio */
+ >;
+ };
};
ocp {
@@ -92,16 +229,6 @@
};
};
- i2c1: i2c at 44e0b000 {
- status = "okay";
- clock-frequency = <400000>;
-
- tps: tps at 24 {
- reg = <0x24>;
- };
-
- };
-
gpevt {
compatible = "gpevt";
pinctrl-names = "default";
@@ -110,15 +237,117 @@
dma-names = "gpioevt";
gpio-evt = <&gpio3 2 0>;
};
+
+ };
+
+ capebus: capebus at 0 {
+ compatible = "bone-capebus";
+
+ bone_dvi_cape: cape at 0 {
+ compatible = "bone-generic-cape";
+ };
+
+ bone_geiger_cape: cape at 1 {
+ compatible = "bone-geiger-cape";
+ };
+
+ bone_lcd3_cape: cape at 2 {
+ compatible = "bone-generic-cape";
+ };
+
+ bone_lcd7_cape: cape at 3 {
+ compatible = "bone-lcd7-cape";
+ };
+
+ bone_weather_cape: cape at 4 {
+ compatible = "bone-generic-cape";
+ };
+
+ bone_adafruit_cape: cape at 5 {
+ compatible = "bone-generic-cape";
+ };
+
+ /* overrides; no EEPROM (prototyping) */
+// override at 3 {
+// compatible = "bone-capebus-slot-override";
+// slot = <3>;
+// board-name = "Geiger Cape";
+// version = "00A0";
+// manufacturer = "Geiger Inc";
+// /* TODO: Add the rest */
+// };
+
+// override at 2 {
+// compatible = "bone-capebus-slot-override";
+// slot = <2>;
+// board-name = "Weather Cape";
+// version = "00A0";
+// manufacturer = "CCO Inc";
+// /* TODO: Add the rest */
+// };
+
+// override at 1 {
+// compatible = "bone-capebus-slot-override";
+// slot = <1>;
+// board-name = "Adafruit 1.8 Cape";
+// version = "00A0";
+// manufacturer = "Adafruit";
+// /* TODO: Add the rest */
+// };
+
+// override at 0 {
+// compatible = "bone-capebus-slot-override";
+// slot = <0>;
+// board-name = "BeagleBone Weather CAPE";
+// version = "00A0";
+// manufacturer = "Beagleboardtoys";
+// /* TODO: Add the rest */
+// };
};
- backlight {
- compatible = "pwm-backlight";
- pwms = <&ehrpwm1 0 500000 0>;
- pwm-names = "st7735fb";
- brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
- default-brightness-level = <50>; /* index to the array above */
- };
+};
+
+&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tps: tps at 24 {
+ reg = <0x24>;
+ };
+
+ baseboard_eeprom: baseboard_eeprom at 50 {
+ compatible = "at,24c256";
+ reg = <0x50>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+
+ clock-frequency = <100000>;
+
+ /* OK, I know these are cape but for now it will do */
+ cape_eeprom_0: cape_eeprom_0 at 54 {
+ compatible = "at,24c256";
+ reg = <0x54>;
+ };
+
+ cape_eeprom_1: cape_eeprom_1 at 55 {
+ compatible = "at,24c256";
+ reg = <0x55>;
+ };
+
+ cape_eeprom_2: cape_eeprom_2 at 56 {
+ compatible = "at,24c256";
+ reg = <0x56>;
+ };
+
+ cape_eeprom_3: cape_eeprom_3 at 57 {
+ compatible = "at,24c256";
+ reg = <0x57>;
+ };
};
/include/ "tps65217.dtsi"
@@ -165,6 +394,7 @@
regulator-always-on;
};
};
+
};
&mmc1 {
@@ -172,21 +402,8 @@
};
&spi1 {
- status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
-
- lcd at 0 {
- compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
- spi-max-frequency = <8000000>;
- reg = <0>;
- spi-cpol;
- spi-cpha;
- pinctrl-names = "default";
- pinctrl-0 = <&lcd_pins>;
- st7735-rst = <&gpio4 19 0>;
- st7735-dc = <&gpio4 21 0>;
- };
};
&edma {
@@ -200,3 +417,415 @@
&cpsw_emac1 {
phy_id = "4a101000.mdio:01";
};
+
+&ehrpwm1 {
+ status = "okay";
+};
+
+&capebus {
+ slots = <&cape_eeprom_0 &cape_eeprom_1 &cape_eeprom_2 &cape_eeprom_3>;
+};
+
+&bone_dvi_cape {
+ board-name = "BeagleBone DVI-D CAPE";
+
+ /* hacky, since this is not a proper DT platform device */
+ /* but until we have DT bindings... */
+ version at 00A0 {
+ version = "00A0";
+ dvi {
+ compatible = "da8xx-dt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
+ ti,hwmods = "lcdc";
+
+ disp-pll = <560000000>;
+ panel-type = "1024x768 at 60";
+ powerdn-gpio = <&gpio2 7 0>;
+ };
+ };
+
+ version at 00A1 {
+ version = "00A1", "01";
+ dvi {
+ compatible = "da8xx-dt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
+ ti,hwmods = "lcdc";
+
+ disp-pll = <560000000>;
+ panel-type = "1024x768 at 60";
+ powerdn-gpio = <&gpio2 31 0>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_led_pins>;
+
+ dvi-led0 {
+ label = "dvi:green:usr0";
+ gpios = <&gpio2 18 0>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ dvi-led1 {
+ label = "dvi:green:usr1";
+ gpios = <&gpio2 19 0>;
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+ };
+};
+
+&bone_geiger_cape {
+ board-name = "Geiger Cape";
+
+ /* note that these can't be versioned... */
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_geiger_cape_pins>;
+
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "bone-geiger-cape";
+
+ pwm-frequency = <20000>; /* 20KHz */
+ pwm-duty-cycle = <60>; /* 60% */
+
+ event-blink-delay = <30>; /* 30ms */
+
+ gpios = <&gpio4 17 0>; /* pulse */
+
+ vsense-name = "AIN5"; /* analog vsense */
+ vsense-scale = <37325>; /* scaling */
+
+ tscadc {
+ compatible = "ti-tscadc-dt";
+
+ ti,hwmods = "adc_tsc";
+
+ adc-channels = <8>;
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_geiger_cape_led_pins>;
+
+ geiger-led0 {
+ label = "geiger:green:usr0";
+ gpios = <&gpio3 23 0>;
+ linux,default-trigger = "geiger-run";
+ default-state = "off";
+ };
+
+ geiger-led1 {
+ label = "geiger:red:usr1";
+ gpios = <&gpio3 25 0>;
+ linux,default-trigger = "geiger-event";
+ default-state = "off";
+ };
+ };
+};
+
+&bone_lcd3_cape {
+ board-name = "BeagleBone LCD3 CAPE";
+
+ /* hacky, since this is not a proper DT platform device */
+ /* but until we have DT bindings... */
+ lcd3 {
+ compatible = "da8xx-dt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
+
+ ti,hwmods = "lcdc";
+
+ disp-pll = <16000000>;
+ panel-type = "CDTech_S035Q01";
+ };
+
+ /* same thing as above */
+ tscadc {
+ compatible = "ti-tscadc-dt";
+
+ ti,hwmods = "adc_tsc";
+
+ tsc-wires = <4>;
+ tsc-x-plate-resistance = <200>;
+ tsc-steps = <6>;
+
+ adc-channels = <4>;
+ };
+
+ version at 00A0 {
+ version = "00A0";
+
+ backlight {
+ compatible = "tps65217-backlight";
+ isel = <1>;
+ fdim = <200>;
+
+ tps = <&tps>; /* link to the tps */
+ brightness = <100>;
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_led_00A0_pins>;
+
+ lcd3-led0 {
+ label = "lcd3:green:usr0";
+ gpios = <&gpio2 18 0>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ lcd3-led1 {
+ label = "lcd3:green:usr1";
+ gpios = <&gpio2 19 0>;
+ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_keys_00A0_pins>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ button at 1 {
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+ gpios = <&gpio2 16 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 2 {
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+ gpios = <&gpio2 17 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 3 {
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+ gpios = <&gpio4 19 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 4 {
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+ gpios = <&gpio2 28 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 5 {
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+ gpios = <&gpio1 7 0x0>;
+ gpio-key,wakeup;
+ };
+ };
+ };
+};
+
+&bone_lcd7_cape {
+ board-name = "BeagleBone LCD7 CAPE";
+
+ /* hacky, since this is not a proper DT platform device */
+ /* but until we have DT bindings... */
+ lcd7 {
+ compatible = "da8xx-dt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
+
+ ti,hwmods = "lcdc";
+
+ disp-pll = <60000000>;
+ panel-type = "TFC_S9700RTWV35TR_01B";
+ };
+
+ /* same thing as above */
+ tscadc {
+ compatible = "ti-tscadc-dt";
+
+ ti,hwmods = "adc_tsc";
+
+ tsc-wires = <4>;
+ tsc-x-plate-resistance = <200>;
+ tsc-steps = <6>;
+
+ adc-channels = <4>;
+ };
+
+ version at 00A0 {
+ version = "00A0";
+
+ backlight {
+ compatible = "tps65217-backlight";
+ isel = <1>;
+ fdim = <200>;
+
+ tps = <&tps>; /* link to the tps */
+ brightness = <100>;
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_led_00A0_pins>;
+
+ lcd3-led0 {
+ label = "lcd3:green:usr0";
+ gpios = <&gpio2 18 0>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ lcd3-led1 {
+ label = "lcd3:green:usr1";
+ gpios = <&gpio2 19 0>;
+ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_keys_00A0_pins>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ button at 1 {
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+ gpios = <&gpio2 16 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 2 {
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+ gpios = <&gpio2 17 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 3 {
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+ gpios = <&gpio4 19 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 4 {
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+ gpios = <&gpio2 28 0x0>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+ button at 5 {
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+ gpios = <&gpio1 7 0x0>;
+ gpio-key,wakeup;
+ };
+ };
+ };
+};
+
+&bone_weather_cape {
+ board-name = "BeagleBone Weather CAPE";
+
+ i2c2-devices {
+ compatible = "i2c-dt";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ parent = <&i2c2>;
+
+ /* Ambient light sensor */
+ tsl2550 at 39 {
+ compatible = "tsl,tsl2550";
+ reg = <0x39>;
+ };
+
+ /* Humidity Sensor */
+ sht21 at 40 {
+ compatible = "sensiron,sht21";
+ reg = <0x40>;
+ };
+
+ /* Barometric pressure sensor */
+ bmp085 at 77 {
+ compatible = "bosch,bmp085";
+ reg = <0x77>;
+ };
+ };
+
+ onewire at 0 {
+ compatible = "w1-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&weather_cape_w1_pins>;
+ status = "okay";
+
+ gpios = <&gpio2 3 0>;
+ };
+
+};
+
+&bone_adafruit_cape {
+ board-name = "Adafruit 1.8 Cape";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_bl_pins>;
+
+ pwms = <&ehrpwm1 1 500000 0>;
+ pwm-names = "st7735fb";
+ brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+ default-brightness-level = <50>; /* index to the array above */
+ };
+
+ spi1-devices {
+ compatible = "spi-dt";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ parent = <&spi1>;
+
+ lcd at 0 {
+ compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
+ spi-max-frequency = <8000000>;
+ reg = <0>;
+ spi-cpol;
+ spi-cpha;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins>;
+ st7735-rst = <&gpio4 19 0>;
+ st7735-dc = <&gpio4 21 0>;
+ };
+
+ };
+};
--
1.7.12
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox