Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
0004  */
0005 
0006 #include <linux/clk.h>
0007 #include <linux/clk-provider.h>
0008 #include <linux/module.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/reset.h>
0011 
0012 #include "ccu_common.h"
0013 #include "ccu_div.h"
0014 #include "ccu_gate.h"
0015 #include "ccu_reset.h"
0016 
0017 #include "ccu-sun9i-a80-de.h"
0018 
0019 static SUNXI_CCU_GATE(fe0_clk,      "fe0",      "fe0-div",
0020               0x00, BIT(0), 0);
0021 static SUNXI_CCU_GATE(fe1_clk,      "fe1",      "fe1-div",
0022               0x00, BIT(1), 0);
0023 static SUNXI_CCU_GATE(fe2_clk,      "fe2",      "fe2-div",
0024               0x00, BIT(2), 0);
0025 static SUNXI_CCU_GATE(iep_deu0_clk, "iep-deu0", "de",
0026               0x00, BIT(4), 0);
0027 static SUNXI_CCU_GATE(iep_deu1_clk, "iep-deu1", "de",
0028               0x00, BIT(5), 0);
0029 static SUNXI_CCU_GATE(be0_clk,      "be0",      "be0-div",
0030               0x00, BIT(8), 0);
0031 static SUNXI_CCU_GATE(be1_clk,      "be1",      "be1-div",
0032               0x00, BIT(9), 0);
0033 static SUNXI_CCU_GATE(be2_clk,      "be2",      "be2-div",
0034               0x00, BIT(10), 0);
0035 static SUNXI_CCU_GATE(iep_drc0_clk, "iep-drc0", "de",
0036               0x00, BIT(12), 0);
0037 static SUNXI_CCU_GATE(iep_drc1_clk, "iep-drc1", "de",
0038               0x00, BIT(13), 0);
0039 static SUNXI_CCU_GATE(merge_clk,    "merge",    "de",
0040               0x00, BIT(20), 0);
0041 
0042 static SUNXI_CCU_GATE(dram_fe0_clk, "dram-fe0", "sdram",
0043               0x04, BIT(0), 0);
0044 static SUNXI_CCU_GATE(dram_fe1_clk, "dram-fe1", "sdram",
0045               0x04, BIT(1), 0);
0046 static SUNXI_CCU_GATE(dram_fe2_clk, "dram-fe2", "sdram",
0047               0x04, BIT(2), 0);
0048 static SUNXI_CCU_GATE(dram_deu0_clk,    "dram-deu0",    "sdram",
0049               0x04, BIT(4), 0);
0050 static SUNXI_CCU_GATE(dram_deu1_clk,    "dram-deu1",    "sdram",
0051               0x04, BIT(5), 0);
0052 static SUNXI_CCU_GATE(dram_be0_clk, "dram-be0", "sdram",
0053               0x04, BIT(8), 0);
0054 static SUNXI_CCU_GATE(dram_be1_clk, "dram-be1", "sdram",
0055               0x04, BIT(9), 0);
0056 static SUNXI_CCU_GATE(dram_be2_clk, "dram-be2", "sdram",
0057               0x04, BIT(10), 0);
0058 static SUNXI_CCU_GATE(dram_drc0_clk,    "dram-drc0",    "sdram",
0059               0x04, BIT(12), 0);
0060 static SUNXI_CCU_GATE(dram_drc1_clk,    "dram-drc1",    "sdram",
0061               0x04, BIT(13), 0);
0062 
0063 static SUNXI_CCU_GATE(bus_fe0_clk,  "bus-fe0",  "bus-de",
0064               0x08, BIT(0), 0);
0065 static SUNXI_CCU_GATE(bus_fe1_clk,  "bus-fe1",  "bus-de",
0066               0x08, BIT(1), 0);
0067 static SUNXI_CCU_GATE(bus_fe2_clk,  "bus-fe2",  "bus-de",
0068               0x08, BIT(2), 0);
0069 static SUNXI_CCU_GATE(bus_deu0_clk, "bus-deu0", "bus-de",
0070               0x08, BIT(4), 0);
0071 static SUNXI_CCU_GATE(bus_deu1_clk, "bus-deu1", "bus-de",
0072               0x08, BIT(5), 0);
0073 static SUNXI_CCU_GATE(bus_be0_clk,  "bus-be0",  "bus-de",
0074               0x08, BIT(8), 0);
0075 static SUNXI_CCU_GATE(bus_be1_clk,  "bus-be1",  "bus-de",
0076               0x08, BIT(9), 0);
0077 static SUNXI_CCU_GATE(bus_be2_clk,  "bus-be2",  "bus-de",
0078               0x08, BIT(10), 0);
0079 static SUNXI_CCU_GATE(bus_drc0_clk, "bus-drc0", "bus-de",
0080               0x08, BIT(12), 0);
0081 static SUNXI_CCU_GATE(bus_drc1_clk, "bus-drc1", "bus-de",
0082               0x08, BIT(13), 0);
0083 
0084 static SUNXI_CCU_M(fe0_div_clk, "fe0-div", "de", 0x20, 0, 4, 0);
0085 static SUNXI_CCU_M(fe1_div_clk, "fe1-div", "de", 0x20, 4, 4, 0);
0086 static SUNXI_CCU_M(fe2_div_clk, "fe2-div", "de", 0x20, 8, 4, 0);
0087 static SUNXI_CCU_M(be0_div_clk, "be0-div", "de", 0x20, 16, 4, 0);
0088 static SUNXI_CCU_M(be1_div_clk, "be1-div", "de", 0x20, 20, 4, 0);
0089 static SUNXI_CCU_M(be2_div_clk, "be2-div", "de", 0x20, 24, 4, 0);
0090 
0091 static struct ccu_common *sun9i_a80_de_clks[] = {
0092     &fe0_clk.common,
0093     &fe1_clk.common,
0094     &fe2_clk.common,
0095     &iep_deu0_clk.common,
0096     &iep_deu1_clk.common,
0097     &be0_clk.common,
0098     &be1_clk.common,
0099     &be2_clk.common,
0100     &iep_drc0_clk.common,
0101     &iep_drc1_clk.common,
0102     &merge_clk.common,
0103 
0104     &dram_fe0_clk.common,
0105     &dram_fe1_clk.common,
0106     &dram_fe2_clk.common,
0107     &dram_deu0_clk.common,
0108     &dram_deu1_clk.common,
0109     &dram_be0_clk.common,
0110     &dram_be1_clk.common,
0111     &dram_be2_clk.common,
0112     &dram_drc0_clk.common,
0113     &dram_drc1_clk.common,
0114 
0115     &bus_fe0_clk.common,
0116     &bus_fe1_clk.common,
0117     &bus_fe2_clk.common,
0118     &bus_deu0_clk.common,
0119     &bus_deu1_clk.common,
0120     &bus_be0_clk.common,
0121     &bus_be1_clk.common,
0122     &bus_be2_clk.common,
0123     &bus_drc0_clk.common,
0124     &bus_drc1_clk.common,
0125 
0126     &fe0_div_clk.common,
0127     &fe1_div_clk.common,
0128     &fe2_div_clk.common,
0129     &be0_div_clk.common,
0130     &be1_div_clk.common,
0131     &be2_div_clk.common,
0132 };
0133 
0134 static struct clk_hw_onecell_data sun9i_a80_de_hw_clks = {
0135     .hws    = {
0136         [CLK_FE0]   = &fe0_clk.common.hw,
0137         [CLK_FE1]   = &fe1_clk.common.hw,
0138         [CLK_FE2]   = &fe2_clk.common.hw,
0139         [CLK_IEP_DEU0]  = &iep_deu0_clk.common.hw,
0140         [CLK_IEP_DEU1]  = &iep_deu1_clk.common.hw,
0141         [CLK_BE0]   = &be0_clk.common.hw,
0142         [CLK_BE1]   = &be1_clk.common.hw,
0143         [CLK_BE2]   = &be2_clk.common.hw,
0144         [CLK_IEP_DRC0]  = &iep_drc0_clk.common.hw,
0145         [CLK_IEP_DRC1]  = &iep_drc1_clk.common.hw,
0146         [CLK_MERGE] = &merge_clk.common.hw,
0147 
0148         [CLK_DRAM_FE0]  = &dram_fe0_clk.common.hw,
0149         [CLK_DRAM_FE1]  = &dram_fe1_clk.common.hw,
0150         [CLK_DRAM_FE2]  = &dram_fe2_clk.common.hw,
0151         [CLK_DRAM_DEU0] = &dram_deu0_clk.common.hw,
0152         [CLK_DRAM_DEU1] = &dram_deu1_clk.common.hw,
0153         [CLK_DRAM_BE0]  = &dram_be0_clk.common.hw,
0154         [CLK_DRAM_BE1]  = &dram_be1_clk.common.hw,
0155         [CLK_DRAM_BE2]  = &dram_be2_clk.common.hw,
0156         [CLK_DRAM_DRC0] = &dram_drc0_clk.common.hw,
0157         [CLK_DRAM_DRC1] = &dram_drc1_clk.common.hw,
0158 
0159         [CLK_BUS_FE0]   = &bus_fe0_clk.common.hw,
0160         [CLK_BUS_FE1]   = &bus_fe1_clk.common.hw,
0161         [CLK_BUS_FE2]   = &bus_fe2_clk.common.hw,
0162         [CLK_BUS_DEU0]  = &bus_deu0_clk.common.hw,
0163         [CLK_BUS_DEU1]  = &bus_deu1_clk.common.hw,
0164         [CLK_BUS_BE0]   = &bus_be0_clk.common.hw,
0165         [CLK_BUS_BE1]   = &bus_be1_clk.common.hw,
0166         [CLK_BUS_BE2]   = &bus_be2_clk.common.hw,
0167         [CLK_BUS_DRC0]  = &bus_drc0_clk.common.hw,
0168         [CLK_BUS_DRC1]  = &bus_drc1_clk.common.hw,
0169 
0170         [CLK_FE0_DIV]   = &fe0_div_clk.common.hw,
0171         [CLK_FE1_DIV]   = &fe1_div_clk.common.hw,
0172         [CLK_FE2_DIV]   = &fe2_div_clk.common.hw,
0173         [CLK_BE0_DIV]   = &be0_div_clk.common.hw,
0174         [CLK_BE1_DIV]   = &be1_div_clk.common.hw,
0175         [CLK_BE2_DIV]   = &be2_div_clk.common.hw,
0176     },
0177     .num    = CLK_NUMBER,
0178 };
0179 
0180 static struct ccu_reset_map sun9i_a80_de_resets[] = {
0181     [RST_FE0]   = { 0x0c, BIT(0) },
0182     [RST_FE1]   = { 0x0c, BIT(1) },
0183     [RST_FE2]   = { 0x0c, BIT(2) },
0184     [RST_DEU0]  = { 0x0c, BIT(4) },
0185     [RST_DEU1]  = { 0x0c, BIT(5) },
0186     [RST_BE0]   = { 0x0c, BIT(8) },
0187     [RST_BE1]   = { 0x0c, BIT(9) },
0188     [RST_BE2]   = { 0x0c, BIT(10) },
0189     [RST_DRC0]  = { 0x0c, BIT(12) },
0190     [RST_DRC1]  = { 0x0c, BIT(13) },
0191     [RST_MERGE] = { 0x0c, BIT(20) },
0192 };
0193 
0194 static const struct sunxi_ccu_desc sun9i_a80_de_clk_desc = {
0195     .ccu_clks   = sun9i_a80_de_clks,
0196     .num_ccu_clks   = ARRAY_SIZE(sun9i_a80_de_clks),
0197 
0198     .hw_clks    = &sun9i_a80_de_hw_clks,
0199 
0200     .resets     = sun9i_a80_de_resets,
0201     .num_resets = ARRAY_SIZE(sun9i_a80_de_resets),
0202 };
0203 
0204 static int sun9i_a80_de_clk_probe(struct platform_device *pdev)
0205 {
0206     struct clk *bus_clk;
0207     struct reset_control *rstc;
0208     void __iomem *reg;
0209     int ret;
0210 
0211     reg = devm_platform_ioremap_resource(pdev, 0);
0212     if (IS_ERR(reg))
0213         return PTR_ERR(reg);
0214 
0215     bus_clk = devm_clk_get(&pdev->dev, "bus");
0216     if (IS_ERR(bus_clk)) {
0217         ret = PTR_ERR(bus_clk);
0218         if (ret != -EPROBE_DEFER)
0219             dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
0220         return ret;
0221     }
0222 
0223     rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
0224     if (IS_ERR(rstc)) {
0225         ret = PTR_ERR(rstc);
0226         if (ret != -EPROBE_DEFER)
0227             dev_err(&pdev->dev,
0228                 "Couldn't get reset control: %d\n", ret);
0229         return ret;
0230     }
0231 
0232     /* The bus clock needs to be enabled for us to access the registers */
0233     ret = clk_prepare_enable(bus_clk);
0234     if (ret) {
0235         dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
0236         return ret;
0237     }
0238 
0239     /* The reset control needs to be asserted for the controls to work */
0240     ret = reset_control_deassert(rstc);
0241     if (ret) {
0242         dev_err(&pdev->dev,
0243             "Couldn't deassert reset control: %d\n", ret);
0244         goto err_disable_clk;
0245     }
0246 
0247     ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_de_clk_desc);
0248     if (ret)
0249         goto err_assert_reset;
0250 
0251     return 0;
0252 
0253 err_assert_reset:
0254     reset_control_assert(rstc);
0255 err_disable_clk:
0256     clk_disable_unprepare(bus_clk);
0257     return ret;
0258 }
0259 
0260 static const struct of_device_id sun9i_a80_de_clk_ids[] = {
0261     { .compatible = "allwinner,sun9i-a80-de-clks" },
0262     { }
0263 };
0264 
0265 static struct platform_driver sun9i_a80_de_clk_driver = {
0266     .probe  = sun9i_a80_de_clk_probe,
0267     .driver = {
0268         .name   = "sun9i-a80-de-clks",
0269         .suppress_bind_attrs = true,
0270         .of_match_table = sun9i_a80_de_clk_ids,
0271     },
0272 };
0273 module_platform_driver(sun9i_a80_de_clk_driver);
0274 
0275 MODULE_IMPORT_NS(SUNXI_CCU);
0276 MODULE_LICENSE("GPL");