summaryrefslogtreecommitdiff
path: root/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-26 01:28:06 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-26 01:28:06 +0300
commit5d8a00eee2ed2e548a5d21b0edf495f3f7bf8bb4 (patch)
treefdc6c7754a5ea2a8a31df53e181e632e6e84b44f /drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
parent7067739df23ffd641ca99c967830e0ed2ba39eab (diff)
parentf59de563358eb9351b7f8f0ba2d3be2ebb70b93d (diff)
downloadlinux-5d8a00eee2ed2e548a5d21b0edf495f3f7bf8bb4.tar.xz
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk updates from Stephen Boyd: "The usual collection of new drivers, non-critical fixes, and updates to existing clk drivers. The bulk of the work is on Allwinner and Rockchip SoCs, but there's also an Intel Atom driver in here too. New Drivers: - Tegra BPMP firmware - Hisilicon hi3660 SoCs - Rockchip rk3328 SoCs - Intel Atom PMC - STM32F746 - IDT VersaClock 5P49V5923 and 5P49V5933 - Marvell mv98dx3236 SoCs - Allwinner V3s SoCs Removed Drivers: - Samsung Exynos4415 SoCs Updates: - Migrate ABx500 to OF - Qualcomm IPQ4019 CPU clks and general PLL support - Qualcomm MSM8974 RPM - Rockchip non-critical fixes and clk id additions - Samsung Exynos4412 CPUs - Socionext UniPhier NAND and eMMC support - ZTE zx296718 i2s and other audio clks - Renesas CAN and MSIOF clks for R-Car M3-W - Renesas resets for R-Car Gen2 and Gen3 and RZ/G1 - TI CDCE913, CDCE937, and CDCE949 clk generators - Marvell Armada ap806 CPU frequencies - STM32F4* I2S/SAI support - Broadcom BCM2835 DSI support - Allwinner sun5i and A80 conversion to new style clk bindings" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (130 commits) clk: renesas: mstp: ensure register writes complete clk: qcom: Do not drop device node twice clk: mvebu: adjust clock handling for the CP110 system controller clk: mvebu: Expand mv98dx3236-core-clock support clk: zte: add i2s clocks for zx296718 clk: sunxi-ng: sun9i-a80: Fix wrong pointer passed to PTR_ERR() clk: sunxi-ng: select SUNXI_CCU_MULT for sun5i clk: sunxi-ng: Check kzalloc() for errors and cleanup error path clk: tegra: Add BPMP clock driver clk: uniphier: add eMMC clock for LD11 and LD20 SoCs clk: uniphier: add NAND clock for all UniPhier SoCs ARM: dts: sun9i: Switch to new clock bindings clk: sunxi-ng: Add A80 Display Engine CCU clk: sunxi-ng: Add A80 USB CCU clk: sunxi-ng: Add A80 CCU clk: sunxi-ng: Support separately grouped PLL lock status register clk: sunxi-ng: mux: Get closest parent rate possible with CLK_SET_RATE_PARENT clk: sunxi-ng: mux: honor CLK_SET_RATE_NO_REPARENT flag clk: sunxi-ng: mux: Fix determine_rate for mux clocks with pre-dividers clk: qcom: SDHCI enablement on Nexus 5X / 6P ...
Diffstat (limited to 'drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c')
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
new file mode 100644
index 000000000000..1d76f24f7df3
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2016 Chen-Yu Tsai. 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.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_gate.h"
+#include "ccu_reset.h"
+
+#include "ccu-sun9i-a80-usb.h"
+
+static SUNXI_CCU_GATE(bus_hci0_clk, "bus-hci0", "bus-usb", 0x0, BIT(1), 0);
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc24M", 0x0, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_hci1_clk, "bus-hci1", "bus-usb", 0x0, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_hci2_clk, "bus-hci2", "bus-usb", 0x0, BIT(5), 0);
+static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc24M", 0x0, BIT(6), 0);
+
+static SUNXI_CCU_GATE(usb0_phy_clk, "usb0-phy", "osc24M", 0x4, BIT(1), 0);
+static SUNXI_CCU_GATE(usb1_hsic_clk, "usb1-hsic", "osc24M", 0x4, BIT(2), 0);
+static SUNXI_CCU_GATE(usb1_phy_clk, "usb1-phy", "osc24M", 0x4, BIT(3), 0);
+static SUNXI_CCU_GATE(usb2_hsic_clk, "usb2-hsic", "osc24M", 0x4, BIT(4), 0);
+static SUNXI_CCU_GATE(usb2_phy_clk, "usb2-phy", "osc24M", 0x4, BIT(5), 0);
+static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "osc24M", 0x4, BIT(10), 0);
+
+static struct ccu_common *sun9i_a80_usb_clks[] = {
+ &bus_hci0_clk.common,
+ &usb_ohci0_clk.common,
+ &bus_hci1_clk.common,
+ &bus_hci2_clk.common,
+ &usb_ohci2_clk.common,
+
+ &usb0_phy_clk.common,
+ &usb1_hsic_clk.common,
+ &usb1_phy_clk.common,
+ &usb2_hsic_clk.common,
+ &usb2_phy_clk.common,
+ &usb_hsic_clk.common,
+};
+
+static struct clk_hw_onecell_data sun9i_a80_usb_hw_clks = {
+ .hws = {
+ [CLK_BUS_HCI0] = &bus_hci0_clk.common.hw,
+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
+ [CLK_BUS_HCI1] = &bus_hci1_clk.common.hw,
+ [CLK_BUS_HCI2] = &bus_hci2_clk.common.hw,
+ [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw,
+
+ [CLK_USB0_PHY] = &usb0_phy_clk.common.hw,
+ [CLK_USB1_HSIC] = &usb1_hsic_clk.common.hw,
+ [CLK_USB1_PHY] = &usb1_phy_clk.common.hw,
+ [CLK_USB2_HSIC] = &usb2_hsic_clk.common.hw,
+ [CLK_USB2_PHY] = &usb2_phy_clk.common.hw,
+ [CLK_USB_HSIC] = &usb_hsic_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun9i_a80_usb_resets[] = {
+ [RST_USB0_HCI] = { 0x0, BIT(17) },
+ [RST_USB1_HCI] = { 0x0, BIT(18) },
+ [RST_USB2_HCI] = { 0x0, BIT(19) },
+
+ [RST_USB0_PHY] = { 0x4, BIT(17) },
+ [RST_USB1_HSIC] = { 0x4, BIT(18) },
+ [RST_USB1_PHY] = { 0x4, BIT(19) },
+ [RST_USB2_HSIC] = { 0x4, BIT(20) },
+ [RST_USB2_PHY] = { 0x4, BIT(21) },
+};
+
+static const struct sunxi_ccu_desc sun9i_a80_usb_clk_desc = {
+ .ccu_clks = sun9i_a80_usb_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun9i_a80_usb_clks),
+
+ .hw_clks = &sun9i_a80_usb_hw_clks,
+
+ .resets = sun9i_a80_usb_resets,
+ .num_resets = ARRAY_SIZE(sun9i_a80_usb_resets),
+};
+
+static int sun9i_a80_usb_clk_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct clk *bus_clk;
+ void __iomem *reg;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ bus_clk = devm_clk_get(&pdev->dev, "bus");
+ if (IS_ERR(bus_clk)) {
+ ret = PTR_ERR(bus_clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
+ return ret;
+ }
+
+ /* The bus clock needs to be enabled for us to access the registers */
+ ret = clk_prepare_enable(bus_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
+ return ret;
+ }
+
+ ret = sunxi_ccu_probe(pdev->dev.of_node, reg,
+ &sun9i_a80_usb_clk_desc);
+ if (ret)
+ goto err_disable_clk;
+
+ return 0;
+
+err_disable_clk:
+ clk_disable_unprepare(bus_clk);
+ return ret;
+}
+
+static const struct of_device_id sun9i_a80_usb_clk_ids[] = {
+ { .compatible = "allwinner,sun9i-a80-usb-clks" },
+ { }
+};
+
+static struct platform_driver sun9i_a80_usb_clk_driver = {
+ .probe = sun9i_a80_usb_clk_probe,
+ .driver = {
+ .name = "sun9i-a80-usb-clks",
+ .of_match_table = sun9i_a80_usb_clk_ids,
+ },
+};
+builtin_platform_driver(sun9i_a80_usb_clk_driver);