* [PATCH 0/2] Add PCIe host driver support for some Mediatek SoCs
From: Ryder Lee @ 2017-04-23 8:19 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patch series add PCIe host controller driver and dt-binding
documentation for Mediatek mt7623 SoCs families.
This driver was validated using Broadcom Tigon3 ethernet card.
Ryder Lee (2):
PCI: mediatek: Add Mediatek PCIe host controller support
dt-bindings: pcie: Add documentation for Mediatek PCIe
.../bindings/pci/mediatek,mt7623-pcie.txt | 153 ++++++
drivers/pci/host/Kconfig | 11 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-mediatek.c | 611 +++++++++++++++++++++
4 files changed, 776 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
create mode 100644 drivers/pci/host/pcie-mediatek.c
--
1.9.1
^ permalink raw reply
* [PATCH 2/2] dt-bindings: phy: Add documentation for Mediatek PCIe PHY
From: Ryder Lee @ 2017-04-23 8:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492935453-17373-1-git-send-email-ryder.lee@mediatek.com>
Add documentation for PCIe PHY available in MT7623 series SoCs.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
.../devicetree/bindings/phy/phy-mt7623-pcie.txt | 67 ++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
diff --git a/Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt b/Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
new file mode 100644
index 0000000..27a9253
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
@@ -0,0 +1,67 @@
+Mediatek MT7623 PCIe PHY
+-----------------------
+
+Required properties:
+ - compatible: Should contain "mediatek,mt7623-pcie-phy"
+ - #phy-cells: must be 0
+ - clocks: Must contain an entry in clock-names.
+ See ../clocks/clock-bindings.txt for details.
+ - clock-names: Must be "refclk"
+ - resets: Must contain an entry in reset-names.
+ See ../reset/reset.txt for details.
+ - reset-names: Must be "phy"
+
+Optional properties:
+ - phy-switch: The PHY on PCIe port2 is shared with USB u3phy2. If you
+ want to enable port2, you should contain it.
+
+Example:
+
+ pcie0_phy: pciephy at 1a149000 {
+ compatible = "mediatek,mt7623-pcie-phy";
+ reg = <0 0x1a149000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-names = "pciephya_ref";
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
+ pcie1_phy: pciephy at 1a14a000 {
+ compatible = "mediatek,mt7623-pcie-phy";
+ reg = <0 0x1a14a000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-names = "pciephya_ref";
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
+ pcie2_phy: pciephy at 1a244000 {
+ compatible = "mediatek,mt7623-pcie-phy";
+ reg = <0 0x1a244000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-names = "pciephya_ref";
+ #phy-cells = <0>;
+
+ phy-switch = <&hifsys>;
+ status = "disabled";
+ };
+
+Specifying phy control of devices
+---------------------------------
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy node and phy-names.
+
+Example:
+
+#include <dt-bindings/phy/phy.h>
+
+pcie: pcie at 1a140000 {
+ ...
+ pcie at 1,0 {
+ ...
+ phys = <&pcie0_phy>;
+ phy-names = "pcie-phy0";
+ }
+ ...
+};
--
1.9.1
^ permalink raw reply related
* [PATCH 1/2] phy: add PCIe phy driver for mt7623 SoCs families
From: Ryder Lee @ 2017-04-23 8:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492935453-17373-1-git-send-email-ryder.lee@mediatek.com>
support PCIe phy of mt7623 SoCs families
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-mt7623-pcie.c | 290 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 300 insertions(+)
create mode 100644 drivers/phy/phy-mt7623-pcie.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index dc5277a..00ab313 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -518,4 +518,13 @@ config PHY_NSP_USB3
help
Enable this to support the Broadcom Northstar plus USB3 PHY.
If unsure, say N.
+
+config PHY_MT7623_PCIE
+ tristate "Mediatek PCIe PHY driver for MT7623 SoC families"
+ depends on ARCH_MEDIATEK && OF
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Say 'Y' here to add support for Mediatek PCIe PHY driver which
+ can be found on the MT7623 SoC families.
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e7b0feb..95032d6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -63,3 +63,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
obj-$(CONFIG_PHY_NSP_USB3) += phy-bcm-nsp-usb3.o
+obj-$(CONFIG_PHY_MT7623_PCIE) += phy-mt7623-pcie.o
diff --git a/drivers/phy/phy-mt7623-pcie.c b/drivers/phy/phy-mt7623-pcie.c
new file mode 100644
index 0000000..4096c12
--- /dev/null
+++ b/drivers/phy/phy-mt7623-pcie.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Offsets of sub-segment in each port registers */
+#define PCIE_SIFSLV_PHYD_BANK2_BASE 0xa00
+#define SSUSB_SIFSLV_PHYA_BASE 0xb00
+#define SSUSB_SIFSLV_PHYA_DA_BASE 0xc00
+
+/*
+ * RX detection stable - 1 scale represent 8 reference cycles
+ * cover reference clock from 1M~100MHz, 7us~40us
+ */
+#define B2_PHYD_RXDET1 (PCIE_SIFSLV_PHYD_BANK2_BASE + 0x28)
+#define RG_SSUSB_RXDET_STB2 GENMASK(17, 9)
+#define RG_SSUSB_RXDET_STB2_VAL(x) ((0x1ff & (x)) << 9)
+
+#define B2_PHYD_RXDET2 (PCIE_SIFSLV_PHYD_BANK2_BASE + 0x2c)
+#define RG_SSUSB_RXDET_STB2_P3 GENMASK(8, 0)
+#define RG_SSUSB_RXDET_STB2_P3_VAL(x) (0x1ff & (x))
+
+#define U3_PHYA_REG0 (SSUSB_SIFSLV_PHYA_BASE + 0x00)
+#define RG_PCIE_CLKDRV_OFFSET GENMASK(3, 1)
+#define RG_PCIE_CLKDRV_OFFSET_VAL(x) ((0x3 & (x)) << 2)
+
+#define U3_PHYA_REG1 (SSUSB_SIFSLV_PHYA_BASE + 0x04)
+#define RG_PCIE_CLKDRV_AMP GENMASK(31, 29)
+#define RG_PCIE_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
+
+#define DA_SSUSB_CDR_REFCK_SEL (SSUSB_SIFSLV_PHYA_DA_BASE + 0x00)
+#define RG_SSUSB_XTAL_EXT_PE1H GENMASK(13, 12)
+#define RG_SSUSB_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
+#define RG_SSUSB_XTAL_EXT_PE2H GENMASK(17, 16)
+#define RG_SSUSB_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
+
+#define DA_SSUSB_PLL_IC (SSUSB_SIFSLV_PHYA_DA_BASE + 0x0c)
+#define RG_SSUSB_PLL_IC_PE2H GENMASK(15, 12)
+#define RG_SSUSB_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
+#define RG_SSUSB_PLL_BR_PE2H GENMASK(29, 28)
+#define RG_SSUSB_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
+
+#define DA_SSUSB_PLL_BC (SSUSB_SIFSLV_PHYA_DA_BASE + 0x08)
+#define RG_SSUSB_PLL_DIVEN_PE2H GENMASK(21, 19)
+#define RG_SSUSB_PLL_BC_PE2H GENMASK(7, 6)
+#define RG_SSUSB_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
+
+#define DA_SSUSB_PLL_IR (SSUSB_SIFSLV_PHYA_DA_BASE + 0x10)
+#define RG_SSUSB_PLL_IR_PE2H GENMASK(19, 16)
+#define RG_SSUSB_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
+
+#define DA_SSUSB_PLL_BP (SSUSB_SIFSLV_PHYA_DA_BASE + 0x14)
+#define RG_SSUSB_PLL_BP_PE2H GENMASK(19, 16)
+#define RG_SSUSB_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
+
+#define DA_SSUSB_PLL_SSC_DELTA1_REG20 (SSUSB_SIFSLV_PHYA_DA_BASE + 0x3c)
+#define RG_SSUSB_PLL_SSC_DELTA1_PE2H GENMASK(31, 16)
+#define RG_SSUSB_PLL_SSC_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
+
+#define DA_SSUSB_PLL_SSC_DELTA_REG25 (SSUSB_SIFSLV_PHYA_DA_BASE + 0x48)
+#define RG_SSUSB_PLL_SSC_DELTA_PE2H GENMASK(15, 0)
+#define RG_SSUSB_PLL_SSC_DELTA_PE2H_VAL(x) (0xffff & (x))
+
+#define HIF_SYSCFG1 0x14
+#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20)
+
+struct mtk_pcie_phy {
+ struct device *dev;
+ void __iomem *base;
+ struct regmap *hif;
+ struct clk *phya_ref;
+ struct phy *phy;
+};
+
+static inline u32 phy_read(struct mtk_pcie_phy *phy, u32 reg)
+{
+ return readl(phy->base + reg);
+}
+
+static inline void phy_write(struct mtk_pcie_phy *phy, u32 val, u32 reg)
+{
+ writel(val, phy->base + reg);
+}
+
+static int mtk_pcie_phy_power_on(struct phy *phy)
+{
+ struct mtk_pcie_phy *mtk_phy = phy_get_drvdata(phy);
+ int err;
+ u32 val;
+
+ /* PCIe port2 PHY is shared with USB u3phy2 */
+ if (mtk_phy->hif)
+ regmap_update_bits(mtk_phy->hif, HIF_SYSCFG1,
+ HIF_SYSCFG1_PHY2_MASK, 0);
+
+ err = clk_prepare_enable(mtk_phy->phya_ref);
+ if (err) {
+ dev_err(mtk_phy->dev, "failed to enable PCIe phy clock\n");
+ return err;
+ }
+
+ val = phy_read(mtk_phy, DA_SSUSB_CDR_REFCK_SEL);
+ val &= ~(RG_SSUSB_XTAL_EXT_PE1H | RG_SSUSB_XTAL_EXT_PE2H);
+ val |= RG_SSUSB_XTAL_EXT_PE1H_VAL(0x2) |
+ RG_SSUSB_XTAL_EXT_PE2H_VAL(0x2);
+ phy_write(mtk_phy, val, DA_SSUSB_CDR_REFCK_SEL);
+
+ /* ref clk drive */
+ val = phy_read(mtk_phy, U3_PHYA_REG1);
+ val &= ~RG_PCIE_CLKDRV_AMP;
+ val |= RG_PCIE_CLKDRV_AMP_VAL(0x4);
+ phy_write(mtk_phy, val, U3_PHYA_REG1);
+
+ val = phy_read(mtk_phy, U3_PHYA_REG0);
+ val &= ~RG_PCIE_CLKDRV_OFFSET;
+ val |= RG_PCIE_CLKDRV_OFFSET_VAL(0x1);
+ phy_write(mtk_phy, val, U3_PHYA_REG0);
+
+ /* SSC delta -5000ppm */
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_SSC_DELTA1_REG20);
+ val &= ~RG_SSUSB_PLL_SSC_DELTA1_PE2H;
+ val |= RG_SSUSB_PLL_SSC_DELTA1_PE2H_VAL(0x3c);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_SSC_DELTA1_REG20);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_SSC_DELTA_REG25);
+ val &= ~RG_SSUSB_PLL_SSC_DELTA_PE2H;
+ val |= RG_SSUSB_PLL_SSC_DELTA_PE2H_VAL(0x36);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_SSC_DELTA_REG25);
+
+ /* change pll BW 0.6M */
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_IC);
+ val &= ~RG_SSUSB_PLL_BR_PE2H;
+ val |= RG_SSUSB_PLL_BR_PE2H_VAL(0x1);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_IC);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_BC);
+ val &= ~(RG_SSUSB_PLL_DIVEN_PE2H | RG_SSUSB_PLL_BC_PE2H);
+ val |= RG_SSUSB_PLL_BC_PE2H_VAL(0x3);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_BC);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_IR);
+ val &= ~RG_SSUSB_PLL_IR_PE2H;
+ val |= RG_SSUSB_PLL_IR_PE2H_VAL(0x2);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_IR);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_IC);
+ val &= ~RG_SSUSB_PLL_IC_PE2H;
+ val |= RG_SSUSB_PLL_IC_PE2H_VAL(0x1);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_IC);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_BP);
+ val &= ~RG_SSUSB_PLL_BP_PE2H;
+ val |= RG_SSUSB_PLL_BP_PE2H_VAL(0xa);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_BP);
+
+ /* Tx Detect Rx Timing: 10us -> 5us */
+ val = phy_read(mtk_phy, B2_PHYD_RXDET1);
+ val &= ~RG_SSUSB_RXDET_STB2;
+ val |= RG_SSUSB_RXDET_STB2_VAL(0x10);
+ phy_write(mtk_phy, val, B2_PHYD_RXDET1);
+
+ val = phy_read(mtk_phy, B2_PHYD_RXDET2);
+ val &= ~RG_SSUSB_RXDET_STB2_P3;
+ val |= RG_SSUSB_RXDET_STB2_P3_VAL(0x10);
+ phy_write(mtk_phy, val, B2_PHYD_RXDET2);
+
+ /* wait for PCIe subsys(MAC layer) register to active */
+ usleep_range(2500, 3000);
+
+ return 0;
+}
+
+static int mtk_pcie_phy_power_off(struct phy *phy)
+{
+ struct mtk_pcie_phy *mtk_phy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(mtk_phy->phya_ref);
+
+ return 0;
+}
+
+static struct phy_ops mtk_pcie_phy_ops = {
+ .power_on = mtk_pcie_phy_power_on,
+ .power_off = mtk_pcie_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id mtk_pcie_phy_of_match[];
+
+static int mtk_pcie_phy_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
+ struct phy_provider *phy_provider;
+ struct mtk_pcie_phy *mtk_phy;
+ struct resource *res;
+ struct phy *phy;
+
+ match = of_match_device(mtk_pcie_phy_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
+ mtk_phy = devm_kzalloc(&pdev->dev, sizeof(*mtk_phy), GFP_KERNEL);
+ if (!mtk_phy)
+ return -ENOMEM;
+
+ mtk_phy->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mtk_phy->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mtk_phy->base)) {
+ dev_err(&pdev->dev, "failed to get phy base\n");
+ return PTR_ERR(mtk_phy->base);
+ }
+
+ mtk_phy->phya_ref = devm_clk_get(&pdev->dev, "pciephya_ref");
+ if (IS_ERR(mtk_phy->phya_ref)) {
+ dev_err(&pdev->dev, "error to get pciephya_ref\n");
+ return PTR_ERR(mtk_phy->phya_ref);
+ }
+
+ if (of_find_property(np, "phy-switch", NULL)) {
+ mtk_phy->hif = syscon_regmap_lookup_by_phandle(
+ np, "phy-switch");
+ if (IS_ERR(mtk_phy->hif)) {
+ dev_err(&pdev->dev, "missing \"phy-switch\" phandle\n");
+ return PTR_ERR(mtk_phy->hif);
+ }
+ }
+
+ platform_set_drvdata(pdev, mtk_phy);
+ phy = devm_phy_create(&pdev->dev, NULL, &mtk_pcie_phy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(&pdev->dev, "failed to create phy device\n");
+ return PTR_ERR(phy);
+ }
+
+ mtk_phy->phy = phy;
+ phy_set_drvdata(phy, mtk_phy);
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(&pdev->dev, "failed to register phy provider\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pcie_phy_of_match[] = {
+ { .compatible = "mediatek,mt7623-pcie-phy"},
+ { .compatible = "mediatek,mt2701-pcie-phy"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_pcie_phy_of_match);
+
+static struct platform_driver mtk_pcie_phy_driver = {
+ .probe = mtk_pcie_phy_probe,
+ .driver = {
+ .name = "mtk-pcie-phy",
+ .of_match_table = mtk_pcie_phy_of_match,
+ }
+};
+module_platform_driver(mtk_pcie_phy_driver);
+
+MODULE_AUTHOR("Ryder Lee <ryder.lee@mediatek.com>");
+MODULE_DESCRIPTION("Mediatek PCIe phy driver");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH 0/2] Add PCIe phy driver for some Mediatek SoCs
From: Ryder Lee @ 2017-04-23 8:17 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patch series add PCIe phy driver and related dt-binding file for
Mediatek mt7623 SoCs families.
Thanks.
Ryder Lee (2):
phy: add PCIe phy driver for mt7623 SoCs families
dt-bindings: phy: Add documentation for Mediatek PCIe PHY
.../devicetree/bindings/phy/phy-mt7623-pcie.txt | 67 +++++
drivers/phy/Kconfig | 9 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-mt7623-pcie.c | 290 +++++++++++++++++++++
4 files changed, 367 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
create mode 100644 drivers/phy/phy-mt7623-pcie.c
--
1.9.1
^ permalink raw reply
* [PATCH 1/1] mt7601u: check return value of alloc_skb
From: Pan Bian @ 2017-04-23 7:00 UTC (permalink / raw)
To: linux-arm-kernel
Function alloc_skb() will return a NULL pointer if there is no enough
memory. However, in function mt7601u_mcu_msg_alloc(), its return value
is not validated before it is used. This patch fixes it.
Signed-off-by: Pan Bian <bianpan2016@163.com>
---
drivers/net/wireless/mediatek/mt7601u/mcu.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt7601u/mcu.c b/drivers/net/wireless/mediatek/mt7601u/mcu.c
index dbdfb3f..a9f5f39 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mcu.c
+++ b/drivers/net/wireless/mediatek/mt7601u/mcu.c
@@ -66,8 +66,10 @@ static inline void trace_mt_mcu_msg_send_cs(struct mt7601u_dev *dev,
WARN_ON(len % 4); /* if length is not divisible by 4 we need to pad */
skb = alloc_skb(len + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
- skb_reserve(skb, MT_DMA_HDR_LEN);
- memcpy(skb_put(skb, len), data, len);
+ if (skb) {
+ skb_reserve(skb, MT_DMA_HDR_LEN);
+ memcpy(skb_put(skb, len), data, len);
+ }
return skb;
}
@@ -170,6 +172,8 @@ static int mt7601u_mcu_function_select(struct mt7601u_dev *dev,
};
skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
+ if (!skb)
+ return -ENOMEM;
return mt7601u_mcu_msg_send(dev, skb, CMD_FUN_SET_OP, func == 5);
}
@@ -205,6 +209,8 @@ int mt7601u_mcu_tssi_read_kick(struct mt7601u_dev *dev, int use_hvga)
};
skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
+ if (!skb)
+ return -ENOMEM;
return mt7601u_mcu_msg_send(dev, skb, CMD_CALIBRATION_OP, true);
}
--
1.9.1
^ permalink raw reply related
* [PATCH v3] efifb: avoid reconfiguration of BAR that covers the framebuffer
From: Yinghai Lu @ 2017-04-23 1:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9dS4OhLbBw59yKYQmoJ8SpFexzk9yH=XfXnzn8NJ4mcg@mail.gmail.com>
On Mon, Apr 10, 2017 at 06:29:27PM +0100, Ard Biesheuvel wrote:
> /*
> @@ -208,8 +208,8 @@ struct pci_bus *pci_acpi_scan_root(struct
> acpi_pci_root *root)
> if (!bus)
> return NULL;
>
> - pci_bus_size_bridges(bus);
> - pci_bus_assign_resources(bus);
> + pci_assign_unassigned_root_bus_resources(bus);
> + pci_bus_claim_resources(bus);
>
> list_for_each_entry(child, &bus->children, node)
> pcie_bus_configure_settings(child);
>
looks like those two lines are reversed. you should use:
pcibios_resource_survey_bus(bus);
pci_assign_unassigned_root_bus_resources(bus);
please check x86 pcibios_resource_survey_bus() definition in
arch/x86/pci/i386.c
but pci_bus_claim_resources() should work too.
Yinghai
^ permalink raw reply
* [PATCH 2/2] dmaengine: s3c24xx: Fix a typo in a comment line
From: SF Markus Elfring @ 2017-04-22 21:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <930f0a6c-bc5c-3d01-6814-563780fc90ef@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 22 Apr 2017 23:09:03 +0200
Add a missing character in this description for a data structure member.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/s3c24xx-dma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c
index 967229829683..da79b2c6989f 100644
--- a/drivers/dma/s3c24xx-dma.c
+++ b/drivers/dma/s3c24xx-dma.c
@@ -159,7 +159,7 @@ struct s3c24xx_sg {
* struct s3c24xx_txd - wrapper for struct dma_async_tx_descriptor
* @vd: virtual DMA descriptor
* @dsg_list: list of children sg's
- * @at: sg currently being transfered
+ * @at: sg currently being transferred
* @width: transfer width
* @disrcc: value for source control register
* @didstc: value for destination control register
--
2.12.2
^ permalink raw reply related
* [PATCH 1/2] dmaengine: s3c24xx: Use devm_kcalloc() in s3c24xx_dma_probe()
From: SF Markus Elfring @ 2017-04-22 21:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <930f0a6c-bc5c-3d01-6814-563780fc90ef@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 22 Apr 2017 23:00:23 +0200
* A multiplication for the size determination of a memory allocation
indicated that an array data structure should be processed.
Thus use the corresponding function "devm_kcalloc".
* Replace the specification of a data structure by a pointer dereference
to make the corresponding size determination a bit safer according to
the Linux coding style convention.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/dma/s3c24xx-dma.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c
index f04c4702d98b..967229829683 100644
--- a/drivers/dma/s3c24xx-dma.c
+++ b/drivers/dma/s3c24xx-dma.c
@@ -1216,10 +1216,10 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
if (IS_ERR(s3cdma->base))
return PTR_ERR(s3cdma->base);
- s3cdma->phy_chans = devm_kzalloc(&pdev->dev,
- sizeof(struct s3c24xx_dma_phy) *
- pdata->num_phy_channels,
- GFP_KERNEL);
+ s3cdma->phy_chans = devm_kcalloc(&pdev->dev,
+ pdata->num_phy_channels,
+ sizeof(*s3cdma->phy_chans),
+ GFP_KERNEL);
if (!s3cdma->phy_chans)
return -ENOMEM;
--
2.12.2
^ permalink raw reply related
* [PATCH 0/2] dmaengine: s3c24xx: Fine-tuning for s3c24xx_dma_probe()
From: SF Markus Elfring @ 2017-04-22 21:23 UTC (permalink / raw)
To: linux-arm-kernel
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sat, 22 Apr 2017 23:14:32 +0200
Two update suggestions were taken into account
from static source code analysis.
Markus Elfring (2):
Use devm_kcalloc() in s3c24xx_dma_probe()
Fix a typo in a comment line
drivers/dma/s3c24xx-dma.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--
2.12.2
^ permalink raw reply
* usb: dwc2: NMI watchdog: BUG: soft lockup - CPU#0 stuck for 146s
From: Stefan Wahren @ 2017-04-22 20:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87mvbaykn1.fsf@eliezer.anholt.net>
Hi,
> Eric Anholt <eric@anholt.net> hat am 20. April 2017 um 20:54 geschrieben:
>
>
> Stefan Wahren <stefan.wahren@i2se.com> writes:
>
> > Hi,
> >
> >> Doug Anderson <dianders@chromium.org> hat am 18. April 2017 um 22:41 geschrieben:
> >>
> >>
> >> It's hard to know for sure that all of this time is really in
> >> urb_enqueue(). Possible we could have task switched out and been
> >> blocked elsewhere. Using ftrace to get more fine-grained timings
> >> would be useful. ktime_get(), ktime_sub(), and ktime_to_us() are your
> >> friends here if you want to use trace_printk.
> >
> > i'm a newbie to ftrace, so i hope this would be helpful.
> >
> > # connect PL2303 to the onboard hub
> > # echo 0 > options/sleep-time
> > # echo 0 > function_profile_enabled
> > # echo 1 > function_profile_enabled
> > # ./usb_test
> > # Waiting for at least 20 seconds and then disconnect PL2303
> > # echo 0 > function_profile_enabled
> > # cat trace_stat/function0
> >
> > Function Hit Time Avg s^2
> > -------- --- ---- --- ---
> > bcm2835_handle_irq 361347 219567633 us 607.636 us 1485199 us
> > __handle_domain_irq 1082482 212639551 us 196.437 us 3642030 us
> > generic_handle_irq 1082482 100592051 us 92.927 us 50511334 us
> > irq_exit 1082482 98197771 us 90.715 us 29649040 us
> > handle_level_irq 1082482 95812379 us 88.511 us 51910093 us
>
> If I'm reading this output right, we're spending half of our interrupt
> processing time in irq_exit(), so even if dwc2's interrupt was free (the
> generic_handle_irq() chain), we'd be eating about half the CPU getting
> back out of the interrupt handler, right?
>
> I don't really know anything about DWC2 or USB, but is there any way we
> could mitigate the interrupt frequency with this hardware? If nothing
> else, could we loop reading gintsts until it reads back 0?
first of all i updated my kernel to 4.11rc7 and the issue still occures. Today i had some time to investigate this issue further and i made some interesting observations:
1. The lockup doesn't occure always after starting usb_test. In rare cases i was able to run the program without lockup.
2. In case the lockup occured we are always able to "rescue" the BCM2835 from this state by sending some serial data to the PL2303.
3. I looked again at the logic analyzer traces of the PL2303 and FTDI. After usb_test has been started the time between 2 _dwc2_hcd_irq calls is mostly smaller than 6 us (this can't be correct for a single device doesn't send any data). With other words it seems to me one or more interrupt(s) are never acked.
4. I placed a trace_printk into dwc2_handle_hcd_intr() in order to dump GINTSTS. In normal state we usually reach the value 0x04000029, but not in lockup state.
Regards
Stefan
^ permalink raw reply
* [PATCH V5 4/7] ARM: pxa: Use - instead of @ for DT OPP entries
From: Robert Jarzmik @ 2017-04-22 19:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <874lxhkauf.fsf@belgarion.home>
Robert Jarzmik <robert.jarzmik@free.fr> writes:
> Viresh Kumar <viresh.kumar@linaro.org> writes:
>
>> On 20-04-17, 22:14, Robert Jarzmik wrote:
>>> Viresh Kumar <viresh.kumar@linaro.org> writes:
>>>
>>> > Compiling the DT file with W=1, DTC warns like follows:
>>> >
>>> > Warning (unit_address_vs_reg): Node /opp_table0/opp at 1000000000 has a
>>> > unit name, but no reg property
>>> >
>>> > Fix this by replacing '@' with '-' as the OPP nodes will never have a
>>> > "reg" property.
>>> >
>>> > Reported-by: Krzysztof Kozlowski <krzk@kernel.org>
>>> > Reported-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>>> > Suggested-by: Mark Rutland <mark.rutland@arm.com>
>>> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>>> > Acked-by: Rob Herring <robh@kernel.org>
>>> Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
>>
>> Thanks. But I need you to pick it up for your pull request for arm-soc.
Applied to pxa/dt tree, thanks.
Cheers.
--
Robert
^ permalink raw reply
* [RFC] minimum gcc version for kernel: raise to gcc-4.3 or 4.6?
From: Arnd Bergmann @ 2017-04-22 15:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.20.1704220400380.32200@eddie.linux-mips.org>
On Sat, Apr 22, 2017 at 5:10 AM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> On Fri, 21 Apr 2017, Kees Cook wrote:
>
>> > The linux-4.2 x86 defconfig could still be built with gcc-4.0, but
>> > later kernels have several minor problems with that, and
>> > require at least gcc-4.3.
>> >
>> > If we are ok with this status quo, we could simply declare gcc-4.3
>> > the absolute minimum version for the kernel, make gcc-4.9
>> > the recommeded minimum version, and remove all workarounds
>> > for gcc-4.2 or older.
>>
>> I think starting with this would be a good first step. I'm not sure
>> the best way to add "recommended minimum" to
>> Documentation/process/changes.rst hmmm
>
> FWIW for some reasons (mainly the ability to avoid NPTL) I have stuck to
> GCC 4.1.2 with some MIPS configurations and I've had no issues with that
> compiler up to Linux 4.6.0, which is the last kernel version I have tried
> with that compiler so far. I could check if anything has regressed since
> then I suppose.
Interesting. This is also the same version that Geert mentioned using
on m68k. I've tried some more x86 and mips builds now and found:
- x86 defconfig broke because the i915 driver relies on gcc-4.3 behavior
for alignment attributes as of a few kernel versions ago for the sw_fence
mechanism:
drivers/gpu/drm/i915/intel_display.c:14571: error: alignment may not
be specified for 'intel_atomic_commit_ready'
- With gcc-4.0 I also get a couple of BUILD_BUG_ON() triggering for
correct code that it doesn't always consider compile-time constant (on all
architectures), this is from x86 defconfig starting around linux-4.3:
mm/built-in.o: In function `do_set_pmd':
memory.c:(.text+0x34df5): undefined reference to `__compiletime_assert_3157'
drivers/built-in.o: In function `cea_mode_alternate_timings':
drm_edid.c:(.text+0x10858a): undefined reference to `__compiletime_assert_2641'
- gcc-4.0 has been broken for all MIPS configurations (but no other arch) since
commit 51b97e354ba9 ("kernel: use the gnu89 standard explicitly") in 3.18,
the problem still exists in stable/linux-3.18.y and mainline but would be
trivial to fix with a oneline patch if anyone had noticed this before me.
arch/mips/kernel/vmlinux.lds.S:110:1: error: pasting "initcall0" and
"." does not give a valid preprocessing token
- The interprocedural optimization changes in gcc-4.3 mean that the
object code is a bit different, and we no longer expect the pre-gcc-4.3
behavior. This mostly results in warnings (e.g. maybe-uninitialized or
section mismatch) when the compiler and/or linker lacks the
information to see that the code is actually correct. On x86 I only
got one failure with gcc-4.1, on mips-gcc-4.1 I got this and a few
more depending on configuration:
mm/built-in.o: In function `create_huge_pmd':
memory.c:(.text+0x34e71): undefined reference to `do_huge_pmd_anonymous_page'
The last one is the key here I think. The linker warnings and errors we
run into here are all fairly easy to fix, but we will keep running into new
ones since evidently nobody does regular builds checking for them, and
they can appear randomly based on configuration for otherwise
acceptable code. Today, most configurations I tried were broken because
of this, and if things worked for you, you were either lucky that you didn't
run into the same bugs (or that Geert fixed the ones you would have hit)
or you had patches on top to work around them already.
Based on what I found so far, gcc-4 can be pretty much ruled out from
being the minimum version based on the number of failures I got.
It's much better than 3.4 but much worse than 4.1 or 4.2 which seem
fixable on MIPS and x86 at least, and may or may not work depending
on configuration. So the best two possible (but conflicting) answers I
have are
a) There are known users on gcc-4.1, and we never break things that
work for users, so gcc-4.1 (or possibly 4.0 if a user shows up) would
be the minimum version.
b) gcc-4.1 and 4.2 have too many problems, so users are better off
when we tell them to upgrade to something newer, and a minimum
version of gcc-4.3 has fewer surprises. We should remove all
workarounds for pre-gcc-4.3 compilers and just force a build error
message.
Arnd
^ permalink raw reply
* [linux-sunxi] [PATCH v2 1/6] clk: sunxi-ng: Add sun4i/sun7i CCU driver
From: Jonathan Liu @ 2017-04-22 14:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ac8c4dab4f160ec605d52120517774bf1de87c2e.1490545262.git-series.plaes@plaes.org>
Hi Priit,
On 27 March 2017 at 04:20, Priit Laes <plaes@plaes.org> wrote:
> +static struct ccu_nkmp pll_ve_clk = {
> + .enable = BIT(31),
> + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> + .k = _SUNXI_CCU_MULT(4, 2),
> + .m = _SUNXI_CCU_DIV(0, 2),
> + .p = _SUNXI_CCU_DIV(16, 2),
> + .common = {
> + .reg = 0x018,
> + .hw.init = CLK_HW_INIT("pll-ve",
> + "hosc",
> + &ccu_nkmp_ops,
> + 0),
> + },
> +};
pll-ve is a NKMP clock in A10 but a NK clock in A20.
> +static const char *const hdmi_parents[] = { "pll-video0", "pll-video0-2x",
> + "pll-vide01", "pll-video1-2x" };
"pll-vide01" should be "pll-video1".
Regards,
Jonathan
^ permalink raw reply
* [PATCH V3 2/2] ARM64: dts: hi6220-hikey: Add clock binding for the pmic mfd
From: Daniel Lezcano @ 2017-04-22 14:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170422020233.GA7065@codeaurora.org>
On 22/04/2017 04:02, Stephen Boyd wrote:
> On 04/17, Daniel Lezcano wrote:
>> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
>> ---
>> Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt | 6 ++++++
>> arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 1 +
>> 2 files changed, 7 insertions(+)
>>
>
> I take it this goes through arm-soc? Not sure why I'm on To:
> line.
Probably it should go through Lee's tree.
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [linux-sunxi] [PATCH v2 1/6] clk: sunxi-ng: Add sun4i/sun7i CCU driver
From: Jonathan Liu @ 2017-04-22 12:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ac8c4dab4f160ec605d52120517774bf1de87c2e.1490545262.git-series.plaes@plaes.org>
Hi Priit,
On 27 March 2017 at 04:20, Priit Laes <plaes@plaes.org> wrote:
> Introduce a clock controller driver for sun4i A10 and sun7i A20
> series SoCs.
>
> Signed-off-by: Priit Laes <plaes@plaes.org>
> ---
> drivers/clk/sunxi-ng/Kconfig | 13 +-
> drivers/clk/sunxi-ng/Makefile | 1 +-
> drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c | 1532 ++++++++++++++++++-
> drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h | 59 +-
> include/dt-bindings/clock/sunxi-a10-a20-ccu.h | 208 ++-
> include/dt-bindings/reset/sunxi-a10-a20-ccu.h | 66 +-
> 6 files changed, 1879 insertions(+)
> create mode 100644 drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c
> create mode 100644 drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h
> create mode 100644 include/dt-bindings/clock/sunxi-a10-a20-ccu.h
> create mode 100644 include/dt-bindings/reset/sunxi-a10-a20-ccu.h
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index 213cf64..abed614 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -65,6 +65,19 @@ config SUN50I_A64_CCU
> default ARM64 && ARCH_SUNXI
> depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>
> +config SUNXI_A10_A20_CCU
> + bool "Support for the Allwinner A10/A20 CCU"
> + select SUNXI_CCU_DIV
> + select SUNXI_CCU_MULT
> + select SUNXI_CCU_NK
> + select SUNXI_CCU_NKM
> + select SUNXI_CCU_NM
> + select SUNXI_CCU_MP
> + select SUNXI_CCU_PHASE
> + default MACH_SUN4I
> + default MACH_SUN7I
> + depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
> +
> config SUN5I_CCU
> bool "Support for the Allwinner sun5i family CCM"
> select SUNXI_CCU_DIV
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 6feaac0..90bab0e 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -21,6 +21,7 @@ obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o
> obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
> obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o
> obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o
> +obj-$(CONFIG_SUNXI_A10_A20_CCU) += ccu-sunxi-a10-a20.o
> obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o
> obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o
> obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c
> new file mode 100644
> index 0000000..1884f5f
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c
> @@ -0,0 +1,1532 @@
> +/*
> + * Copyright (c) 2017 Priit Laes. All rights reserved.
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/of_address.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +#include "ccu_div.h"
> +#include "ccu_gate.h"
> +#include "ccu_mp.h"
> +#include "ccu_mult.h"
> +#include "ccu_nk.h"
> +#include "ccu_nkm.h"
> +#include "ccu_nkmp.h"
> +#include "ccu_nm.h"
> +#include "ccu_phase.h"
> +
> +#include "ccu-sunxi-a10-a20.h"
> +
> +static struct ccu_nkmp pll_core_clk = {
> + .enable = BIT(31),
> + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> + .k = _SUNXI_CCU_MULT(4, 2),
> + .m = _SUNXI_CCU_DIV(0, 2),
> + .p = _SUNXI_CCU_DIV(16, 2),
> + .common = {
> + .reg = 0x000,
> + .hw.init = CLK_HW_INIT("pll-core",
> + "hosc",
> + &ccu_nkmp_ops,
> + 0),
> + },
> +};
> +
> +/*
> + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
> + * the base (2x, 4x and 8x), and one variable divider (the one true
> + * pll audio).
> + *
> + * We don't have any need for the variable divider for now, so we just
> + * hardcode it to match with the clock names.
> + */
> +#define SUN4I_PLL_AUDIO_REG 0x008
> +static struct ccu_nm pll_audio_base_clk = {
> + .enable = BIT(31),
> + .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0),
> + .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0),
> + .common = {
> + .reg = 0x008,
> + .hw.init = CLK_HW_INIT("pll-audio-base",
> + "hosc",
> + &ccu_nm_ops,
> + 0),
> + },
> +
> +};
> +
> +static struct ccu_mult pll_video0_clk = {
> + .enable = BIT(31),
> + .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127),
> + .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14),
> + 270000000, 297000000),
> + .common = {
> + .reg = 0x010,
> + .features = (CCU_FEATURE_FRACTIONAL |
> + CCU_FEATURE_ALL_PREDIV),
> + .prediv = 8,
> + .hw.init = CLK_HW_INIT("pll-video0",
> + "hosc",
> + &ccu_mult_ops,
> + 0),
> + },
> +};
> +
> +static struct ccu_nkmp pll_ve_clk = {
> + .enable = BIT(31),
> + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> + .k = _SUNXI_CCU_MULT(4, 2),
> + .m = _SUNXI_CCU_DIV(0, 2),
> + .p = _SUNXI_CCU_DIV(16, 2),
> + .common = {
> + .reg = 0x018,
> + .hw.init = CLK_HW_INIT("pll-ve",
> + "hosc",
> + &ccu_nkmp_ops,
> + 0),
> + },
> +};
> +
> +static struct ccu_nk pll_ddr_base_clk = {
> + .enable = BIT(31),
> + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> + .k = _SUNXI_CCU_MULT(4, 2),
> + .common = {
> + .reg = 0x020,
> + .hw.init = CLK_HW_INIT("pll-ddr-base",
> + "hosc",
> + &ccu_nk_ops,
> + 0),
> + },
> +};
> +
> +static SUNXI_CCU_M(pll_ddr_clk, "pll-ddr", "pll-ddr-base", 0x020, 0, 2,
> + CLK_IS_CRITICAL);
> +
> +static struct ccu_div pll_ddr_other_clk = {
> + .div = _SUNXI_CCU_DIV_FLAGS(16, 2, CLK_DIVIDER_POWER_OF_TWO),
> +
> + .common = {
> + .reg = 0x020,
> + .hw.init = CLK_HW_INIT("pll-ddr-other", "pll-ddr-base",
> + &ccu_div_ops,
> + 0),
> + },
> +};
> +
> +static struct ccu_nk pll_periph_clk = {
> + .enable = BIT(31),
> + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> + .k = _SUNXI_CCU_MULT(4, 2),
> + .fixed_post_div = 2,
> + .common = {
> + .reg = 0x028,
> + .features = CCU_FEATURE_FIXED_POSTDIV,
> + .hw.init = CLK_HW_INIT("pll-periph",
> + "hosc",
> + &ccu_nk_ops,
> + 0),
> + },
> +};
> +/* Not documented on A10 */
> +static SUNXI_CCU_GATE(pll_periph_sata_clk, "pll-periph-sata", "pll-periph",
> + 0x028, BIT(14), 0);
> +
> +static struct ccu_mult pll_video1_clk = {
> + .enable = BIT(31),
> + .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127),
> + .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14),
> + 270000000, 297000000),
> + .common = {
> + .reg = 0x030,
> + .features = (CCU_FEATURE_FRACTIONAL |
> + CCU_FEATURE_ALL_PREDIV),
> + .prediv = 8,
> + .hw.init = CLK_HW_INIT("pll-video1",
> + "hosc",
> + &ccu_mult_ops,
> + 0),
> + },
> +};
> +
> +/* Not present on A10 */
> +static struct ccu_nk pll_gpu_clk = {
> + .enable = BIT(31),
> + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> + .k = _SUNXI_CCU_MULT(4, 2),
> + .common = {
> + .reg = 0x040,
> + .hw.init = CLK_HW_INIT("pll-gpu",
> + "hosc",
> + &ccu_nk_ops,
> + 0),
> + },
> +};
> +
> +static SUNXI_CCU_GATE(hosc_clk, "hosc", "osc24M", 0x050, BIT(0), 0);
> +
> +static const char *const cpu_parents[] = { "osc32k", "hosc",
> + "pll-core", "pll-periph" };
> +static const struct ccu_mux_fixed_prediv cpu_predivs[] = {
> + { .index = 3, .div = 3, },
> +};
> +
> +#define SUN4I_AHB_REG 0x054
> +static struct ccu_mux cpu_clk = {
> + .mux = {
> + .shift = 16,
> + .width = 2,
> + .fixed_predivs = cpu_predivs,
> + .n_predivs = ARRAY_SIZE(cpu_predivs),
> + },
> + .common = {
> + .reg = 0x054,
> + .features = CCU_FEATURE_FIXED_PREDIV,
> + .hw.init = CLK_HW_INIT_PARENTS("cpu",
> + cpu_parents,
> + &ccu_mux_ops,
> + CLK_IS_CRITICAL),
> + }
> +};
> +
> +static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x054, 0, 2, 0);
> +
> +static const char *const ahb_parents[] = { "axi", "pll-periph",
> + "pll-periph-2x" };
> +static const struct ccu_mux_fixed_prediv ahb_predivs[] = {
> + { .index = 2, .div = 2, },
> +};
> +
> +/* Undocumented on A10 */
> +static struct ccu_div ahb_clk = {
> + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
> + .mux = {
> + .shift = 6,
> + .width = 2,
> + .fixed_predivs = ahb_predivs,
> + .n_predivs = ARRAY_SIZE(ahb_predivs),
> + },
> +
> + .common = {
> + .reg = 0x054,
> + .hw.init = CLK_HW_INIT_PARENTS("ahb",
> + ahb_parents,
> + &ccu_div_ops,
> + 0),
> + },
> +};
> +
> +static struct clk_div_table apb0_div_table[] = {
> + { .val = 0, .div = 2 },
> + { .val = 1, .div = 2 },
> + { .val = 2, .div = 4 },
> + { .val = 3, .div = 8 },
> + { /* Sentinel */ },
> +};
> +static SUNXI_CCU_DIV_TABLE(apb0_clk, "apb0", "ahb",
> + 0x054, 8, 2, apb0_div_table, 0);
> +
> +static const char *const apb1_parents[] = { "hosc", "pll-periph", "osc32k" };
> +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x058,
> + 0, 5, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + 0);
> +
> +/* Not present on A20 */
> +static SUNXI_CCU_GATE(axi_dram_clk, "axi-dram", "ahb",
> + 0x05c, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(ahb_otg_clk, "ahb-otg", "ahb",
> + 0x060, BIT(0), 0);
> +static SUNXI_CCU_GATE(ahb_ehci0_clk, "ahb-ehci0", "ahb",
> + 0x060, BIT(1), 0);
> +static SUNXI_CCU_GATE(ahb_ohci0_clk, "ahb-ohci0", "ahb",
> + 0x060, BIT(2), 0);
> +static SUNXI_CCU_GATE(ahb_ehci1_clk, "ahb-ehci1", "ahb",
> + 0x060, BIT(3), 0);
> +static SUNXI_CCU_GATE(ahb_ohci1_clk, "ahb-ohci1", "ahb",
> + 0x060, BIT(4), 0);
> +static SUNXI_CCU_GATE(ahb_ss_clk, "ahb-ss", "ahb",
> + 0x060, BIT(5), 0);
> +static SUNXI_CCU_GATE(ahb_dma_clk, "ahb-dma", "ahb",
> + 0x060, BIT(6), 0);
> +static SUNXI_CCU_GATE(ahb_bist_clk, "ahb-bist", "ahb",
> + 0x060, BIT(7), 0);
> +static SUNXI_CCU_GATE(ahb_mmc0_clk, "ahb-mmc0", "ahb",
> + 0x060, BIT(8), 0);
> +static SUNXI_CCU_GATE(ahb_mmc1_clk, "ahb-mmc1", "ahb",
> + 0x060, BIT(9), 0);
> +static SUNXI_CCU_GATE(ahb_mmc2_clk, "ahb-mmc2", "ahb",
> + 0x060, BIT(10), 0);
> +static SUNXI_CCU_GATE(ahb_mmc3_clk, "ahb-mmc3", "ahb",
> + 0x060, BIT(11), 0);
> +static SUNXI_CCU_GATE(ahb_ms_clk, "ahb-ms", "ahb",
> + 0x060, BIT(12), 0);
> +static SUNXI_CCU_GATE(ahb_nand_clk, "ahb-nand", "ahb",
> + 0x060, BIT(13), 0);
> +static SUNXI_CCU_GATE(ahb_sdram_clk, "ahb-sdram", "ahb",
> + 0x060, BIT(14), CLK_IS_CRITICAL);
> +
> +static SUNXI_CCU_GATE(ahb_ace_clk, "ahb-ace", "ahb",
> + 0x060, BIT(16), 0);
> +static SUNXI_CCU_GATE(ahb_emac_clk, "ahb-emac", "ahb",
> + 0x060, BIT(17), 0);
> +static SUNXI_CCU_GATE(ahb_ts_clk, "ahb-ts", "ahb",
> + 0x060, BIT(18), 0);
> +static SUNXI_CCU_GATE(ahb_spi0_clk, "ahb-spi0", "ahb",
> + 0x060, BIT(20), 0);
> +static SUNXI_CCU_GATE(ahb_spi1_clk, "ahb-spi1", "ahb",
> + 0x060, BIT(21), 0);
> +static SUNXI_CCU_GATE(ahb_spi2_clk, "ahb-spi2", "ahb",
> + 0x060, BIT(22), 0);
> +static SUNXI_CCU_GATE(ahb_spi3_clk, "ahb-spi3", "ahb",
> + 0x060, BIT(23), 0);
> +static SUNXI_CCU_GATE(ahb_pata_clk, "ahb-pata", "ahb",
> + 0x060, BIT(24), 0);
> +/* Not documented on A20 */
> +static SUNXI_CCU_GATE(ahb_sata_clk, "ahb-sata", "ahb",
> + 0x060, BIT(25), 0);
> +/* Not present on A20 */
> +static SUNXI_CCU_GATE(ahb_gps_clk, "ahb-gps", "ahb",
> + 0x060, BIT(26), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(ahb_hstimer_clk, "ahb-hstimer", "ahb",
> + 0x060, BIT(28), 0);
> +
> +static SUNXI_CCU_GATE(ahb_ve_clk, "ahb-ve", "ahb",
> + 0x064, BIT(0), 0);
> +static SUNXI_CCU_GATE(ahb_tvd_clk, "ahb-tvd", "ahb",
> + 0x064, BIT(1), 0);
> +static SUNXI_CCU_GATE(ahb_tve0_clk, "ahb-tve0", "ahb",
> + 0x064, BIT(2), 0);
> +static SUNXI_CCU_GATE(ahb_tve1_clk, "ahb-tve1", "ahb",
> + 0x064, BIT(3), 0);
> +static SUNXI_CCU_GATE(ahb_lcd0_clk, "ahb-lcd0", "ahb",
> + 0x064, BIT(4), 0);
> +static SUNXI_CCU_GATE(ahb_lcd1_clk, "ahb-lcd1", "ahb",
> + 0x064, BIT(5), 0);
> +static SUNXI_CCU_GATE(ahb_csi0_clk, "ahb-csi0", "ahb",
> + 0x064, BIT(8), 0);
> +static SUNXI_CCU_GATE(ahb_csi1_clk, "ahb-csi1", "ahb",
> + 0x064, BIT(9), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(ahb_hdmi1_clk, "ahb-hdmi1", "ahb",
> + 0x064, BIT(10), 0);
> +static SUNXI_CCU_GATE(ahb_hdmi0_clk, "ahb-hdmi0", "ahb",
> + 0x064, BIT(11), 0);
> +static SUNXI_CCU_GATE(ahb_de_be0_clk, "ahb-de-be0", "ahb",
> + 0x064, BIT(12), 0);
> +static SUNXI_CCU_GATE(ahb_de_be1_clk, "ahb-de-be1", "ahb",
> + 0x064, BIT(13), 0);
> +static SUNXI_CCU_GATE(ahb_de_fe0_clk, "ahb-de-fe0", "ahb",
> + 0x064, BIT(14), 0);
> +static SUNXI_CCU_GATE(ahb_de_fe1_clk, "ahb-de-fe1", "ahb",
> + 0x064, BIT(15), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(ahb_gmac_clk, "ahb-gmac", "ahb",
> + 0x064, BIT(17), 0);
> +static SUNXI_CCU_GATE(ahb_mp_clk, "ahb-mp", "ahb",
> + 0x064, BIT(18), 0);
> +static SUNXI_CCU_GATE(ahb_gpu_clk, "ahb-gpu", "ahb",
> + 0x064, BIT(20), 0);
> +
> +static SUNXI_CCU_GATE(apb0_codec_clk, "apb0-codec", "apb0",
> + 0x068, BIT(0), 0);
> +static SUNXI_CCU_GATE(apb0_spdif_clk, "apb0-spdif", "apb0",
> + 0x068, BIT(1), 0);
> +static SUNXI_CCU_GATE(apb0_ac97_clk, "apb0-ac97", "apb0",
> + 0x068, BIT(2), 0);
> +static SUNXI_CCU_GATE(apb0_i2s0_clk, "apb0-i2s0", "apb0",
> + 0x068, BIT(3), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb0_i2s1_clk, "apb0-i2s1", "apb0",
> + 0x068, BIT(4), 0);
> +static SUNXI_CCU_GATE(apb0_pio_clk, "apb0-pio", "apb0",
> + 0x068, BIT(5), 0);
> +static SUNXI_CCU_GATE(apb0_ir0_clk, "apb0-ir0", "apb0",
> + 0x068, BIT(6), 0);
> +static SUNXI_CCU_GATE(apb0_ir1_clk, "apb0-ir1", "apb0",
> + 0x068, BIT(7), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb0_i2s2_clk, "apb0-i2s2", "apb0",
> + 0x068, BIT(8), 0);
> +static SUNXI_CCU_GATE(apb0_keypad_clk, "apb0-keypad", "apb0",
> + 0x068, BIT(10), 0);
> +
> +static SUNXI_CCU_GATE(apb1_i2c0_clk, "apb1-i2c0", "apb1",
> + 0x06c, BIT(0), 0);
> +static SUNXI_CCU_GATE(apb1_i2c1_clk, "apb1-i2c1", "apb1",
> + 0x06c, BIT(1), 0);
> +static SUNXI_CCU_GATE(apb1_i2c2_clk, "apb1-i2c2", "apb1",
> + 0x06c, BIT(2), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb1_i2c3_clk, "apb1-i2c3", "apb1",
> + 0x06c, BIT(3), 0);
> +static SUNXI_CCU_GATE(apb1_can_clk, "apb1-can", "apb1",
> + 0x06c, BIT(4), 0);
> +static SUNXI_CCU_GATE(apb1_scr_clk, "apb1-scr", "apb1",
> + 0x06c, BIT(5), 0);
> +static SUNXI_CCU_GATE(apb1_ps20_clk, "apb1-ps20", "apb1",
> + 0x06c, BIT(6), 0);
> +static SUNXI_CCU_GATE(apb1_ps21_clk, "apb1-ps21", "apb1",
> + 0x06c, BIT(7), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb1_i2c4_clk, "apb1-i2c4", "apb1",
> + 0x06c, BIT(15), 0);
> +static SUNXI_CCU_GATE(apb1_uart0_clk, "apb1-uart0", "apb1",
> + 0x06c, BIT(16), 0);
> +static SUNXI_CCU_GATE(apb1_uart1_clk, "apb1-uart1", "apb1",
> + 0x06c, BIT(17), 0);
> +static SUNXI_CCU_GATE(apb1_uart2_clk, "apb1-uart2", "apb1",
> + 0x06c, BIT(18), 0);
> +static SUNXI_CCU_GATE(apb1_uart3_clk, "apb1-uart3", "apb1",
> + 0x06c, BIT(19), 0);
> +static SUNXI_CCU_GATE(apb1_uart4_clk, "apb1-uart4", "apb1",
> + 0x06c, BIT(20), 0);
> +static SUNXI_CCU_GATE(apb1_uart5_clk, "apb1-uart5", "apb1",
> + 0x06c, BIT(21), 0);
> +static SUNXI_CCU_GATE(apb1_uart6_clk, "apb1-uart6", "apb1",
> + 0x06c, BIT(22), 0);
> +static SUNXI_CCU_GATE(apb1_uart7_clk, "apb1-uart7", "apb1",
> + 0x06c, BIT(23), 0);
> +
> +static const char *const mod0_default_parents[] = { "hosc", "pll-periph",
> + "pll-ddr-other" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ms_clk, "ms", mod0_default_parents, 0x084,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
> + 0x088, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
> + 0x088, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
> + 0x08c, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
> + 0x08c, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2",
> + 0x090, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2",
> + 0x090, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3_output", "mmc3",
> + 0x094, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3_sample", "mmc3",
> + 0x094, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents, 0x098,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents, 0x09c,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_MP_WITH_MUX_GATE(pata_clk, "pata", mod0_default_parents, 0x0ac,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +/* TODO: Check whether A10 actually supports osc32k as 4th parent? */
> +static const char *const ir_parents_sun4i[] = { "hosc", "pll-periph",
> + "pll-ddr-other" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun4i_clk, "ir0", ir_parents_sun4i, 0x0b0,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun4i_clk, "ir1", ir_parents_sun4i, 0x0b4,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +static const char *const ir_parents_sun7i[] = { "hosc", "pll-periph",
> + "pll-ddr-other", "osc32k" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun7i_clk, "ir0", ir_parents_sun7i, 0x0b0,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun7i_clk, "ir1", ir_parents_sun7i, 0x0b4,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const char *const audio_parents[] = { "pll-audio-8x", "pll-audio-4x",
> + "pll-audio-2x", "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", audio_parents,
> + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", audio_parents,
> + 0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", audio_parents,
> + 0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static const char *const keypad_parents[] = { "hosc", "losc"};
> +static const u8 keypad_table[] = { 0, 2 };
> +static struct ccu_mp keypad_clk = {
> + .enable = BIT(31),
> + .m = _SUNXI_CCU_DIV(0, 5),
> + .p = _SUNXI_CCU_DIV(16, 2),
> + .mux = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table),
> + .common = {
> + .reg = 0x0c4,
> + .hw.init = CLK_HW_INIT_PARENTS("keypad",
> + keypad_parents,
> + &ccu_mp_ops,
> + 0),
> + },
> +};
> +
> +/*
> + * TODO: SATA clock also supports external clock as parent via BIT(24)
> + * The external clock is probably an optional crystal or oscillator
> + * that can be connected to the SATA-CLKM / SATA-CLKP pins.
> + */
> +static SUNXI_CCU_GATE(sata_clk, "sata", "pll-periph-sata",
> + 0x0c8, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "pll-periph",
> + 0x0cc, BIT(6), 0);
> +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "pll-periph",
> + 0x0cc, BIT(7), 0);
> +static SUNXI_CCU_GATE(usb_phy_clk, "usb-phy", "pll-periph",
> + 0x0cc, BIT(8), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0d4,
> + 0, 4, /* M */
> + 16, 2, /* P */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +/* Not present on A10 */
> +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", audio_parents,
> + 0x0d8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +/* Not present on A10 */
> +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", audio_parents,
> + 0x0dc, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "pll-ddr",
> + 0x100, BIT(0), 0);
> +static SUNXI_CCU_GATE(dram_csi0_clk, "dram-csi0", "pll-ddr",
> + 0x100, BIT(1), 0);
> +static SUNXI_CCU_GATE(dram_csi1_clk, "dram-csi1", "pll-ddr",
> + 0x100, BIT(2), 0);
> +static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "pll-ddr",
> + 0x100, BIT(3), 0);
> +static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "pll-ddr",
> + 0x100, BIT(4), 0);
> +static SUNXI_CCU_GATE(dram_tve0_clk, "dram-tve0", "pll-ddr",
> + 0x100, BIT(5), 0);
> +static SUNXI_CCU_GATE(dram_tve1_clk, "dram-tve1", "pll-ddr",
> + 0x100, BIT(6), 0);
> +
> +static SUNXI_CCU_GATE(dram_out_clk, "dram-out", "pll-ddr",
> + 0x100, BIT(15), 0);
> +static SUNXI_CCU_GATE(dram_de_fe1_clk, "dram-de-fe1", "pll-ddr",
> + 0x100, BIT(24), 0);
> +static SUNXI_CCU_GATE(dram_de_fe0_clk, "dram-de-fe0", "pll-ddr",
> + 0x100, BIT(25), 0);
> +static SUNXI_CCU_GATE(dram_de_be0_clk, "dram-de-be0", "pll-ddr",
> + 0x100, BIT(26), 0);
> +static SUNXI_CCU_GATE(dram_de_be1_clk, "dram-de-be1", "pll-ddr",
> + 0x100, BIT(27), 0);
> +static SUNXI_CCU_GATE(dram_mp_clk, "dram-mp", "pll-ddr",
> + 0x100, BIT(28), 0);
> +static SUNXI_CCU_GATE(dram_ace_clk, "dram-ace", "pll-ddr",
> + 0x100, BIT(29), 0);
> +
> +static const char *const de_parents[] = { "pll-video0", "pll-video1",
> + "pll-ddr-other" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_be0_clk, "de-be0", de_parents,
> + 0x104, 0, 4, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_be1_clk, "de-be1", de_parents,
> + 0x108, 0, 4, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe0_clk, "de-fe0", de_parents,
> + 0x10c, 0, 4, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe1_clk, "de-fe1", de_parents,
> + 0x110, 0, 4, 24, 2, BIT(31), 0);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_mp_clk, "de-mp", de_parents,
> + 0x114, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const tcon_parents[] = { "pll-video0", "pll-video1",
> + "pll-video0-2x", "pll-video1-2x" };
> +static SUNXI_CCU_MUX_WITH_GATE(tcon0_ch0_clk, "tcon0-ch0-sclk", tcon_parents,
> + 0x118, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
> +static SUNXI_CCU_MUX_WITH_GATE(tcon1_ch0_clk, "tcon1-ch0-sclk", tcon_parents,
> + 0x11c, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static const char *const csi_isp_parents[] = { "pll-video0", "pll-ve",
> + "pll-ddr-other", "pll-sata" };
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(csi_isp_clk, "csi-isp",
> + csi_isp_parents,
> + 0x120, 0, 4, 24, 2, BIT(31), 0);
> +
> +/* TVD clock setup for A10 */
> +static const char *const tvd_parents[] = { "pll-video0", "pll-video1" };
> +static SUNXI_CCU_MUX_WITH_GATE(tvd_sun4i_clk, "tvd", tvd_parents,
> + 0x128, 24, 1, BIT(31), 0);
> +
> +/* TVD clock setup for A20 */
> +static SUNXI_CCU_MP_WITH_MUX_GATE(tvd_sclk2_sun7i_clk,
> + "tvd-sclk2", tvd_parents,
> + 0x128,
> + 0, 4, /* M */
> + 16, 4, /* P */
> + 8, 1, /* mux */
> + BIT(15), /* gate */
> + 0);
> +static SUNXI_CCU_M_WITH_GATE(tvd_sclk1_sun7i_clk, "tvd-sclk1", "tvd-sclk2",
> + 0x128, 0, 4, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(tcon0_ch1_sclk2_clk, "tcon0-ch1-sclk2",
> + tcon_parents,
> + 0x12c, 0, 4, 24, 2, BIT(31),
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_GATE(tcon0_ch1_clk,
> + "tcon0-ch1-sclk1", "tcon0-ch1-sclk2",
> + 0x12c, 11, 1, BIT(15),
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_ch1_sclk2_clk, "tcon1-ch1-sclk2",
> + tcon_parents,
> + 0x130, 0, 4, 24, 2, BIT(31),
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_GATE(tcon1_ch1_clk,
> + "tcon1-ch1-sclk1", "tcon1-ch1-sclk2",
> + 0x130, 11, 1, BIT(15),
> + CLK_SET_RATE_PARENT);
> +
> +static const char *const csi_parents[] = { "hosc", "pll-video0", "pll-video1",
> + "pll-video0-2x", "pll-video1-2x"};
> +static const u8 csi_table[] = { 0, 1, 2, 5, 6};
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_clk, "csi0",
> + csi_parents, csi_table,
> + 0x134, 0, 5, 24, 3, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_clk, "csi1",
> + csi_parents, csi_table,
> + 0x138, 0, 5, 24, 3, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c, 16, 8, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio",
> + 0x140, BIT(31), CLK_SET_RATE_PARENT);
> +static SUNXI_CCU_GATE(avs_clk, "avs", "hosc", 0x144, BIT(31), 0);
> +
> +static const char *const ace_parents[] = { "pll-ve", "pll-ddr-other" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(ace_clk, "ace", ace_parents,
> + 0x148, 0, 4, 24, 1, BIT(31), 0);
> +
> +static const char *const hdmi_parents[] = { "pll-video0", "pll-video0-2x",
> + "pll-vide01", "pll-video1-2x" };
"pll-vide01" should be "pll-video1"
> +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
> + 0x150, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const gpu_parents_sun4i[] = { "pll-video0", "pll-ve",
> + "pll-ddr-other",
> + "pll-video1" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(gpu_sun4i_clk, "gpu", gpu_parents_sun4i,
> + 0x154, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const gpu_parents_sun7i[] = { "pll-video0", "pll-ve",
> + "pll-ddr-other", "pll-video1",
> + "pll-gpu" };
> +static const u8 gpu_table_sun7i[] = { 0, 1, 2, 3, 4 };
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_sun7i_clk, "gpu",
> + gpu_parents_sun7i, gpu_table_sun7i,
> + 0x154, 0, 4, 24, 3, BIT(31), 0);
> +
> +static const char *const mbus_parents[] = { "hosc", "pll-periph-2x",
> + "pll-ddr-other" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
> + 0x15c, 0, 4, 16, 2, 24, 2, BIT(31),
> + CLK_IS_CRITICAL);
> +
> +static SUNXI_CCU_GATE(hdmi1_slow_clk, "hdmi1-slow", "hosc", 0x178, BIT(31), 0);
> +
> +static const char *const hdmi1_parents[] = { "pll-video0", "pll-video1" };
> +static const u8 hdmi1_table[] = { 0, 1};
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi1_clk, "hdmi1",
> + hdmi1_parents, hdmi1_table,
> + 0x17c, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const out_parents[] = { "hosc", "osc32k", "hosc" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(out_a_clk, "out-a", out_parents,
> + 0x1f0, 8, 5, 20, 2, 24, 2, BIT(31), 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(out_b_clk, "out-b", out_parents,
> + 0x1f4, 8, 5, 20, 2, 24, 2, BIT(31), 0);
> +
> +static struct ccu_common *sun4i_a10_ccu_clks[] = {
> + &hosc_clk.common,
> + &pll_core_clk.common,
> + &pll_audio_base_clk.common,
> + &pll_video0_clk.common,
> + &pll_ve_clk.common,
> + &pll_ddr_base_clk.common,
> + &pll_ddr_clk.common,
> + &pll_ddr_other_clk.common,
> + &pll_periph_clk.common,
> + &pll_periph_sata_clk.common,
> + &pll_video1_clk.common,
> + &cpu_clk.common,
> + &axi_clk.common,
> + &axi_dram_clk.common,
> + &ahb_clk.common,
> + &apb0_clk.common,
> + &apb1_clk.common,
> + &ahb_otg_clk.common,
> + &ahb_ehci0_clk.common,
> + &ahb_ohci0_clk.common,
> + &ahb_ehci1_clk.common,
> + &ahb_ohci1_clk.common,
> + &ahb_ss_clk.common,
> + &ahb_dma_clk.common,
> + &ahb_bist_clk.common,
> + &ahb_mmc0_clk.common,
> + &ahb_mmc1_clk.common,
> + &ahb_mmc2_clk.common,
> + &ahb_mmc3_clk.common,
> + &ahb_ms_clk.common,
> + &ahb_nand_clk.common,
> + &ahb_sdram_clk.common,
> + &ahb_ace_clk.common,
> + &ahb_emac_clk.common,
> + &ahb_ts_clk.common,
> + &ahb_spi0_clk.common,
> + &ahb_spi1_clk.common,
> + &ahb_spi2_clk.common,
> + &ahb_spi3_clk.common,
> + &ahb_pata_clk.common,
> + &ahb_sata_clk.common,
> + &ahb_gps_clk.common,
> + &ahb_ve_clk.common,
> + &ahb_tvd_clk.common,
> + &ahb_tve0_clk.common,
> + &ahb_tve1_clk.common,
> + &ahb_lcd0_clk.common,
> + &ahb_lcd1_clk.common,
> + &ahb_csi0_clk.common,
> + &ahb_csi1_clk.common,
> + &ahb_hdmi0_clk.common,
> + &ahb_de_be0_clk.common,
> + &ahb_de_be1_clk.common,
> + &ahb_de_fe0_clk.common,
> + &ahb_de_fe1_clk.common,
> + &ahb_mp_clk.common,
> + &ahb_gpu_clk.common,
> + &apb0_codec_clk.common,
> + &apb0_spdif_clk.common,
> + &apb0_ac97_clk.common,
> + &apb0_i2s0_clk.common,
> + &apb0_pio_clk.common,
> + &apb0_ir0_clk.common,
> + &apb0_ir1_clk.common,
> + &apb0_keypad_clk.common,
> + &apb1_i2c0_clk.common,
> + &apb1_i2c1_clk.common,
> + &apb1_i2c2_clk.common,
> + &apb1_can_clk.common,
> + &apb1_scr_clk.common,
> + &apb1_ps20_clk.common,
> + &apb1_ps21_clk.common,
> + &apb1_uart0_clk.common,
> + &apb1_uart1_clk.common,
> + &apb1_uart2_clk.common,
> + &apb1_uart3_clk.common,
> + &apb1_uart4_clk.common,
> + &apb1_uart5_clk.common,
> + &apb1_uart6_clk.common,
> + &apb1_uart7_clk.common,
> + &nand_clk.common,
> + &ms_clk.common,
> + &mmc0_clk.common,
> + &mmc0_output_clk.common,
> + &mmc0_sample_clk.common,
> + &mmc1_clk.common,
> + &mmc1_output_clk.common,
> + &mmc1_sample_clk.common,
> + &mmc2_clk.common,
> + &mmc2_output_clk.common,
> + &mmc2_sample_clk.common,
> + &mmc3_clk.common,
> + &mmc3_output_clk.common,
> + &mmc3_sample_clk.common,
> + &ts_clk.common,
> + &ss_clk.common,
> + &spi0_clk.common,
> + &spi1_clk.common,
> + &spi2_clk.common,
> + &pata_clk.common,
> + &ir0_sun4i_clk.common,
> + &ir1_sun4i_clk.common,
> + &i2s0_clk.common,
> + &ac97_clk.common,
> + &spdif_clk.common,
> + &keypad_clk.common,
> + &sata_clk.common,
> + &usb_ohci0_clk.common,
> + &usb_ohci1_clk.common,
> + &usb_phy_clk.common,
> + &spi3_clk.common,
> + &dram_ve_clk.common,
> + &dram_csi0_clk.common,
> + &dram_csi1_clk.common,
> + &dram_ts_clk.common,
> + &dram_tvd_clk.common,
> + &dram_tve0_clk.common,
> + &dram_tve1_clk.common,
> + &dram_out_clk.common,
> + &dram_de_fe1_clk.common,
> + &dram_de_fe0_clk.common,
> + &dram_de_be0_clk.common,
> + &dram_de_be1_clk.common,
> + &dram_mp_clk.common,
> + &dram_ace_clk.common,
> + &de_mp_clk.common,
> + &csi_isp_clk.common,
> + &tvd_sun4i_clk.common,
> + &tcon0_ch1_sclk2_clk.common,
> + &tcon0_ch1_clk.common,
> + &tcon1_ch1_sclk2_clk.common,
> + &tcon1_ch1_clk.common,
> + &csi0_clk.common,
> + &csi1_clk.common,
> + &ve_clk.common,
> + &codec_clk.common,
> + &avs_clk.common,
> + &ace_clk.common,
> + &hdmi_clk.common,
> + &gpu_sun4i_clk.common,
> +};
> +
> +static struct ccu_common *sun7i_a20_ccu_clks[] = {
> + &hosc_clk.common,
> + &pll_core_clk.common,
> + &pll_audio_base_clk.common,
> + &pll_video0_clk.common,
> + &pll_ve_clk.common,
> + &pll_ddr_base_clk.common,
> + &pll_ddr_clk.common,
> + &pll_ddr_other_clk.common,
> + &pll_periph_clk.common,
> + &pll_periph_sata_clk.common,
> + &pll_video1_clk.common,
> + &pll_gpu_clk.common,
> + &cpu_clk.common,
> + &axi_clk.common,
> + &ahb_clk.common,
> + &apb0_clk.common,
> + &apb1_clk.common,
> + &ahb_otg_clk.common,
> + &ahb_ehci0_clk.common,
> + &ahb_ohci0_clk.common,
> + &ahb_ehci1_clk.common,
> + &ahb_ohci1_clk.common,
> + &ahb_ss_clk.common,
> + &ahb_dma_clk.common,
> + &ahb_bist_clk.common,
> + &ahb_mmc0_clk.common,
> + &ahb_mmc1_clk.common,
> + &ahb_mmc2_clk.common,
> + &ahb_mmc3_clk.common,
> + &ahb_ms_clk.common,
> + &ahb_nand_clk.common,
> + &ahb_sdram_clk.common,
> + &ahb_ace_clk.common,
> + &ahb_emac_clk.common,
> + &ahb_ts_clk.common,
> + &ahb_spi0_clk.common,
> + &ahb_spi1_clk.common,
> + &ahb_spi2_clk.common,
> + &ahb_spi3_clk.common,
> + &ahb_pata_clk.common,
> + &ahb_sata_clk.common,
> + &ahb_hstimer_clk.common,
> + &ahb_ve_clk.common,
> + &ahb_tvd_clk.common,
> + &ahb_tve0_clk.common,
> + &ahb_tve1_clk.common,
> + &ahb_lcd0_clk.common,
> + &ahb_lcd1_clk.common,
> + &ahb_csi0_clk.common,
> + &ahb_csi1_clk.common,
> + &ahb_hdmi1_clk.common,
> + &ahb_hdmi0_clk.common,
> + &ahb_de_be0_clk.common,
> + &ahb_de_be1_clk.common,
> + &ahb_de_fe0_clk.common,
> + &ahb_de_fe1_clk.common,
> + &ahb_gmac_clk.common,
> + &ahb_mp_clk.common,
> + &ahb_gpu_clk.common,
> + &apb0_codec_clk.common,
> + &apb0_spdif_clk.common,
> + &apb0_ac97_clk.common,
> + &apb0_i2s0_clk.common,
> + &apb0_i2s1_clk.common,
> + &apb0_pio_clk.common,
> + &apb0_ir0_clk.common,
> + &apb0_ir1_clk.common,
> + &apb0_i2s2_clk.common,
> + &apb0_keypad_clk.common,
> + &apb1_i2c0_clk.common,
> + &apb1_i2c1_clk.common,
> + &apb1_i2c2_clk.common,
> + &apb1_i2c3_clk.common,
> + &apb1_can_clk.common,
> + &apb1_scr_clk.common,
> + &apb1_ps20_clk.common,
> + &apb1_ps21_clk.common,
> + &apb1_i2c4_clk.common,
> + &apb1_uart0_clk.common,
> + &apb1_uart1_clk.common,
> + &apb1_uart2_clk.common,
> + &apb1_uart3_clk.common,
> + &apb1_uart4_clk.common,
> + &apb1_uart5_clk.common,
> + &apb1_uart6_clk.common,
> + &apb1_uart7_clk.common,
> + &nand_clk.common,
> + &ms_clk.common,
> + &mmc0_clk.common,
> + &mmc0_output_clk.common,
> + &mmc0_sample_clk.common,
> + &mmc1_clk.common,
> + &mmc1_output_clk.common,
> + &mmc1_sample_clk.common,
> + &mmc2_clk.common,
> + &mmc2_output_clk.common,
> + &mmc2_sample_clk.common,
> + &mmc3_clk.common,
> + &mmc3_output_clk.common,
> + &mmc3_sample_clk.common,
> + &ts_clk.common,
> + &ss_clk.common,
> + &spi0_clk.common,
> + &spi1_clk.common,
> + &spi2_clk.common,
> + &pata_clk.common,
> + &ir0_sun7i_clk.common,
> + &ir1_sun7i_clk.common,
> + &i2s0_clk.common,
> + &ac97_clk.common,
> + &spdif_clk.common,
> + &keypad_clk.common,
> + &sata_clk.common,
> + &usb_ohci0_clk.common,
> + &usb_ohci1_clk.common,
> + &usb_phy_clk.common,
> + &spi3_clk.common,
> + &i2s1_clk.common,
> + &i2s2_clk.common,
> + &dram_ve_clk.common,
> + &dram_csi0_clk.common,
> + &dram_csi1_clk.common,
> + &dram_ts_clk.common,
> + &dram_tvd_clk.common,
> + &dram_tve0_clk.common,
> + &dram_tve1_clk.common,
> + &dram_out_clk.common,
> + &dram_de_fe1_clk.common,
> + &dram_de_fe0_clk.common,
> + &dram_de_be0_clk.common,
> + &dram_de_be1_clk.common,
> + &dram_mp_clk.common,
> + &dram_ace_clk.common,
> + &de_be0_clk.common,
> + &de_be1_clk.common,
> + &de_fe0_clk.common,
> + &de_fe1_clk.common,
> + &de_mp_clk.common,
> + &tcon0_ch0_clk.common,
> + &tcon1_ch0_clk.common,
> + &csi_isp_clk.common,
> + &tvd_sclk1_sun7i_clk.common,
> + &tvd_sclk2_sun7i_clk.common,
> + &tcon0_ch1_sclk2_clk.common,
> + &tcon0_ch1_clk.common,
> + &tcon1_ch1_sclk2_clk.common,
> + &tcon1_ch1_clk.common,
> + &csi0_clk.common,
> + &csi1_clk.common,
> + &ve_clk.common,
> + &codec_clk.common,
> + &avs_clk.common,
> + &ace_clk.common,
> + &hdmi_clk.common,
> + &gpu_sun7i_clk.common,
> + &mbus_clk.common,
> + &hdmi1_slow_clk.common,
> + &hdmi1_clk.common,
> + &out_a_clk.common,
> + &out_b_clk.common
> +};
> +
> +/* Post-divider for pll-audio is hardcoded to 4 */
> +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
> + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_periph_2x_clk, "pll-periph-2x",
> + "pll-periph", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
> + "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
> + "pll-video1", 1, 2, CLK_SET_RATE_PARENT);
> +
> +
> +static struct clk_hw_onecell_data sun4i_a10_hw_clks = {
> + .hws = {
> + [CLK_HOSC] = &hosc_clk.common.hw,
> + [CLK_PLL_CORE] = &pll_core_clk.common.hw,
> + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw,
> + [CLK_PLL_AUDIO] = &pll_audio_clk.hw,
> + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
> + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
> + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw,
> + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
> + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw,
> + [CLK_PLL_VE] = &pll_ve_clk.common.hw,
> + [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw,
> + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
> + [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw,
> + [CLK_PLL_PERIPH] = &pll_periph_clk.common.hw,
> + [CLK_PLL_PERIPH_2X] = &pll_periph_2x_clk.hw,
> + [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw,
> + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
> + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw,
> + [CLK_CPU] = &cpu_clk.common.hw,
> + [CLK_AXI] = &axi_clk.common.hw,
> + [CLK_AXI_DRAM] = &axi_dram_clk.common.hw,
> + [CLK_AHB] = &ahb_clk.common.hw,
> + [CLK_APB0] = &apb0_clk.common.hw,
> + [CLK_APB1] = &apb1_clk.common.hw,
> + [CLK_AHB_OTG] = &ahb_otg_clk.common.hw,
> + [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw,
> + [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw,
> + [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw,
> + [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw,
> + [CLK_AHB_SS] = &ahb_ss_clk.common.hw,
> + [CLK_AHB_DMA] = &ahb_dma_clk.common.hw,
> + [CLK_AHB_BIST] = &ahb_bist_clk.common.hw,
> + [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw,
> + [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw,
> + [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw,
> + [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw,
> + [CLK_AHB_MS] = &ahb_ms_clk.common.hw,
> + [CLK_AHB_NAND] = &ahb_nand_clk.common.hw,
> + [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw,
> + [CLK_AHB_ACE] = &ahb_ace_clk.common.hw,
> + [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw,
> + [CLK_AHB_TS] = &ahb_ts_clk.common.hw,
> + [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw,
> + [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw,
> + [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw,
> + [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw,
> + [CLK_AHB_PATA] = &ahb_pata_clk.common.hw,
> + [CLK_AHB_SATA] = &ahb_sata_clk.common.hw,
> + [CLK_AHB_GPS] = &ahb_gps_clk.common.hw,
> + [CLK_AHB_VE] = &ahb_ve_clk.common.hw,
> + [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw,
> + [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw,
> + [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw,
> + [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw,
> + [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw,
> + [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw,
> + [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw,
> + [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw,
> + [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw,
> + [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw,
> + [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw,
> + [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw,
> + [CLK_AHB_MP] = &ahb_mp_clk.common.hw,
> + [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw,
> + [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw,
> + [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw,
> + [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw,
> + [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw,
> + [CLK_APB0_PIO] = &apb0_pio_clk.common.hw,
> + [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw,
> + [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw,
> + [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw,
> + [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw,
> + [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw,
> + [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw,
> + [CLK_APB1_CAN] = &apb1_can_clk.common.hw,
> + [CLK_APB1_SCR] = &apb1_scr_clk.common.hw,
> + [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw,
> + [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw,
> + [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw,
> + [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw,
> + [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw,
> + [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw,
> + [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw,
> + [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw,
> + [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw,
> + [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw,
> + [CLK_NAND] = &nand_clk.common.hw,
> + [CLK_MS] = &ms_clk.common.hw,
> + [CLK_MMC0] = &mmc0_clk.common.hw,
> + [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw,
> + [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw,
> + [CLK_MMC1] = &mmc1_clk.common.hw,
> + [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw,
> + [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw,
> + [CLK_MMC2] = &mmc2_clk.common.hw,
> + [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw,
> + [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw,
> + [CLK_MMC3] = &mmc3_clk.common.hw,
> + [CLK_MMC3_OUTPUT] = &mmc3_output_clk.common.hw,
> + [CLK_MMC3_SAMPLE] = &mmc3_sample_clk.common.hw,
> + [CLK_TS] = &ts_clk.common.hw,
> + [CLK_SS] = &ss_clk.common.hw,
> + [CLK_SPI0] = &spi0_clk.common.hw,
> + [CLK_SPI1] = &spi1_clk.common.hw,
> + [CLK_SPI2] = &spi2_clk.common.hw,
> + [CLK_PATA] = &pata_clk.common.hw,
> + [CLK_IR0] = &ir0_sun4i_clk.common.hw,
> + [CLK_IR1] = &ir1_sun4i_clk.common.hw,
> + [CLK_I2S0] = &i2s0_clk.common.hw,
> + [CLK_AC97] = &ac97_clk.common.hw,
> + [CLK_SPDIF] = &spdif_clk.common.hw,
> + [CLK_KEYPAD] = &keypad_clk.common.hw,
> + [CLK_SATA] = &sata_clk.common.hw,
> + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
> + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
> + [CLK_USB_PHY] = &usb_phy_clk.common.hw,
> + [CLK_SPI3] = &spi3_clk.common.hw,
> + [CLK_DRAM_VE] = &dram_ve_clk.common.hw,
> + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw,
> + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw,
> + [CLK_DRAM_TS] = &dram_ts_clk.common.hw,
> + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw,
> + [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw,
> + [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw,
> + [CLK_DRAM_OUT] = &dram_out_clk.common.hw,
> + [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw,
> + [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw,
> + [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw,
> + [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw,
> + [CLK_DRAM_MP] = &dram_mp_clk.common.hw,
> + [CLK_DRAM_ACE] = &dram_ace_clk.common.hw,
> + [CLK_DE_BE0] = &de_be0_clk.common.hw,
> + [CLK_DE_BE1] = &de_be1_clk.common.hw,
> + [CLK_DE_FE0] = &de_fe0_clk.common.hw,
> + [CLK_DE_FE1] = &de_fe1_clk.common.hw,
> + [CLK_DE_MP] = &de_mp_clk.common.hw,
> + [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw,
> + [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw,
> + [CLK_CSI_ISP] = &csi_isp_clk.common.hw,
> + [CLK_TVD] = &tvd_sun4i_clk.common.hw,
> + [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw,
> + [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw,
> + [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw,
> + [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw,
> + [CLK_CSI0] = &csi0_clk.common.hw,
> + [CLK_CSI1] = &csi1_clk.common.hw,
> + [CLK_VE] = &ve_clk.common.hw,
> + [CLK_CODEC] = &codec_clk.common.hw,
> + [CLK_AVS] = &avs_clk.common.hw,
> + [CLK_ACE] = &ace_clk.common.hw,
> + [CLK_HDMI] = &hdmi_clk.common.hw,
> + [CLK_GPU] = &gpu_sun7i_clk.common.hw,
> + },
> + .num = CLK_NUMBER_SUN4I,
> +};
> +static struct clk_hw_onecell_data sun7i_a20_hw_clks = {
> + .hws = {
> + [CLK_HOSC] = &hosc_clk.common.hw,
> + [CLK_PLL_CORE] = &pll_core_clk.common.hw,
> + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw,
> + [CLK_PLL_AUDIO] = &pll_audio_clk.hw,
> + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
> + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
> + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw,
> + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
> + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw,
> + [CLK_PLL_VE] = &pll_ve_clk.common.hw,
> + [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw,
> + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
> + [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw,
> + [CLK_PLL_PERIPH] = &pll_periph_clk.common.hw,
> + [CLK_PLL_PERIPH_2X] = &pll_periph_2x_clk.hw,
> + [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw,
> + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
> + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw,
> + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
> + [CLK_CPU] = &cpu_clk.common.hw,
> + [CLK_AXI] = &axi_clk.common.hw,
> + [CLK_AHB] = &ahb_clk.common.hw,
> + [CLK_APB0] = &apb0_clk.common.hw,
> + [CLK_APB1] = &apb1_clk.common.hw,
> + [CLK_AHB_OTG] = &ahb_otg_clk.common.hw,
> + [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw,
> + [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw,
> + [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw,
> + [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw,
> + [CLK_AHB_SS] = &ahb_ss_clk.common.hw,
> + [CLK_AHB_DMA] = &ahb_dma_clk.common.hw,
> + [CLK_AHB_BIST] = &ahb_bist_clk.common.hw,
> + [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw,
> + [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw,
> + [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw,
> + [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw,
> + [CLK_AHB_MS] = &ahb_ms_clk.common.hw,
> + [CLK_AHB_NAND] = &ahb_nand_clk.common.hw,
> + [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw,
> + [CLK_AHB_ACE] = &ahb_ace_clk.common.hw,
> + [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw,
> + [CLK_AHB_TS] = &ahb_ts_clk.common.hw,
> + [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw,
> + [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw,
> + [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw,
> + [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw,
> + [CLK_AHB_PATA] = &ahb_pata_clk.common.hw,
> + [CLK_AHB_SATA] = &ahb_sata_clk.common.hw,
> + [CLK_AHB_HSTIMER] = &ahb_hstimer_clk.common.hw,
> + [CLK_AHB_VE] = &ahb_ve_clk.common.hw,
> + [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw,
> + [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw,
> + [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw,
> + [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw,
> + [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw,
> + [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw,
> + [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw,
> + [CLK_AHB_HDMI1] = &ahb_hdmi1_clk.common.hw,
> + [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw,
> + [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw,
> + [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw,
> + [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw,
> + [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw,
> + [CLK_AHB_GMAC] = &ahb_gmac_clk.common.hw,
> + [CLK_AHB_MP] = &ahb_mp_clk.common.hw,
> + [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw,
> + [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw,
> + [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw,
> + [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw,
> + [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw,
> + [CLK_APB0_I2S1] = &apb0_i2s1_clk.common.hw,
> + [CLK_APB0_PIO] = &apb0_pio_clk.common.hw,
> + [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw,
> + [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw,
> + [CLK_APB0_I2S2] = &apb0_i2s2_clk.common.hw,
> + [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw,
> + [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw,
> + [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw,
> + [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw,
> + [CLK_APB1_I2C3] = &apb1_i2c3_clk.common.hw,
> + [CLK_APB1_CAN] = &apb1_can_clk.common.hw,
> + [CLK_APB1_SCR] = &apb1_scr_clk.common.hw,
> + [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw,
> + [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw,
> + [CLK_APB1_I2C4] = &apb1_i2c4_clk.common.hw,
> + [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw,
> + [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw,
> + [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw,
> + [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw,
> + [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw,
> + [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw,
> + [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw,
> + [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw,
> + [CLK_NAND] = &nand_clk.common.hw,
> + [CLK_MS] = &ms_clk.common.hw,
> + [CLK_MMC0] = &mmc0_clk.common.hw,
> + [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw,
> + [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw,
> + [CLK_MMC1] = &mmc1_clk.common.hw,
> + [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw,
> + [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw,
> + [CLK_MMC2] = &mmc2_clk.common.hw,
> + [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw,
> + [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw,
> + [CLK_MMC3] = &mmc3_clk.common.hw,
> + [CLK_MMC3_OUTPUT] = &mmc3_output_clk.common.hw,
> + [CLK_MMC3_SAMPLE] = &mmc3_sample_clk.common.hw,
> + [CLK_TS] = &ts_clk.common.hw,
> + [CLK_SS] = &ss_clk.common.hw,
> + [CLK_SPI0] = &spi0_clk.common.hw,
> + [CLK_SPI1] = &spi1_clk.common.hw,
> + [CLK_SPI2] = &spi2_clk.common.hw,
> + [CLK_PATA] = &pata_clk.common.hw,
> + [CLK_IR0] = &ir0_sun7i_clk.common.hw,
> + [CLK_IR1] = &ir1_sun7i_clk.common.hw,
> + [CLK_I2S0] = &i2s0_clk.common.hw,
> + [CLK_AC97] = &ac97_clk.common.hw,
> + [CLK_SPDIF] = &spdif_clk.common.hw,
> + [CLK_KEYPAD] = &keypad_clk.common.hw,
> + [CLK_SATA] = &sata_clk.common.hw,
> + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
> + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
> + [CLK_USB_PHY] = &usb_phy_clk.common.hw,
> + [CLK_SPI3] = &spi3_clk.common.hw,
> + [CLK_I2S1] = &i2s1_clk.common.hw,
> + [CLK_I2S2] = &i2s2_clk.common.hw,
> + [CLK_DRAM_VE] = &dram_ve_clk.common.hw,
> + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw,
> + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw,
> + [CLK_DRAM_TS] = &dram_ts_clk.common.hw,
> + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw,
> + [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw,
> + [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw,
> + [CLK_DRAM_OUT] = &dram_out_clk.common.hw,
> + [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw,
> + [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw,
> + [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw,
> + [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw,
> + [CLK_DRAM_MP] = &dram_mp_clk.common.hw,
> + [CLK_DRAM_ACE] = &dram_ace_clk.common.hw,
> + [CLK_DE_BE0] = &de_be0_clk.common.hw,
> + [CLK_DE_BE1] = &de_be1_clk.common.hw,
> + [CLK_DE_FE0] = &de_fe0_clk.common.hw,
> + [CLK_DE_FE1] = &de_fe1_clk.common.hw,
> + [CLK_DE_MP] = &de_mp_clk.common.hw,
> + [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw,
> + [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw,
> + [CLK_CSI_ISP] = &csi_isp_clk.common.hw,
> + [CLK_TVD_SCLK2] = &tvd_sclk2_sun7i_clk.common.hw,
> + [CLK_TVD] = &tvd_sclk1_sun7i_clk.common.hw,
> + [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw,
> + [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw,
> + [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw,
> + [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw,
> + [CLK_CSI0] = &csi0_clk.common.hw,
> + [CLK_CSI1] = &csi1_clk.common.hw,
> + [CLK_VE] = &ve_clk.common.hw,
> + [CLK_CODEC] = &codec_clk.common.hw,
> + [CLK_AVS] = &avs_clk.common.hw,
> + [CLK_ACE] = &ace_clk.common.hw,
> + [CLK_HDMI] = &hdmi_clk.common.hw,
> + [CLK_GPU] = &gpu_sun7i_clk.common.hw,
> + [CLK_MBUS] = &mbus_clk.common.hw,
> + [CLK_HDMI1_SLOW] = &hdmi1_slow_clk.common.hw,
> + [CLK_HDMI1] = &hdmi1_clk.common.hw,
> + [CLK_OUT_A] = &out_a_clk.common.hw,
> + [CLK_OUT_B] = &out_b_clk.common.hw,
> + },
> + .num = CLK_NUMBER_SUN7I,
> +};
> +
> +static struct ccu_reset_map sun4i_a10_ccu_resets[] = {
> + [RST_USB_PHY0] = { 0x0cc, BIT(0) },
> + [RST_USB_PHY1] = { 0x0cc, BIT(1) },
> + [RST_USB_PHY2] = { 0x0cc, BIT(2) },
> + [RST_DE_BE0] = { 0x104, BIT(30) },
> + [RST_DE_BE1] = { 0x108, BIT(30) },
> + [RST_DE_FE0] = { 0x10c, BIT(30) },
> + [RST_DE_FE1] = { 0x110, BIT(30) },
> + [RST_DE_MP] = { 0x114, BIT(30) },
> + [RST_TCON0] = { 0x118, BIT(30) },
> + [RST_TCON1] = { 0x11c, BIT(30) },
> + [RST_CSI0] = { 0x134, BIT(30) },
> + [RST_CSI1] = { 0x138, BIT(30) },
> + [RST_VE] = { 0x13c, BIT(0) },
> + [RST_ACE] = { 0x148, BIT(16) },
> + [RST_LVDS] = { 0x14c, BIT(0) },
> + [RST_GPU] = { 0x154, BIT(30) },
> +};
> +
> +static struct ccu_reset_map sun7i_a20_ccu_resets[] = {
> + [RST_USB_PHY0] = { 0x0cc, BIT(0) },
> + [RST_USB_PHY1] = { 0x0cc, BIT(1) },
> + [RST_USB_PHY2] = { 0x0cc, BIT(2) },
> + [RST_DE_BE0] = { 0x104, BIT(30) },
> + [RST_DE_BE1] = { 0x108, BIT(30) },
> + [RST_DE_FE0] = { 0x10c, BIT(30) },
> + [RST_DE_FE1] = { 0x110, BIT(30) },
> + [RST_DE_MP] = { 0x114, BIT(30) },
> + [RST_TCON0] = { 0x118, BIT(30) },
> + [RST_TCON1] = { 0x11c, BIT(30) },
> + [RST_CSI0] = { 0x134, BIT(30) },
> + [RST_CSI1] = { 0x138, BIT(30) },
> + [RST_VE] = { 0x13c, BIT(0) },
> + [RST_ACE] = { 0x148, BIT(16) },
> + [RST_LVDS] = { 0x14c, BIT(0) },
> + [RST_GPU] = { 0x154, BIT(30) },
> + [RST_HDMI_H] = { 0x170, BIT(0) },
> + [RST_HDMI_SYS] = { 0x170, BIT(1) },
> + [RST_HDMI_AUDIO_DMA] = { 0x170, BIT(2) },
> +};
> +
> +static const struct sunxi_ccu_desc sun4i_a10_ccu_desc = {
> + .ccu_clks = sun4i_a10_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun4i_a10_ccu_clks),
> +
> + .hw_clks = &sun4i_a10_hw_clks,
> +
> + .resets = sun4i_a10_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun4i_a10_ccu_resets),
> +};
> +
> +static const struct sunxi_ccu_desc sun7i_a20_ccu_desc = {
> + .ccu_clks = sun7i_a20_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun7i_a20_ccu_clks),
> +
> + .hw_clks = &sun7i_a20_hw_clks,
> +
> + .resets = sun7i_a20_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun7i_a20_ccu_resets),
> +};
> +
> +static void init_clocks(void __iomem *reg)
> +{
> + u32 val;
> +
> + /* Force the PLL-Audio-1x divider to 4 */
> + val = readl(reg + SUN4I_PLL_AUDIO_REG);
> + val &= ~GENMASK(19, 16);
> + writel(val | (3 << 16), reg + SUN4I_PLL_AUDIO_REG);
> +
> + /* Use PLL6 as parent for AHB */
> + val = readl(reg + SUN4I_AHB_REG);
> + val &= ~GENMASK(7, 6);
> + writel(val | (2 << 6), reg + SUN4I_AHB_REG);
> +}
> +
> +static void __init sun4i_a10_ccu_setup(struct device_node *node)
> +{
> + void __iomem *reg;
> +
> + reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> + if (IS_ERR(reg)) {
> + pr_err("%s: Could not map the clock registers\n",
> + of_node_full_name(node));
> + return;
> + }
> +
> + init_clocks(reg);
> +
> + sunxi_ccu_probe(node, reg, &sun4i_a10_ccu_desc);
> +}
> +
> +static void __init sun7i_a20_ccu_setup(struct device_node *node)
> +{
> + void __iomem *reg;
> +
> + reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> + if (IS_ERR(reg)) {
> + pr_err("%s: Could not map the clock registers\n",
> + of_node_full_name(node));
> + return;
> + }
> +
> + init_clocks(reg);
> +
> + sunxi_ccu_probe(node, reg, &sun7i_a20_ccu_desc);
> +}
> +
> +CLK_OF_DECLARE(sun4i_a10_ccu, "allwinner,sun4i-a10-ccu",
> + sun4i_a10_ccu_setup);
> +CLK_OF_DECLARE(sun7i_a20_ccu, "allwinner,sun7i-a20-ccu",
> + sun7i_a20_ccu_setup);
> diff --git a/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h
> new file mode 100644
> index 0000000..bca224d
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h
> @@ -0,0 +1,59 @@
> +/*
> + * Copyright 2017 Priit Laes
> + *
> + * Priit Laes <plaes@plaes.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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 _CCU_SUNXI_A10_A20_H_
> +#define _CCU_SUNXI_A10_A20_H_
> +
> +#include <dt-bindings/clock/sunxi-a10-a20-ccu.h>
> +#include <dt-bindings/reset/sunxi-a10-a20-ccu.h>
> +
> +/* The HOSC is exported */
> +#define CLK_PLL_CORE 2
> +#define CLK_PLL_AUDIO_BASE 3
> +#define CLK_PLL_AUDIO 4
> +#define CLK_PLL_AUDIO_2X 5
> +#define CLK_PLL_AUDIO_4X 6
> +#define CLK_PLL_AUDIO_8X 7
> +#define CLK_PLL_VIDEO0 8
> +#define CLK_PLL_VIDEO0_2X 9
> +#define CLK_PLL_VE 10
> +#define CLK_PLL_DDR_BASE 11
> +#define CLK_PLL_DDR 12
> +#define CLK_PLL_DDR_OTHER 13
> +#define CLK_PLL_PERIPH 14
> +#define CLK_PLL_PERIPH_2X 15
> +#define CLK_PLL_VIDEO1 17
> +#define CLK_PLL_VIDEO1_2X 18
> +#define CLK_PLL_GPU 19
> +
> +/* The CPU clock is exported */
> +#define CLK_AXI 21
> +#define CLK_AXI_DRAM 22
> +#define CLK_AHB 23
> +#define CLK_APB0 24
> +#define CLK_APB1 25
> +
> +/* AHB gates are exported (23..68) */
> +/* APB0 gates are exported (69..78) */
> +/* APB1 gates are exported (79..95) */
> +/* IP module clocks are exported (96..128) */
> +/* DRAM gates are exported (129..142)*/
> +/* Media (display engine clocks & etc) are exported (143..169) */
> +
> +#define CLK_NUMBER_SUN4I (CLK_GPU + 1)
> +#define CLK_NUMBER_SUN7I (CLK_OUT_B + 1)
> +
> +#endif /* _CCU_SUNXI_A10_A20_H_ */
> diff --git a/include/dt-bindings/clock/sunxi-a10-a20-ccu.h b/include/dt-bindings/clock/sunxi-a10-a20-ccu.h
> new file mode 100644
> index 0000000..364ccbe
> --- /dev/null
> +++ b/include/dt-bindings/clock/sunxi-a10-a20-ccu.h
> @@ -0,0 +1,208 @@
> +/*
> + * Copyright (C) 2017 Priit Laes <plaes@plaes.org>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUNXI_A10_A20_H_
> +#define _DT_BINDINGS_CLK_SUNXI_A10_A20_H_
> +
> +#define CLK_HOSC 1
> +#define CLK_PLL_PERIPH_SATA 16
> +#define CLK_CPU 20
> +
> +/* AHB Gates */
> +#define CLK_AHB_OTG 26
> +#define CLK_AHB_EHCI0 27
> +#define CLK_AHB_OHCI0 28
> +#define CLK_AHB_EHCI1 29
> +#define CLK_AHB_OHCI1 30
> +#define CLK_AHB_SS 31
> +#define CLK_AHB_DMA 32
> +#define CLK_AHB_BIST 33
> +#define CLK_AHB_MMC0 34
> +#define CLK_AHB_MMC1 35
> +#define CLK_AHB_MMC2 36
> +#define CLK_AHB_MMC3 37
> +#define CLK_AHB_MS 38
> +#define CLK_AHB_NAND 39
> +#define CLK_AHB_SDRAM 40
> +#define CLK_AHB_ACE 41
> +#define CLK_AHB_EMAC 42
> +#define CLK_AHB_TS 43
> +#define CLK_AHB_SPI0 44
> +#define CLK_AHB_SPI1 45
> +#define CLK_AHB_SPI2 46
> +#define CLK_AHB_SPI3 47
> +#define CLK_AHB_PATA 48
> +#define CLK_AHB_SATA 49
> +#define CLK_AHB_GPS 50
> +#define CLK_AHB_HSTIMER 51
> +#define CLK_AHB_VE 52
> +#define CLK_AHB_TVD 53
> +#define CLK_AHB_TVE0 54
> +#define CLK_AHB_TVE1 55
> +#define CLK_AHB_LCD0 56
> +#define CLK_AHB_LCD1 57
> +#define CLK_AHB_CSI0 58
> +#define CLK_AHB_CSI1 59
> +#define CLK_AHB_HDMI0 60
> +#define CLK_AHB_HDMI1 61
> +#define CLK_AHB_DE_BE0 62
> +#define CLK_AHB_DE_BE1 63
> +#define CLK_AHB_DE_FE0 64
> +#define CLK_AHB_DE_FE1 65
> +#define CLK_AHB_GMAC 66
> +#define CLK_AHB_MP 67
> +#define CLK_AHB_GPU 68
> +
> +/* APB0 Gates */
> +#define CLK_APB0_CODEC 69
> +#define CLK_APB0_SPDIF 70
> +#define CLK_APB0_I2S0 71
> +#define CLK_APB0_AC97 72
> +#define CLK_APB0_I2S1 73
> +#define CLK_APB0_PIO 74
> +#define CLK_APB0_IR0 75
> +#define CLK_APB0_IR1 76
> +#define CLK_APB0_I2S2 77
> +#define CLK_APB0_KEYPAD 78
> +
> +/* APB1 Gates */
> +#define CLK_APB1_I2C0 79
> +#define CLK_APB1_I2C1 80
> +#define CLK_APB1_I2C2 81
> +#define CLK_APB1_I2C3 82
> +#define CLK_APB1_CAN 83
> +#define CLK_APB1_SCR 84
> +#define CLK_APB1_PS20 85
> +#define CLK_APB1_PS21 86
> +#define CLK_APB1_I2C4 87
> +#define CLK_APB1_UART0 88
> +#define CLK_APB1_UART1 89
> +#define CLK_APB1_UART2 90
> +#define CLK_APB1_UART3 91
> +#define CLK_APB1_UART4 92
> +#define CLK_APB1_UART5 93
> +#define CLK_APB1_UART6 94
> +#define CLK_APB1_UART7 95
> +
> +/* IP clocks */
> +#define CLK_NAND 96
> +#define CLK_MS 97
> +#define CLK_MMC0 98
> +#define CLK_MMC0_OUTPUT 99
> +#define CLK_MMC0_SAMPLE 100
> +#define CLK_MMC1 101
> +#define CLK_MMC1_OUTPUT 102
> +#define CLK_MMC1_SAMPLE 103
> +#define CLK_MMC2 104
> +#define CLK_MMC2_OUTPUT 105
> +#define CLK_MMC2_SAMPLE 106
> +#define CLK_MMC3 107
> +#define CLK_MMC3_OUTPUT 108
> +#define CLK_MMC3_SAMPLE 109
> +#define CLK_TS 110
> +#define CLK_SS 111
> +#define CLK_SPI0 112
> +#define CLK_SPI1 113
> +#define CLK_SPI2 114
> +#define CLK_PATA 115
> +#define CLK_IR0 116
> +#define CLK_IR1 117
> +#define CLK_I2S0 118
> +#define CLK_AC97 119
> +#define CLK_SPDIF 120
> +#define CLK_KEYPAD 121
> +#define CLK_SATA 122
> +#define CLK_USB_OHCI0 123
> +#define CLK_USB_OHCI1 124
> +#define CLK_USB_PHY 125
> +#define CLK_SPI3 126
> +#define CLK_I2S1 127
> +#define CLK_I2S2 128
> +
> +/* DRAM Gates */
> +#define CLK_DRAM_VE 129
> +#define CLK_DRAM_CSI0 130
> +#define CLK_DRAM_CSI1 131
> +#define CLK_DRAM_TS 132
> +#define CLK_DRAM_TVD 133
> +#define CLK_DRAM_TVE0 134
> +#define CLK_DRAM_TVE1 135
> +#define CLK_DRAM_OUT 136
> +#define CLK_DRAM_DE_FE1 137
> +#define CLK_DRAM_DE_FE0 138
> +#define CLK_DRAM_DE_BE0 139
> +#define CLK_DRAM_DE_BE1 140
> +#define CLK_DRAM_MP 141
> +#define CLK_DRAM_ACE 142
> +
> +/* Display Engine Clocks */
> +#define CLK_DE_BE0 143
> +#define CLK_DE_BE1 144
> +#define CLK_DE_FE0 145
> +#define CLK_DE_FE1 146
> +#define CLK_DE_MP 147
> +#define CLK_TCON0_CH0 148
> +#define CLK_TCON1_CH0 149
> +#define CLK_CSI_ISP 150
> +#define CLK_TVD_SCLK2 151
> +#define CLK_TVD 152
> +#define CLK_TCON0_CH1_SCLK2 153
> +#define CLK_TCON0_CH1 154
> +#define CLK_TCON1_CH1_SCLK2 155
> +#define CLK_TCON1_CH1 156
> +#define CLK_CSI0 157
> +#define CLK_CSI1 158
> +#define CLK_CODEC 159
> +#define CLK_VE 160
> +#define CLK_AVS 161
> +#define CLK_ACE 162
> +#define CLK_HDMI 163
> +#define CLK_GPU 164
> +
> +/* Following only exist on sun7i-a20 */
> +#define CLK_MBUS 165
> +#define CLK_HDMI1_SLOW 166
> +#define CLK_HDMI1 167
> +#define CLK_OUT_A 168
> +#define CLK_OUT_B 169
> +
> +#endif /* _DT_BINDINGS_CLK_SUNXI_A10_A20_H_ */
> diff --git a/include/dt-bindings/reset/sunxi-a10-a20-ccu.h b/include/dt-bindings/reset/sunxi-a10-a20-ccu.h
> new file mode 100644
> index 0000000..9845cee
> --- /dev/null
> +++ b/include/dt-bindings/reset/sunxi-a10-a20-ccu.h
> @@ -0,0 +1,66 @@
> +/*
> + * Copyright (C) 2017 Priit Laes <plaes@plaes.org>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUNXI_A10_A10_H
> +#define _DT_BINDINGS_RST_SUNXI_A10_A10_H
> +
> +#define RST_USB_PHY0 1
> +#define RST_USB_PHY1 2
> +#define RST_USB_PHY2 3
> +#define RST_DE_BE0 4
> +#define RST_DE_BE1 5
> +#define RST_DE_FE0 6
> +#define RST_DE_FE1 7
> +#define RST_DE_MP 8
> +#define RST_TCON0 9
> +#define RST_TCON1 10
> +#define RST_CSI0 11
> +#define RST_CSI1 12
> +#define RST_VE 13
> +#define RST_ACE 14
> +#define RST_LVDS 15
> +#define RST_GPU 16
> +#define RST_HDMI_H 17
> +#define RST_HDMI_SYS 18
> +#define RST_HDMI_AUDIO_DMA 19
> +
> +#endif /* DT_BINDINGS_RST_SUNXI_A10_A10_H */
> --
> git-series 0.9.1
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Regards,
Jonathan
^ permalink raw reply
* [PATCH v2 0/5] mtd: nand: gpmi: add i.MX 7 support
From: Marek Vasut @ 2017-04-22 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170422012338.4635-1-stefan@agner.ch>
On 04/22/2017 03:23 AM, Stefan Agner wrote:
> This patchset adds support for i.MX 7 SoC for the GPMI NAND controller.
> There have been similar patchsets already:
> https://lkml.org/lkml/2016/2/23/912
>
> However, this patchset does not make use of any of the new features.
> The current feature set seems to work fine, I successfully run the MTD
> tests on a Colibri iMX7.
>
> --
> Stefan
>
> Changes since v1:
> - Make clks_count const
> - Introduce IS_IMX7D for i.MX 7 SoC's and make it part of GPMI_IS_MX6
Super, thanks.
--
Best regards,
Marek Vasut
^ permalink raw reply
* [RFC PATCH] of: Fix DMA configuration for non-DT masters
From: Oza Oza @ 2017-04-22 8:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <67d1f46172599be243405f4341665fd0ef9ab969.1490726288.git.robin.murphy@arm.com>
On Wed, Mar 29, 2017 at 12:27 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> For PCI masters not represented in DT, we pass the OF node of their
> associated host bridge to of_dma_configure(), such that they can inherit
> the appropriate DMA configuration from whatever is described there.
> Unfortunately, whilst this has worked for the "dma-coherent" property,
> it turns out to miss the case where the host bridge node has a non-empty
> "dma-ranges", since nobody is expecting the 'device' to be a bus itself.
>
> It transpires, though, that the de-facto interface since the prototype
> change in 1f5c69aa51f9 ("of: Move of_dma_configure() to device.c to help
> re-use") is very clear-cut: either the master_np argument is redundant
> with dev->of_node, or dev->of_node is NULL and master_np is the relevant
> parent bus. Let's ratify that behaviour, then teach the whole
> of_dma_configure() pipeline to cope with both cases properly.
>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
>
> This is what I'd consider the better fix - rather than adding yet more
> special cases - which will also make it simple to handle multiple
> "dma-ranges" entries with minimal further disruption. The callers now
> left passing dev->of_node as 'parent' are harmless, but look a bit silly
> and clearly want cleaning up - I'd be partial to renaming the existing
> function and having a single-argument wrapper for the 'normal' case, e.g.:
>
> static inline int of_dma_configure(struct device_node *dev)
> {
> return of_dma_configure_parent(dev, NULL);
> }
>
> Thoughts?
>
> Robin.
>
> drivers/iommu/of_iommu.c | 7 ++++---
> drivers/of/address.c | 37 +++++++++++++++++++++++++------------
> drivers/of/device.c | 12 +++++++-----
> include/linux/of_address.h | 7 ++++---
> include/linux/of_device.h | 4 ++--
> include/linux/of_iommu.h | 4 ++--
> 6 files changed, 44 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index 2683e9fc0dcf..35aff07bb5eb 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -138,21 +138,22 @@ static const struct iommu_ops
> }
>
> const struct iommu_ops *of_iommu_configure(struct device *dev,
> - struct device_node *master_np)
> + struct device_node *parent)
> {
> struct of_phandle_args iommu_spec;
> - struct device_node *np;
> + struct device_node *np, *master_np;
> const struct iommu_ops *ops = NULL;
> int idx = 0;
>
> if (dev_is_pci(dev))
> - return of_pci_iommu_configure(to_pci_dev(dev), master_np);
> + return of_pci_iommu_configure(to_pci_dev(dev), parent);
>
> /*
> * We don't currently walk up the tree looking for a parent IOMMU.
> * See the `Notes:' section of
> * Documentation/devicetree/bindings/iommu/iommu.txt
> */
> + master_np = dev->of_node ? dev->of_node : parent;
> while (!of_parse_phandle_with_args(master_np, "iommus",
> "#iommu-cells", idx,
> &iommu_spec)) {
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..833bc17f5e55 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -808,6 +808,7 @@ EXPORT_SYMBOL(of_io_request_and_map);
> /**
> * of_dma_get_range - Get DMA range info
> * @np: device node to get DMA range info
> + * @parent: node of device's parent bus, if @np is NULL
> * @dma_addr: pointer to store initial DMA address of DMA range
> * @paddr: pointer to store initial CPU address of DMA range
> * @size: pointer to store size of DMA range
> @@ -822,36 +823,48 @@ EXPORT_SYMBOL(of_io_request_and_map);
> * It returns -ENODEV if "dma-ranges" property was not found
> * for this device in DT.
> */
> -int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size)
> +int of_dma_get_range(struct device_node *np, struct device_node *parent,
> + u64 *dma_addr, u64 *paddr, u64 *size)
> {
> - struct device_node *node = of_node_get(np);
> + struct device_node *node;
> const __be32 *ranges = NULL;
> int len, naddr, nsize, pna;
> int ret = 0;
> u64 dmaaddr;
>
> - if (!node)
> - return -EINVAL;
> -
> - while (1) {
> + if (np) {
> + node = of_node_get(np);
> naddr = of_n_addr_cells(node);
> nsize = of_n_size_cells(node);
> node = of_get_next_parent(node);
> - if (!node)
> - break;
> + } else if (parent) {
> + node = of_node_get(parent);
> + np = parent;
> + if (of_property_read_u32(node, "#address-cells", &naddr))
> + naddr = of_n_addr_cells(node);
> + if (of_property_read_u32(node, "#size-cells", &nsize))
> + nsize = of_n_size_cells(node);
> + } else {
> + return -EINVAL;
> + }
>
> + while (node) {
> ranges = of_get_property(node, "dma-ranges", &len);
>
> - /* Ignore empty ranges, they imply no translation required */
> - if (ranges && len > 0)
> - break;
> -
> /*
> * At least empty ranges has to be defined for parent node if
> * DMA is supported
> */
> if (!ranges)
> break;
> +
> + /* Ignore empty ranges, they imply no translation required */
> + if (len > 0)
> + break;
> +
> + naddr = of_n_addr_cells(node);
> + nsize = of_n_size_cells(node);
> + node = of_get_next_parent(node);
> }
>
> if (!ranges) {
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index 9bb8518b28f2..57ec5324ed6c 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -73,7 +73,8 @@ int of_device_add(struct platform_device *ofdev)
> /**
> * of_dma_configure - Setup DMA configuration
> * @dev: Device to apply DMA configuration
> - * @np: Pointer to OF node having DMA configuration
> + * @parent: OF node of device's parent bus, if @dev is not
> + * represented in DT (i.e. @dev->of_node is NULL)
> *
> * Try to get devices's DMA configuration from DT and update it
> * accordingly.
> @@ -82,13 +83,14 @@ int of_device_add(struct platform_device *ofdev)
> * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
> * to fix up DMA configuration.
> */
> -void of_dma_configure(struct device *dev, struct device_node *np)
> +void of_dma_configure(struct device *dev, struct device_node *parent)
> {
> u64 dma_addr, paddr, size;
> int ret;
> bool coherent;
> unsigned long offset;
> const struct iommu_ops *iommu;
> + struct device_node *np = dev->of_node;
>
> /*
> * Set default coherent_dma_mask to 32 bit. Drivers are expected to
> @@ -104,7 +106,7 @@ void of_dma_configure(struct device *dev, struct device_node *np)
> if (!dev->dma_mask)
> dev->dma_mask = &dev->coherent_dma_mask;
>
> - ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
> + ret = of_dma_get_range(np, parent, &dma_addr, &paddr, &size);
> if (ret < 0) {
> dma_addr = offset = 0;
> size = dev->coherent_dma_mask + 1;
> @@ -132,11 +134,11 @@ void of_dma_configure(struct device *dev, struct device_node *np)
> dev->coherent_dma_mask = DMA_BIT_MASK(ilog2(dma_addr + size));
> *dev->dma_mask = dev->coherent_dma_mask;
>
> - coherent = of_dma_is_coherent(np);
> + coherent = of_dma_is_coherent(np ? np : parent);
> dev_dbg(dev, "device is%sdma coherent\n",
> coherent ? " " : " not ");
>
> - iommu = of_iommu_configure(dev, np);
> + iommu = of_iommu_configure(dev, parent);
> dev_dbg(dev, "device is%sbehind an iommu\n",
> iommu ? " " : " not ");
>
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 37864734ca50..f1a507f3ae57 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -52,8 +52,8 @@ extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
> extern struct of_pci_range *of_pci_range_parser_one(
> struct of_pci_range_parser *parser,
> struct of_pci_range *range);
> -extern int of_dma_get_range(struct device_node *np, u64 *dma_addr,
> - u64 *paddr, u64 *size);
> +extern int of_dma_get_range(struct device_node *np, struct device_node *parent,
> + u64 *dma_addr, u64 *paddr, u64 *size);
> extern bool of_dma_is_coherent(struct device_node *np);
> #else /* CONFIG_OF_ADDRESS */
> static inline void __iomem *of_io_request_and_map(struct device_node *device,
> @@ -95,7 +95,8 @@ static inline struct of_pci_range *of_pci_range_parser_one(
> return NULL;
> }
>
> -static inline int of_dma_get_range(struct device_node *np, u64 *dma_addr,
> +static inline int of_dma_get_range(struct device_node *np,
> + struct device_node *parent, u64 *dma_addr,
> u64 *paddr, u64 *size)
> {
> return -ENODEV;
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index c12dace043f3..bcd2b6fbeef3 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -55,7 +55,7 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
> return of_node_get(cpu_dev->of_node);
> }
>
> -void of_dma_configure(struct device *dev, struct device_node *np);
> +void of_dma_configure(struct device *dev, struct device_node *parent);
> #else /* CONFIG_OF */
>
> static inline int of_driver_match_device(struct device *dev,
> @@ -103,7 +103,7 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
> {
> return NULL;
> }
> -static inline void of_dma_configure(struct device *dev, struct device_node *np)
> +static inline void of_dma_configure(struct device *dev, struct device_node *parent)
> {}
> #endif /* CONFIG_OF */
>
> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 13394ac83c66..c02b62e8e6ed 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -12,7 +12,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
> size_t *size);
>
> extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> - struct device_node *master_np);
> + struct device_node *parent);
>
> #else
>
> @@ -24,7 +24,7 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
> }
>
> static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
> - struct device_node *master_np)
> + struct device_node *parent)
> {
> return NULL;
> }
> --
> 2.11.0.dirty
>
Hi Robin,
After some more thoughts to this, I have improved upon old patch design.
please check https://lkml.org/lkml/2017/4/22/34
this patch served following purposes
1) exposes intrface to the pci host driver for thir inbound memory ranges
2) provide an interface to callers such as of_dma_get_ranges.
so then the returned size get best possible (largest) dma_mask.
for e.g.
dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>;
we should get dev->coherent_dma_mask=0x7fffffffff.
3) this patch handles multiple inbound windows and dma-ranges.
it is left to the caller, how it wants to use them.
the new function returns the resources in a standard and unform way
4) this way the callers of of_dma_get_ranges does not need to change.
and
5) leaves scope of adding PCI flag handling for inbound memory
by the new function.
which I feel much better approach/way than accommodating
of_dma_get_ranges to handle multiple dma-ranges, addressing PCI
masters.
also in your patch I think, you have to make emulated parent node
which is more work I suppose.
again I have tested this on our SOC and it works well.
Regards,
Oza.
^ permalink raw reply
* linux-next: build failure after merge of the arm tree
From: Mason @ 2017-04-22 8:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170421234315.GO17774@n2100.armlinux.org.uk>
On 22/04/2017 01:43, Russell King - ARM Linux wrote:
> Or I drop the offending patch (done) and we get the DMA subsystem fixed
> first. Given how long it's been this way, I doubt there's any hurry to
> get this change in for the next merge window.
Your solution makes sense.
Vinod, could you apply [PATCH v2] dmaengine: sun4i: fix invalid argument
to your tree when you have the time?
Regards.
^ permalink raw reply
* [RFC PATH] of/pci/dma: fix DMA configruation for PCI masters
From: Oza Pawandeep @ 2017-04-22 8:08 UTC (permalink / raw)
To: linux-arm-kernel
current device frmework and of framework integration assumes dma-ranges
in a way where memory-mapped devices define their dma-ranges.
dma-ranges: (child-bus-address, parent-bus-address, length).
but iproc based SOCs and other SOCs(suc as rcar) have PCI world dma-ranges.
dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>;
of_dma_configure is specifically witten to take care of memory mapped devices.
but no implementation exists for pci to take care of pcie based memory ranges.
in fact pci world doesnt seem to define standard dma-ranges
this patch served following purposes
1) exposes intrface to the pci host driver for thir inbound memory ranges
2) provide an interface to callers such as of_dma_get_ranges.
so then the returned size get best possible (largest) dma_mask.
for e.g.
dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>;
we should get dev->coherent_dma_mask=0x7fffffffff.
3) this patch handles multiple inbound windows and dma-ranges.
it is left to the caller, how it wants to use them.
the new function returns the resources in a standard and unform way
4) this way the callers of of_dma_get_ranges does not need to change.
and
5) leaves scope of adding PCI flag handling for inbound memory
by the new function.
Signed-off-by: Oza Pawandeep <oza.oza@broadcom.com>
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..ec21191 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -6,6 +6,7 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/sizes.h>
@@ -829,10 +830,30 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz
int len, naddr, nsize, pna;
int ret = 0;
u64 dmaaddr;
+ struct resource_entry *window;
+ LIST_HEAD(res);
if (!node)
return -EINVAL;
+ if (strcmp(np->name, "pci")) {
+ *size = 0;
+ ret = of_pci_get_dma_ranges(np, &res);
+ if (!ret) {
+ resource_list_for_each_entry(window, &res) {
+ struct resource *res_dma = window->res;
+
+ if (*size < resource_size(res_dma)) {
+ *dma_addr = res_dma->start - window->offset;
+ *paddr = res_dma->start;
+ *size = resource_size(res_dma);
+ }
+ }
+ }
+ pci_free_resource_list(&res);
+ goto out;
+ }
+
while (1) {
naddr = of_n_addr_cells(node);
nsize = of_n_size_cells(node);
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 0ee42c3..2aa9401 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -283,6 +283,83 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
return err;
}
EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
+
+/**
+ * of_pci_get_dma_ranges - Parse PCI host bridge inbound resources from DT
+ * @np: device node of the host bridge having the dma-ranges property
+ * @resources: list where the range of resources will be added after DT parsing
+ *
+ * It is the caller's job to free the @resources list.
+ *
+ * This function will parse the "dma-ranges" property of a
+ * PCI host bridge device node and setup the resource mapping based
+ * on its content.
+ *
+ * It returns zero if the range parsing has been successful or a standard error
+ * value if it failed.
+ */
+
+int of_pci_get_dma_ranges(struct device_node *np, struct list_head *resources)
+{
+ struct device_node *node = of_node_get(np);
+ int rlen;
+ int ret = 0;
+ const int na = 3, ns = 2;
+ struct resource *res;
+ struct of_pci_range_parser parser;
+ struct of_pci_range range;
+
+ if (!node)
+ return -EINVAL;
+
+ parser.node = node;
+ parser.pna = of_n_addr_cells(node);
+ parser.np = parser.pna + na + ns;
+
+ parser.range = of_get_property(node, "dma-ranges", &rlen);
+
+ if (!parser.range) {
+ pr_debug("pcie device has no dma-ranges defined for node(%s)\n",
+ np->full_name);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ parser.end = parser.range + rlen / sizeof(__be32);
+
+ for_each_of_pci_range(&parser, &range) {
+ /*
+ * If we failed translation or got a zero-sized region
+ * then skip this range
+ */
+ if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+ continue;
+
+ res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ if (!res) {
+ ret = -ENOMEM;
+ goto parse_failed;
+ }
+
+ ret = of_pci_range_to_resource(&range, np, res);
+ if (ret) {
+ kfree(res);
+ continue;
+ }
+
+ pci_add_resource_offset(resources, res,
+ res->start - range.pci_addr);
+ }
+
+ return ret;
+
+parse_failed:
+ pci_free_resource_list(resources);
+out:
+ of_node_put(node);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_dma_ranges);
#endif /* CONFIG_OF_ADDRESS */
#ifdef CONFIG_PCI_MSI
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 0e0974e..617b90d 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -76,6 +76,7 @@ static inline void of_pci_check_probe_only(void) { }
int of_pci_get_host_bridge_resources(struct device_node *dev,
unsigned char busno, unsigned char bus_max,
struct list_head *resources, resource_size_t *io_base);
+int of_pci_get_dma_ranges(struct device_node *np, struct list_head *resources);
#else
static inline int of_pci_get_host_bridge_resources(struct device_node *dev,
unsigned char busno, unsigned char bus_max,
@@ -83,6 +84,12 @@ static inline int of_pci_get_host_bridge_resources(struct device_node *dev,
{
return -EINVAL;
}
+
+static inline int of_pci_get_dma_ranges(struct device_node *np,
+ struct list_head *resources)
+{
+ return -EINVAL;
+}
#endif
#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 1/3] clk: add clk_bulk_get accessories
From: Stephen Boyd @ 2017-04-22 3:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1491969809-20154-2-git-send-email-aisheng.dong@nxp.com>
On 04/12, Dong Aisheng wrote:
>
> #ifdef CONFIG_HAVE_CLK
> @@ -230,6 +257,32 @@ static inline void clk_unprepare(struct clk *clk)
> struct clk *clk_get(struct device *dev, const char *id);
>
> /**
> + * clk_bulk_get - lookup and obtain a number of references to clock producer.
> + * @dev: device for clock "consumer"
> + * @num_clks: the number of clk_bulk_data
> + * @clks: the clk_bulk_data table of consumer
> + *
> + * This helper function allows drivers to get several clk consumers in one
> + * operation. If any of the clk cannot be acquired then any clks
> + * that were obtained will be freed before returning to the caller.
> + *
> + * Returns 0 if all clocks specified in clk_bulk_data table are obtained
> + * successfully, or valid IS_ERR() condition containing errno.
> + * The implementation uses @dev and @clk_bulk_data.id to determine the
> + * clock consumer, and thereby the clock producer.
> + * (IOW, @id may be identical strings, but clk_get may return different
> + * clock producers depending on @dev.) The clock returned is stored in
This comment is inaccurate. Only one dev is possible with this
API.
> + * each @clk_bulk_data.clk field.
> + *
> + * Drivers must assume that the clock source is not enabled.
> + *
> + * clk_bulk_get should not be called from within interrupt context.
> + */
> +
Drop space.
> +int __must_check clk_bulk_get(struct device *dev, int num_clks,
> + struct clk_bulk_data *clks);
> +
> +/**
> * devm_clk_get - lookup and obtain a managed reference to a clock producer.
> * @dev: device for clock "consumer"
> * @id: clock consumer ID
> @@ -279,6 +332,20 @@ struct clk *devm_get_clk_from_child(struct device *dev,
> int clk_enable(struct clk *clk);
>
> /**
> + * clk_bulk_enable - inform the system when the bulk of clock source should
> + * be running.
> + * @num_clks: the number of clk_bulk_data
> + * @clks: the clk_bulk_data table of consumer
> + *
> + * If the clock can not be enabled/disabled all, this should return success.
> + *
> + * May be called from atomic contexts.
> + *
> + * Returns success (0) or negative errno.
> + */
> +int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks);
> +
> +/**
> * clk_disable - inform the system when the clock source is no longer required.
> * @clk: clock source
> *
> @@ -295,6 +362,24 @@ int clk_enable(struct clk *clk);
> void clk_disable(struct clk *clk);
>
> /**
> + * clk_bulk_disable - inform the system when the bulk of clock source is no
> + * longer required.
> + * @num_clks: the number of clk_bulk_data
> + * @clks: the clk_bulk_data table of consumer
> + *
> + * Inform the system that a bulk of clock source is no longer required by
> + * a driver and may be shut down.
> + *
> + * May be called from atomic contexts.
> + *
> + * Implementation detail: if the bulk of clock source is shared between
I'm not sure "bulk of clock source" is the correct terminology.
Perhaps "set of clks"?
> + * multiple drivers, clk_bulk_enable() calls must be balanced by the
> + * same number of clk_bulk_disable() calls for the clock source to be
> + * disabled.
> + */
> +void clk_bulk_disable(int num_clks, struct clk_bulk_data *clks);
We can mark clk_bulk_data structure as const here? Probably
applies in other places as well in this patch.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [RFC] minimum gcc version for kernel: raise to gcc-4.3 or 4.6?
From: Maciej W. Rozycki @ 2017-04-22 3:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGXu5jJpofLF0qAf0-2iNTesZt-X704Q7L=DpQYdtHY5n2HD0w@mail.gmail.com>
On Fri, 21 Apr 2017, Kees Cook wrote:
> > The linux-4.2 x86 defconfig could still be built with gcc-4.0, but
> > later kernels have several minor problems with that, and
> > require at least gcc-4.3.
> >
> > If we are ok with this status quo, we could simply declare gcc-4.3
> > the absolute minimum version for the kernel, make gcc-4.9
> > the recommeded minimum version, and remove all workarounds
> > for gcc-4.2 or older.
>
> I think starting with this would be a good first step. I'm not sure
> the best way to add "recommended minimum" to
> Documentation/process/changes.rst hmmm
FWIW for some reasons (mainly the ability to avoid NPTL) I have stuck to
GCC 4.1.2 with some MIPS configurations and I've had no issues with that
compiler up to Linux 4.6.0, which is the last kernel version I have tried
with that compiler so far. I could check if anything has regressed since
then I suppose.
Maciej
^ permalink raw reply
* [RFC PATCH 0/3] clk: introduce clk_bulk_get accessories
From: Stephen Boyd @ 2017-04-22 3:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1491969809-20154-1-git-send-email-aisheng.dong@nxp.com>
On 04/12, Dong Aisheng wrote:
>
> Together with the err path handling for each clocks, it does make
> things a bit ugly.
>
> Since we already have regulator_bulk_get accessories, i thought we
> probably could introduce clk_bulk_get as well to handle such case to
> ease the driver owners' life.
>
> Besides IMX cpufreq driver, there is also some similar cases
> in kernel which could befinit from this api as well.
> e.g.
> drivers/cpufreq/tegra124-cpufreq.c
> drivers/cpufreq/s3c2412-cpufreq.c
> sound/soc/samsung/smdk_spdif.c
> arch/arm/mach-omap1/serial.c
> ...
>
> And actually, if we handle clocks more than 3, then it might be
> worthy to try, which there is quite many manay in kernel and
> that probably could save a lot codes.
>
> This is a RFC patch intending to bring up the idea to discuss.
>
Idea seems fine to me. Please also add Russell King, as we need
an ack from him on the clk.h API changes.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [RFC PATCH 2/3] clk: add managed version of clk_bulk_get
From: Stephen Boyd @ 2017-04-22 2:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170413143727.GE24254@b29396-OptiPlex-7040>
On 04/13, Dong Aisheng wrote:
> On Wed, Apr 12, 2017 at 12:03:28PM +0800, Dong Aisheng wrote:
>
> drivers/built-in.o: In function `devm_clk_bulk_get':
> >> (.text+0x1930e): undefined reference to `clk_bulk_get'
> drivers/built-in.o: In function `devm_clk_bulk_release':
> >> clk-devres.c:(.text+0x19370): undefined reference to `clk_bulk_put'
>
> clk_bulk_get is defined in clkdev.c which depends on CONFIG_CLKDEV_LOOKUP.
> However, some platforms like m68k may not select CLKDEV_LOOKUP but
> select HAVE_CLK. Thus compiling devm_clk_bulk_get may cause a undefined
> reference to 'clk_bulk_get'.
>
> Since clk_bulk_get is built upon the platform specific clk_get api,
> clk_bulk_get can also be used by that platform accordingly.
>
> Then we probably could move clk_bulk_get into clk-devres.c as well which
> is controlled by common CONFIG_HAVE_CLK to benifit all platforms.
clk-devres is for devm* things. I'd just make another file for
now, clk-bulk.c or something like that. When everyone moves to
common clk, we can fold it into clk.c, or not because clk.c is
rather large right now.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [RFC PATCH 2/3] clk: add managed version of clk_bulk_get
From: Stephen Boyd @ 2017-04-22 2:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1491969809-20154-3-git-send-email-aisheng.dong@nxp.com>
On 04/12, Dong Aisheng wrote:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d05b66..3fc6010 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -278,11 +278,25 @@ struct clk *clk_get(struct device *dev, const char *id);
> *
> * clk_bulk_get should not be called from within interrupt context.
> */
> -
Should be in previous patch?
> int __must_check clk_bulk_get(struct device *dev, int num_clks,
> struct clk_bulk_data *clks);
>
> /**
> + * devm_clk_bulk_get - managed get multiple clk consumers
> + * @dev: device for clock "consumer"
> + * @num_clks: the number of clk_bulk_data
> + * @clks: the clk_bulk_data table of consumer
> + *
> + * Return 0 on success, an errno on failure.
> + *
> + * This helper function allows drivers to get several regulator
s/regulator/clk/
> + * consumers in one operation with management, the clks will
> + * automatically be freed when the device is unbound.
> + */
> +int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
Thanks for the __must_check. We need to add more __must_check to
clk APIs.
> + struct clk_bulk_data *clks);
> +
> +/**
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH 5/5 v3] ARM: dts: Add the FOTG210 USB host to Gemini
From: kbuild test robot @ 2017-04-22 2:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170421204058.6206-5-linus.walleij@linaro.org>
Hi Linus,
[auto build test ERROR on next-20170421]
[cannot apply to robh/for-next usb/usb-testing balbi-usb/next v4.9-rc8 v4.9-rc7 v4.9-rc6 v4.11-rc7]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Linus-Walleij/usb-host-add-DT-bindings-for-faraday-fotg2/20170422-072414
config: arm-sama5_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All errors (new ones prefixed by >>):
>> Error: arch/arm/boot/dts/gemini.dtsi:161.19-20 syntax error
FATAL ERROR: Unable to parse input tree
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 24300 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170422/a2a86dda/attachment-0001.gz>
^ permalink raw reply
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