mirror of
https://github.com/torvalds/linux.git
synced 2024-12-19 01:23:20 +00:00
Merge tag 'sunxi-clk-for-3.15' of https://bitbucket.org/emiliolopez/linux into clk-next-sunxi
Allwinner sunXi SoCs clock changes This adds support for the new, more correct clock node naming and gets the A10 compatibles in line with the rest of the other SoCs. It also adds support for the USB, GMAC and A31's PLL6 clocks. Some of these changes also require DT modifications that will be merged via arm-soc.
This commit is contained in:
commit
df21f62bbb
@ -6,37 +6,41 @@ This binding uses the common clock binding[1].
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be one of the following:
|
||||
"allwinner,sun4i-osc-clk" - for a gatable oscillator
|
||||
"allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
|
||||
"allwinner,sun4i-a10-osc-clk" - for a gatable oscillator
|
||||
"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
|
||||
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
|
||||
"allwinner,sun4i-pll5-clk" - for the PLL5 clock
|
||||
"allwinner,sun4i-pll6-clk" - for the PLL6 clock
|
||||
"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
|
||||
"allwinner,sun4i-axi-clk" - for the AXI clock
|
||||
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
|
||||
"allwinner,sun4i-ahb-clk" - for the AHB clock
|
||||
"allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10
|
||||
"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
|
||||
"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
|
||||
"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
|
||||
"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
|
||||
"allwinner,sun4i-a10-axi-clk" - for the AXI clock
|
||||
"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
|
||||
"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
|
||||
"allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
|
||||
"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
|
||||
"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
|
||||
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
|
||||
"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
|
||||
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
|
||||
"allwinner,sun4i-apb0-clk" - for the APB0 clock
|
||||
"allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10
|
||||
"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
|
||||
"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
|
||||
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
|
||||
"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
|
||||
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
|
||||
"allwinner,sun4i-apb1-clk" - for the APB1 clock
|
||||
"allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing
|
||||
"allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10
|
||||
"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
|
||||
"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
|
||||
"allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
|
||||
"allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
|
||||
"allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
|
||||
"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
|
||||
"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
|
||||
"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
|
||||
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
|
||||
"allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
|
||||
"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
|
||||
"allwinner,sun7i-a20-out-clk" - for the external output clocks
|
||||
"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
|
||||
"allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
|
||||
"allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
|
||||
|
||||
Required properties for all clocks:
|
||||
- reg : shall be the control register address for the clock.
|
||||
@ -44,10 +48,17 @@ Required properties for all clocks:
|
||||
multiplexed clocks, the list order must match the hardware
|
||||
programming order.
|
||||
- #clock-cells : from common clock binding; shall be set to 0 except for
|
||||
"allwinner,*-gates-clk" where it shall be set to 1
|
||||
"allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk" and
|
||||
"allwinner,sun4i-pll6-clk" where it shall be set to 1
|
||||
- clock-output-names : shall be the corresponding names of the outputs.
|
||||
If the clock module only has one output, the name shall be the
|
||||
module name.
|
||||
|
||||
Additionally, "allwinner,*-gates-clk" clocks require:
|
||||
- clock-output-names : the corresponding gate names that the clock controls
|
||||
And "allwinner,*-usb-clk" clocks also require:
|
||||
- reset-cells : shall be set to 1
|
||||
|
||||
For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
|
||||
dummy clocks at 25 MHz and 125 MHz, respectively. See example.
|
||||
|
||||
Clock consumers should specify the desired clocks they use with a
|
||||
"clocks" phandle cell. Consumers that are using a gated clock should
|
||||
@ -56,23 +67,68 @@ offset of the bit controlling this particular gate in the register.
|
||||
|
||||
For example:
|
||||
|
||||
osc24M: osc24M@01c20050 {
|
||||
osc24M: clk@01c20050 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "allwinner,sun4i-osc-clk";
|
||||
compatible = "allwinner,sun4i-a10-osc-clk";
|
||||
reg = <0x01c20050 0x4>;
|
||||
clocks = <&osc24M_fixed>;
|
||||
clock-output-names = "osc24M";
|
||||
};
|
||||
|
||||
pll1: pll1@01c20000 {
|
||||
pll1: clk@01c20000 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "allwinner,sun4i-pll1-clk";
|
||||
compatible = "allwinner,sun4i-a10-pll1-clk";
|
||||
reg = <0x01c20000 0x4>;
|
||||
clocks = <&osc24M>;
|
||||
clock-output-names = "pll1";
|
||||
};
|
||||
|
||||
pll5: clk@01c20020 {
|
||||
#clock-cells = <1>;
|
||||
compatible = "allwinner,sun4i-pll5-clk";
|
||||
reg = <0x01c20020 0x4>;
|
||||
clocks = <&osc24M>;
|
||||
clock-output-names = "pll5_ddr", "pll5_other";
|
||||
};
|
||||
|
||||
cpu: cpu@01c20054 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "allwinner,sun4i-cpu-clk";
|
||||
compatible = "allwinner,sun4i-a10-cpu-clk";
|
||||
reg = <0x01c20054 0x4>;
|
||||
clocks = <&osc32k>, <&osc24M>, <&pll1>;
|
||||
clock-output-names = "cpu";
|
||||
};
|
||||
|
||||
mmc0_clk: clk@01c20088 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "allwinner,sun4i-mod0-clk";
|
||||
reg = <0x01c20088 0x4>;
|
||||
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
|
||||
clock-output-names = "mmc0";
|
||||
};
|
||||
|
||||
mii_phy_tx_clk: clk@2 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <25000000>;
|
||||
clock-output-names = "mii_phy_tx";
|
||||
};
|
||||
|
||||
gmac_int_tx_clk: clk@3 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <125000000>;
|
||||
clock-output-names = "gmac_int_tx";
|
||||
};
|
||||
|
||||
gmac_clk: clk@01c20164 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "allwinner,sun7i-a20-gmac-clk";
|
||||
reg = <0x01c20164 0x4>;
|
||||
/*
|
||||
* The first clock must be fixed at 25MHz;
|
||||
* the second clock must be fixed at 125MHz
|
||||
*/
|
||||
clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
|
||||
clock-output-names = "gmac";
|
||||
};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
#include "clk-factors.h"
|
||||
|
||||
@ -51,6 +52,8 @@ static void __init sun4i_osc_clk_setup(struct device_node *node)
|
||||
if (!gate)
|
||||
goto err_free_fixed;
|
||||
|
||||
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||
|
||||
/* set up gate and fixed rate properties */
|
||||
gate->reg = of_iomap(node, 0);
|
||||
gate->bit_idx = SUNXI_OSC24M_GATE;
|
||||
@ -77,7 +80,7 @@ err_free_gate:
|
||||
err_free_fixed:
|
||||
kfree(fixed);
|
||||
}
|
||||
CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup);
|
||||
CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
|
||||
|
||||
|
||||
|
||||
@ -249,7 +252,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
|
||||
*n = DIV_ROUND_UP(div, (*k+1));
|
||||
}
|
||||
|
||||
/**
|
||||
* sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6
|
||||
* PLL6 rate is calculated as follows
|
||||
* rate = parent_rate * n * (k + 1) / 2
|
||||
* parent_rate is always 24Mhz
|
||||
*/
|
||||
|
||||
static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
|
||||
u8 *n, u8 *k, u8 *m, u8 *p)
|
||||
{
|
||||
u8 div;
|
||||
|
||||
/*
|
||||
* We always have 24MHz / 2, so we can just say that our
|
||||
* parent clock is 12MHz.
|
||||
*/
|
||||
parent_rate = parent_rate / 2;
|
||||
|
||||
/* Normalize value to a parent_rate multiple (24M / 2) */
|
||||
div = *freq / parent_rate;
|
||||
*freq = parent_rate * div;
|
||||
|
||||
/* we were called to round the frequency, we can now return */
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
*k = div / 32;
|
||||
if (*k > 3)
|
||||
*k = 3;
|
||||
|
||||
*n = DIV_ROUND_UP(div, (*k+1));
|
||||
}
|
||||
|
||||
/**
|
||||
* sun4i_get_apb1_factors() - calculates m, p factors for APB1
|
||||
@ -376,6 +410,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
|
||||
*
|
||||
* This clock looks something like this
|
||||
* ________________________
|
||||
* MII TX clock from PHY >-----|___________ _________|----> to GMAC core
|
||||
* GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
|
||||
* Ext. 125MHz RGMII TX clk >--|__divider__/ |
|
||||
* |________________________|
|
||||
*
|
||||
* The external 125 MHz reference is optional, i.e. GMAC can use its
|
||||
* internal TX clock just fine. The A31 GMAC clock module does not have
|
||||
* the divider controls for the external reference.
|
||||
*
|
||||
* To keep it simple, let the GMAC use either the MII TX clock for MII mode,
|
||||
* and its internal TX clock for GMII and RGMII modes. The GMAC driver should
|
||||
* select the appropriate source and gate/ungate the output to the PHY.
|
||||
*
|
||||
* Only the GMAC should use this clock. Altering the clock so that it doesn't
|
||||
* match the GMAC's operation parameters will result in the GMAC not being
|
||||
* able to send traffic out. The GMAC driver should set the clock rate and
|
||||
* enable/disable this clock to configure the required state. The clock
|
||||
* driver then responds by auto-reparenting the clock.
|
||||
*/
|
||||
|
||||
#define SUN7I_A20_GMAC_GPIT 2
|
||||
#define SUN7I_A20_GMAC_MASK 0x3
|
||||
#define SUN7I_A20_GMAC_PARENTS 2
|
||||
|
||||
static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_mux *mux;
|
||||
struct clk_gate *gate;
|
||||
const char *clk_name = node->name;
|
||||
const char *parents[SUN7I_A20_GMAC_PARENTS];
|
||||
void *reg;
|
||||
|
||||
if (of_property_read_string(node, "clock-output-names", &clk_name))
|
||||
return;
|
||||
|
||||
/* allocate mux and gate clock structs */
|
||||
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
return;
|
||||
|
||||
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
goto free_mux;
|
||||
|
||||
/* gmac clock requires exactly 2 parents */
|
||||
parents[0] = of_clk_get_parent_name(node, 0);
|
||||
parents[1] = of_clk_get_parent_name(node, 1);
|
||||
if (!parents[0] || !parents[1])
|
||||
goto free_gate;
|
||||
|
||||
reg = of_iomap(node, 0);
|
||||
if (!reg)
|
||||
goto free_gate;
|
||||
|
||||
/* set up gate and fixed rate properties */
|
||||
gate->reg = reg;
|
||||
gate->bit_idx = SUN7I_A20_GMAC_GPIT;
|
||||
gate->lock = &clk_lock;
|
||||
mux->reg = reg;
|
||||
mux->mask = SUN7I_A20_GMAC_MASK;
|
||||
mux->flags = CLK_MUX_INDEX_BIT;
|
||||
mux->lock = &clk_lock;
|
||||
|
||||
clk = clk_register_composite(NULL, clk_name,
|
||||
parents, SUN7I_A20_GMAC_PARENTS,
|
||||
&mux->hw, &clk_mux_ops,
|
||||
NULL, NULL,
|
||||
&gate->hw, &clk_gate_ops,
|
||||
0);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
goto iounmap_reg;
|
||||
|
||||
of_clk_add_provider(node, of_clk_src_simple_get, clk);
|
||||
clk_register_clkdev(clk, clk_name, NULL);
|
||||
|
||||
return;
|
||||
|
||||
iounmap_reg:
|
||||
iounmap(reg);
|
||||
free_gate:
|
||||
kfree(gate);
|
||||
free_mux:
|
||||
kfree(mux);
|
||||
}
|
||||
CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
|
||||
sun7i_a20_gmac_clk_setup);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* sunxi_factors_clk_setup() - Setup function for factor clocks
|
||||
*/
|
||||
@ -387,6 +517,7 @@ struct factors_data {
|
||||
int mux;
|
||||
struct clk_factors_config *table;
|
||||
void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static struct clk_factors_config sun4i_pll1_config = {
|
||||
@ -416,6 +547,13 @@ static struct clk_factors_config sun4i_pll5_config = {
|
||||
.kwidth = 2,
|
||||
};
|
||||
|
||||
static struct clk_factors_config sun6i_a31_pll6_config = {
|
||||
.nshift = 8,
|
||||
.nwidth = 5,
|
||||
.kshift = 4,
|
||||
.kwidth = 2,
|
||||
};
|
||||
|
||||
static struct clk_factors_config sun4i_apb1_config = {
|
||||
.mshift = 0,
|
||||
.mwidth = 5,
|
||||
@ -455,6 +593,20 @@ static const struct factors_data sun4i_pll5_data __initconst = {
|
||||
.enable = 31,
|
||||
.table = &sun4i_pll5_config,
|
||||
.getter = sun4i_get_pll5_factors,
|
||||
.name = "pll5",
|
||||
};
|
||||
|
||||
static const struct factors_data sun4i_pll6_data __initconst = {
|
||||
.enable = 31,
|
||||
.table = &sun4i_pll5_config,
|
||||
.getter = sun4i_get_pll5_factors,
|
||||
.name = "pll6",
|
||||
};
|
||||
|
||||
static const struct factors_data sun6i_a31_pll6_data __initconst = {
|
||||
.enable = 31,
|
||||
.table = &sun6i_a31_pll6_config,
|
||||
.getter = sun6i_a31_get_pll6_factors,
|
||||
};
|
||||
|
||||
static const struct factors_data sun4i_apb1_data __initconst = {
|
||||
@ -497,14 +649,14 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
|
||||
(parents[i] = of_clk_get_parent_name(node, i)) != NULL)
|
||||
i++;
|
||||
|
||||
/* Nodes should be providing the name via clock-output-names
|
||||
* but originally our dts didn't, and so we used node->name.
|
||||
* The new, better nodes look like clk@deadbeef, so we pull the
|
||||
* name just in this case */
|
||||
if (!strcmp("clk", clk_name)) {
|
||||
of_property_read_string_index(node, "clock-output-names",
|
||||
0, &clk_name);
|
||||
}
|
||||
/*
|
||||
* some factor clocks, such as pll5 and pll6, may have multiple
|
||||
* outputs, and have their name designated in factors_data
|
||||
*/
|
||||
if (data->name)
|
||||
clk_name = data->name;
|
||||
else
|
||||
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||
|
||||
factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
|
||||
if (!factors)
|
||||
@ -601,6 +753,8 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
|
||||
(parents[i] = of_clk_get_parent_name(node, i)) != NULL)
|
||||
i++;
|
||||
|
||||
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||
|
||||
clk = clk_register_mux(NULL, clk_name, parents, i,
|
||||
CLK_SET_RATE_NO_REPARENT, reg,
|
||||
data->shift, SUNXI_MUX_GATE_WIDTH,
|
||||
@ -660,6 +814,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
|
||||
|
||||
clk_parent = of_clk_get_parent_name(node, 0);
|
||||
|
||||
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||
|
||||
clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
|
||||
reg, data->shift, data->width,
|
||||
data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
|
||||
@ -672,6 +828,59 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* sunxi_gates_reset... - reset bits in leaf gate clk registers handling
|
||||
*/
|
||||
|
||||
struct gates_reset_data {
|
||||
void __iomem *reg;
|
||||
spinlock_t *lock;
|
||||
struct reset_controller_dev rcdev;
|
||||
};
|
||||
|
||||
static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct gates_reset_data *data = container_of(rcdev,
|
||||
struct gates_reset_data,
|
||||
rcdev);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(data->lock, flags);
|
||||
|
||||
reg = readl(data->reg);
|
||||
writel(reg & ~BIT(id), data->reg);
|
||||
|
||||
spin_unlock_irqrestore(data->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct gates_reset_data *data = container_of(rcdev,
|
||||
struct gates_reset_data,
|
||||
rcdev);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(data->lock, flags);
|
||||
|
||||
reg = readl(data->reg);
|
||||
writel(reg | BIT(id), data->reg);
|
||||
|
||||
spin_unlock_irqrestore(data->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct reset_control_ops sunxi_gates_reset_ops = {
|
||||
.assert = sunxi_gates_reset_assert,
|
||||
.deassert = sunxi_gates_reset_deassert,
|
||||
};
|
||||
|
||||
/**
|
||||
* sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
|
||||
*/
|
||||
@ -680,6 +889,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
|
||||
|
||||
struct gates_data {
|
||||
DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
|
||||
u32 reset_mask;
|
||||
};
|
||||
|
||||
static const struct gates_data sun4i_axi_gates_data __initconst = {
|
||||
@ -746,10 +956,21 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
|
||||
.mask = { 0xff80ff },
|
||||
};
|
||||
|
||||
static const struct gates_data sun4i_a10_usb_gates_data __initconst = {
|
||||
.mask = {0x1C0},
|
||||
.reset_mask = 0x07,
|
||||
};
|
||||
|
||||
static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
|
||||
.mask = {0x140},
|
||||
.reset_mask = 0x03,
|
||||
};
|
||||
|
||||
static void __init sunxi_gates_clk_setup(struct device_node *node,
|
||||
struct gates_data *data)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
struct gates_reset_data *reset_data;
|
||||
const char *clk_parent;
|
||||
const char *clk_name;
|
||||
void *reg;
|
||||
@ -793,6 +1014,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
|
||||
clk_data->clk_num = i;
|
||||
|
||||
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
/* Register a reset controler for gates with reset bits */
|
||||
if (data->reset_mask == 0)
|
||||
return;
|
||||
|
||||
reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
|
||||
if (!reset_data)
|
||||
return;
|
||||
|
||||
reset_data->reg = reg;
|
||||
reset_data->lock = &clk_lock;
|
||||
reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
|
||||
reset_data->rcdev.ops = &sunxi_gates_reset_ops;
|
||||
reset_data->rcdev.of_node = node;
|
||||
reset_controller_register(&reset_data->rcdev);
|
||||
}
|
||||
|
||||
|
||||
@ -832,7 +1068,7 @@ static const struct divs_data pll5_divs_data __initconst = {
|
||||
};
|
||||
|
||||
static const struct divs_data pll6_divs_data __initconst = {
|
||||
.factors = &sun4i_pll5_data,
|
||||
.factors = &sun4i_pll6_data,
|
||||
.div = {
|
||||
{ .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
|
||||
{ .fixed = 2 }, /* P, other */
|
||||
@ -854,7 +1090,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
|
||||
struct divs_data *data)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
const char *parent = node->name;
|
||||
const char *parent;
|
||||
const char *clk_name;
|
||||
struct clk **clks, *pclk;
|
||||
struct clk_hw *gate_hw, *rate_hw;
|
||||
@ -868,6 +1104,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
|
||||
|
||||
/* Set up factor clock that we will be dividing */
|
||||
pclk = sunxi_factors_clk_setup(node, data->factors);
|
||||
parent = __clk_get_name(pclk);
|
||||
|
||||
reg = of_iomap(node, 0);
|
||||
|
||||
@ -970,56 +1207,59 @@ free_clkdata:
|
||||
|
||||
/* Matches for factors clocks */
|
||||
static const struct of_device_id clk_factors_match[] __initconst = {
|
||||
{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
|
||||
{.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
|
||||
{.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
|
||||
{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* Matches for divider clocks */
|
||||
static const struct of_device_id clk_div_match[] __initconst = {
|
||||
{.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,},
|
||||
{.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,},
|
||||
{.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_axi_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* Matches for divided outputs */
|
||||
static const struct of_device_id clk_divs_match[] __initconst = {
|
||||
{.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
|
||||
{.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* Matches for mux clocks */
|
||||
static const struct of_device_id clk_mux_match[] __initconst = {
|
||||
{.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
|
||||
{.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* Matches for gate clocks */
|
||||
static const struct of_device_id clk_gates_match[] __initconst = {
|
||||
{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-axi-gates-clk", .data = &sun4i_axi_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
|
||||
{.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
|
||||
{.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
|
||||
{.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
|
||||
{}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user