diff --git a/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq7h-olb.yaml b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq7h-olb.yaml new file mode 100644 index 000000000000..2958ca9e330b --- /dev/null +++ b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq7h-olb.yaml @@ -0,0 +1,192 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/mobileye/mobileye,eyeq7h-olb.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mobileye EyeQ7H SoC system controller + +maintainers: + - Benoît Monin + - Grégory Clement + - Théo Lebrun + - Vladimir Kondratiev + +description: + OLB ("Other Logic Block") is a hardware system controller grouping + smaller blocks. Clocks and resets are generated by those blocks and + used by internal controllers of the SoC. The EyeQ7H SoC hosts 14 + different OLB. + +properties: + compatible: + items: + - enum: + - mobileye,eyeq7h-acc0-olb + - mobileye,eyeq7h-acc1-olb + - mobileye,eyeq7h-ddr0-olb + - mobileye,eyeq7h-ddr1-olb + - mobileye,eyeq7h-east-olb + - mobileye,eyeq7h-mips0-olb + - mobileye,eyeq7h-mips1-olb + - mobileye,eyeq7h-mips2-olb + - mobileye,eyeq7h-periph-east-olb + - mobileye,eyeq7h-periph-west-olb + - mobileye,eyeq7h-south-olb + - mobileye,eyeq7h-west-olb + - mobileye,eyeq7h-xnn0-olb + - mobileye,eyeq7h-xnn1-olb + - const: syscon + + reg: + maxItems: 1 + + '#reset-cells': + description: + First cell is domain and optional if compatible has a single reset domain. + Second cell is reset index inside that domain. + enum: [ 1, 2 ] + + '#clock-cells': + const: 1 + + clocks: + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + maxItems: 2 + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +allOf: + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq7h-ddr0-olb + - mobileye,eyeq7h-ddr1-olb + - mobileye,eyeq7h-mips0-olb + - mobileye,eyeq7h-mips1-olb + - mobileye,eyeq7h-mips2-olb + - mobileye,eyeq7h-periph-east-olb + - mobileye,eyeq7h-south-olb + then: + properties: + clocks: + items: + - description: Reference input clock. + clock-names: + items: + - const: ref + + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq7h-east-olb + - mobileye,eyeq7h-west-olb + then: + properties: + clocks: + items: + - description: Reference input clock from the main oscillator. + - description: 100MHz reference input clock. + clock-names: + items: + - const: ref + - const: ref_100p0 + + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq7h-acc0-olb + - mobileye,eyeq7h-acc1-olb + - mobileye,eyeq7h-periph-west-olb + - mobileye,eyeq7h-xnn0-olb + - mobileye,eyeq7h-xnn1-olb + then: + properties: + clocks: + items: + - description: 100MHz reference input clock. + - description: 106.6MHz reference input clock. + clock-names: + items: + - const: ref_100p0 + - const: ref_106p6 + + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq7h-ddr0-olb + - mobileye,eyeq7h-ddr1-olb + - mobileye,eyeq7h-east-olb + - mobileye,eyeq7h-periph-east-olb + - mobileye,eyeq7h-periph-west-olb + - mobileye,eyeq7h-west-olb + then: + properties: + '#reset-cells': + const: 1 + required: + - '#reset-cells' + + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq7h-acc0-olb + - mobileye,eyeq7h-acc1-olb + - mobileye,eyeq7h-south-olb + - mobileye,eyeq7h-xnn0-olb + - mobileye,eyeq7h-xnn1-olb + then: + properties: + '#reset-cells': + const: 2 + required: + - '#reset-cells' + + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq7h-mips0-olb + - mobileye,eyeq7h-mips1-olb + - mobileye,eyeq7h-mips2-olb + then: + properties: + '#reset-cells': false + +additionalProperties: false + +examples: + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + + system-controller0@45000000 { + compatible = "mobileye,eyeq7h-acc0-olb", "syscon"; + reg = <0x0 0x45000000 0x0 0x1000>; + #reset-cells = <2>; + #clock-cells = <1>; + clocks = <&olb_south 7>, <&olb_east 5>; + clock-names = "ref_100p0", "ref_106p6"; + }; + }; diff --git a/drivers/clk/clk-eyeq.c b/drivers/clk/clk-eyeq.c index 9743de55bdf8..cf37feccc734 100644 --- a/drivers/clk/clk-eyeq.c +++ b/drivers/clk/clk-eyeq.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * PLL clock driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms. + * PLL clock driver for the Mobileye EyeQ platforms. * * This controller handles: * - Read-only PLLs, all derived from the same main crystal clock. @@ -45,67 +45,104 @@ #include #include +#include /* In frac mode, it enables fractional noise canceling DAC. Else, no function. */ -#define PCSR0_DAC_EN BIT(0) +#define FRACG_PCSR0_DAC_EN BIT(0) /* Fractional or integer mode */ -#define PCSR0_DSM_EN BIT(1) -#define PCSR0_PLL_EN BIT(2) +#define FRACG_PCSR0_DSM_EN BIT(1) +#define FRACG_PCSR0_PLL_EN BIT(2) /* All clocks output held at 0 */ -#define PCSR0_FOUTPOSTDIV_EN BIT(3) -#define PCSR0_POST_DIV1 GENMASK(6, 4) -#define PCSR0_POST_DIV2 GENMASK(9, 7) -#define PCSR0_REF_DIV GENMASK(15, 10) -#define PCSR0_INTIN GENMASK(27, 16) -#define PCSR0_BYPASS BIT(28) +#define FRACG_PCSR0_FOUTPOSTDIV_EN BIT(3) +#define FRACG_PCSR0_POST_DIV1 GENMASK(6, 4) +#define FRACG_PCSR0_POST_DIV2 GENMASK(9, 7) +#define FRACG_PCSR0_REF_DIV GENMASK(15, 10) +#define FRACG_PCSR0_INTIN GENMASK(27, 16) +#define FRACG_PCSR0_BYPASS BIT(28) /* Bits 30..29 are reserved */ -#define PCSR0_PLL_LOCKED BIT(31) +#define FRACG_PCSR0_PLL_LOCKED BIT(31) -#define PCSR1_RESET BIT(0) -#define PCSR1_SSGC_DIV GENMASK(4, 1) +#define FRACG_PCSR1_RESET BIT(0) +#define FRACG_PCSR1_SSGC_DIV GENMASK(4, 1) /* Spread amplitude (% = 0.1 * SPREAD[4:0]) */ -#define PCSR1_SPREAD GENMASK(9, 5) -#define PCSR1_DIS_SSCG BIT(10) +#define FRACG_PCSR1_SPREAD GENMASK(9, 5) +#define FRACG_PCSR1_DIS_SSCG BIT(10) /* Down-spread or center-spread */ -#define PCSR1_DOWN_SPREAD BIT(11) -#define PCSR1_FRAC_IN GENMASK(31, 12) +#define FRACG_PCSR1_DOWN_SPREAD BIT(11) +#define FRACG_PCSR1_FRAC_IN GENMASK(31, 12) -struct eqc_pll { - unsigned int index; - const char *name; - unsigned int reg64; -}; +#define JFRACR_PCSR0_BYPASS BIT(0) +#define JFRACR_PCSR0_PLL_EN BIT(1) +#define JFRACR_PCSR0_FOUTVCO_EN BIT(2) +#define JFRACR_PCSR0_FOUTPOSTDIV_EN BIT(3) +#define JFRACR_PCSR0_POST_DIV1 GENMASK(6, 4) +#define JFRACR_PCSR0_POST_DIV2 GENMASK(9, 7) +#define JFRACR_PCSR0_REF_DIV GENMASK(15, 10) +#define JFRACR_PCSR0_FB_DIV GENMASK(27, 16) +#define JFRACR_PCSR0_VCO_SEL GENMASK(29, 28) +#define JFRACR_PCSR0_PLL_LOCKED GENMASK(31, 30) + +#define JFRACR_PCSR1_FRAC_IN GENMASK(23, 0) +#define JFRACR_PCSR1_FOUT4PHASE_EN BIT(24) +#define JFRACR_PCSR1_DAC_EN BIT(25) +#define JFRACR_PCSR1_DSM_EN BIT(26) +/* Bits 31..27 are reserved */ +#define JFRACR_PCSR2_RESET BIT(0) +#define JFRACR_PCSR2_DIS_SSCG BIT(1) +#define JFRACR_PCSR2_DOWN_SPREAD BIT(2) +#define JFRACR_PCSR2_SSGC_DIV GENMASK(7, 4) +#define JFRACR_PCSR2_SPREAD GENMASK(12, 8) +/* Bits 31..13 are reserved */ + +#define AINTP_PCSR_BYPASS BIT(0) +#define AINTP_PCSR_PLL_EN BIT(1) +#define AINTP_PCSR_FOUTVCO_EN BIT(2) +#define AINTP_PCSR_FOUTPOSTDIV_EN BIT(3) +#define AINTP_PCSR_POST_DIV1 GENMASK(6, 4) +#define AINTP_PCSR_POST_DIV2 GENMASK(9, 7) +#define AINTP_PCSR_REF_DIV GENMASK(15, 10) +#define AINTP_PCSR_FB_DIV GENMASK(27, 16) +#define AINTP_PCSR_VCO_SEL GENMASK(29, 28) +/* bit 30 is reserved */ +#define AINTP_PCSR_PLL_LOCKED BIT(31) /* - * Divider clock. Divider is 2*(v+1), with v the register value. - * Min divider is 2, max is 2*(2^width). + * Special index values to lookup a parent clock by its name + * from the device tree or by its globally unique name. */ -struct eqc_div { - unsigned int index; - const char *name; - unsigned int parent; - unsigned int reg; - u8 shift; - u8 width; -}; +#define PARENT_BY_FWNAME (-1) +#define PARENT_BY_NAME (-2) -struct eqc_fixed_factor { - unsigned int index; +struct eqc_clock { + int index; + int parent_idx; const char *name; - unsigned int mult; - unsigned int div; - unsigned int parent; + const char *parent_name; + int (*probe)(struct device *dev, struct device_node *np, + const struct eqc_clock *clk, void __iomem *base, + struct clk_hw_onecell_data *cells); + void (*unregister)(struct clk_hw *hw); + union { + struct { + unsigned int reg; + u8 shift; + u8 width; + unsigned long flags; + const struct clk_div_table *table; + } div; + struct { + unsigned int mult; + unsigned int div; + } ff; + struct { + unsigned int reg; + } pll; + }; }; struct eqc_match_data { - unsigned int pll_count; - const struct eqc_pll *plls; - - unsigned int div_count; - const struct eqc_div *divs; - - unsigned int fixed_factor_count; - const struct eqc_fixed_factor *fixed_factors; + unsigned int clk_count; + const struct eqc_clock *clks; const char *reset_auxdev_name; const char *pinctrl_auxdev_name; @@ -115,11 +152,8 @@ struct eqc_match_data { }; struct eqc_early_match_data { - unsigned int early_pll_count; - const struct eqc_pll *early_plls; - - unsigned int early_fixed_factor_count; - const struct eqc_fixed_factor *early_fixed_factors; + unsigned int early_clk_count; + const struct eqc_clock *early_clks; /* * We want our of_xlate callback to EPROBE_DEFER instead of dev_err() @@ -129,8 +163,10 @@ struct eqc_early_match_data { }; /* - * Both factors (mult and div) must fit in 32 bits. When an operation overflows, - * this function throws away low bits so that factors still fit in 32 bits. + * All Mobileye EyeQ SoC have 64 bits long, but both factors (mult and div) + * must fit in 32 bits as clk_fixed_factor uses unsigned int. When an + * operation overflows, this function throws away low bits so that + * factors still fit in 32 bits. * * Precision loss depends on amplitude of mult and div. Worst theoretical * loss is: (UINT_MAX+1) / UINT_MAX - 1 = 2.3e-10. @@ -161,34 +197,63 @@ static void eqc_pll_downshift_factors(unsigned long *mult, unsigned long *div) *div >>= shift; } -static int eqc_pll_parse_registers(u32 r0, u32 r1, unsigned long *mult, - unsigned long *div, unsigned long *acc) +static int eqc_pll_parse_aintp(void __iomem *base, unsigned long *mult, unsigned long *div) +{ + u32 r0; + + r0 = readl(base); + if (r0 & AINTP_PCSR_BYPASS) { + *mult = 1; + *div = 1; + return 0; + } + + if (!(r0 & AINTP_PCSR_PLL_LOCKED)) + return -EINVAL; + + *mult = FIELD_GET(AINTP_PCSR_FB_DIV, r0); + *div = FIELD_GET(AINTP_PCSR_REF_DIV, r0); + + if (!*mult || !*div) + return -EINVAL; + + return 0; +} + +static int eqc_pll_parse_fracg(void __iomem *base, unsigned long *mult, + unsigned long *div, unsigned long *acc) { unsigned long spread; + u32 r0, r1; + u64 val; - if (r0 & PCSR0_BYPASS) { + val = readq(base); + r0 = val; + r1 = val >> 32; + + if (r0 & FRACG_PCSR0_BYPASS) { *mult = 1; *div = 1; *acc = 0; return 0; } - if (!(r0 & PCSR0_PLL_LOCKED)) + if (!(r0 & FRACG_PCSR0_PLL_LOCKED)) return -EINVAL; - *mult = FIELD_GET(PCSR0_INTIN, r0); - *div = FIELD_GET(PCSR0_REF_DIV, r0); + *mult = FIELD_GET(FRACG_PCSR0_INTIN, r0); + *div = FIELD_GET(FRACG_PCSR0_REF_DIV, r0); /* Fractional mode, in 2^20 (0x100000) parts. */ - if (r0 & PCSR0_DSM_EN) { + if (r0 & FRACG_PCSR0_DSM_EN) { *div *= (1ULL << 20); - *mult = *mult * (1ULL << 20) + FIELD_GET(PCSR1_FRAC_IN, r1); + *mult = *mult * (1ULL << 20) + FIELD_GET(FRACG_PCSR1_FRAC_IN, r1); } if (!*mult || !*div) return -EINVAL; - if (r1 & (PCSR1_RESET | PCSR1_DIS_SSCG)) { + if (r1 & (FRACG_PCSR1_RESET | FRACG_PCSR1_DIS_SSCG)) { *acc = 0; return 0; } @@ -203,10 +268,10 @@ static int eqc_pll_parse_registers(u32 r0, u32 r1, unsigned long *mult, * * Care is taken to avoid overflowing or losing precision. */ - spread = FIELD_GET(PCSR1_SPREAD, r1); + spread = FIELD_GET(FRACG_PCSR1_SPREAD, r1); *acc = DIV_ROUND_CLOSEST(spread * 1000000000, 1024 * 2); - if (r1 & PCSR1_DOWN_SPREAD) { + if (r1 & FRACG_PCSR1_DOWN_SPREAD) { /* * Downspreading: the central frequency is half a * spread lower. @@ -224,101 +289,58 @@ static int eqc_pll_parse_registers(u32 r0, u32 r1, unsigned long *mult, return 0; } -static void eqc_probe_init_plls(struct device *dev, const struct eqc_match_data *data, - void __iomem *base, struct clk_hw_onecell_data *cells) +static int eqc_pll_parse_jfracr(void __iomem *base, unsigned long *mult, + unsigned long *div, unsigned long *acc) { - unsigned long mult, div, acc; - const struct eqc_pll *pll; - struct clk_hw *hw; - unsigned int i; - u32 r0, r1; + unsigned long spread; + u32 r0, r1, r2; u64 val; - int ret; - for (i = 0; i < data->pll_count; i++) { - pll = &data->plls[i]; + val = readq(base); + r0 = val; + r1 = val >> 32; + r2 = readl(base + 8); - val = readq(base + pll->reg64); - r0 = val; - r1 = val >> 32; - - ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc); - if (ret) { - dev_warn(dev, "failed parsing state of %s\n", pll->name); - cells->hws[pll->index] = ERR_PTR(ret); - continue; - } - - hw = clk_hw_register_fixed_factor_with_accuracy_fwname(dev, - dev->of_node, pll->name, "ref", 0, mult, div, acc); - cells->hws[pll->index] = hw; - if (IS_ERR(hw)) - dev_warn(dev, "failed registering %s: %pe\n", pll->name, hw); + if (r0 & JFRACR_PCSR0_BYPASS) { + *mult = 1; + *div = 1; + *acc = 0; + return 0; } -} -static void eqc_probe_init_divs(struct device *dev, const struct eqc_match_data *data, - void __iomem *base, struct clk_hw_onecell_data *cells) -{ - struct clk_parent_data parent_data = { }; - const struct eqc_div *div; - struct clk_hw *parent; - void __iomem *reg; - struct clk_hw *hw; - unsigned int i; + /* Consider the PLL locked if either the phase or the frequency is locked */ + if (!(r0 & JFRACR_PCSR0_PLL_LOCKED)) + return -EINVAL; - for (i = 0; i < data->div_count; i++) { - div = &data->divs[i]; - reg = base + div->reg; - parent = cells->hws[div->parent]; + *mult = FIELD_GET(JFRACR_PCSR0_FB_DIV, r0); + *div = FIELD_GET(JFRACR_PCSR0_REF_DIV, r0); - if (IS_ERR(parent)) { - /* Parent is in early clk provider. */ - parent_data.index = div->parent; - parent_data.hw = NULL; - } else { - /* Avoid clock lookup when we already have the hw reference. */ - parent_data.index = 0; - parent_data.hw = parent; - } - - hw = clk_hw_register_divider_table_parent_data(dev, div->name, - &parent_data, 0, reg, div->shift, div->width, - CLK_DIVIDER_EVEN_INTEGERS, NULL, NULL); - cells->hws[div->index] = hw; - if (IS_ERR(hw)) - dev_warn(dev, "failed registering %s: %pe\n", - div->name, hw); + /* fractional part on 24 bits */ + if (r1 & JFRACR_PCSR1_DSM_EN) { + *div *= (1ULL << 24); + *mult = *mult * (1ULL << 24) + FIELD_GET(JFRACR_PCSR1_FRAC_IN, r1); } -} -static void eqc_probe_init_fixed_factors(struct device *dev, - const struct eqc_match_data *data, - struct clk_hw_onecell_data *cells) -{ - const struct eqc_fixed_factor *ff; - struct clk_hw *hw, *parent_hw; - unsigned int i; + if (!*mult || !*div) + return -EINVAL; - for (i = 0; i < data->fixed_factor_count; i++) { - ff = &data->fixed_factors[i]; - parent_hw = cells->hws[ff->parent]; + if (r2 & (JFRACR_PCSR2_RESET | JFRACR_PCSR2_DIS_SSCG)) { + *acc = 0; + } else { + /* spread spectrum is identical to FRACG PLL */ + spread = FIELD_GET(JFRACR_PCSR2_SPREAD, r2); + *acc = DIV_ROUND_CLOSEST(spread * 1000000000, 1024 * 2); - if (IS_ERR(parent_hw)) { - /* Parent is in early clk provider. */ - hw = clk_hw_register_fixed_factor_index(dev, ff->name, - ff->parent, 0, ff->mult, ff->div); - } else { - /* Avoid clock lookup when we already have the hw reference. */ - hw = clk_hw_register_fixed_factor_parent_hw(dev, ff->name, - parent_hw, 0, ff->mult, ff->div); + if (r2 & JFRACR_PCSR2_DOWN_SPREAD) { + *mult *= 2048 - spread; + *div *= 2048; } - - cells->hws[ff->index] = hw; - if (IS_ERR(hw)) - dev_warn(dev, "failed registering %s: %pe\n", - ff->name, hw); } + + /* make sure mult and div fit in 32 bits */ + eqc_pll_downshift_factors(mult, div); + + return 0; } static void eqc_auxdev_create_optional(struct device *dev, void __iomem *base, @@ -335,6 +357,155 @@ static void eqc_auxdev_create_optional(struct device *dev, void __iomem *base, } } +static int eqc_fill_parent_data(const struct eqc_clock *clk, + struct clk_hw_onecell_data *cells, + struct clk_parent_data *parent_data) +{ + int pidx = clk->parent_idx; + + memset(parent_data, 0, sizeof(struct clk_parent_data)); + + if (pidx == PARENT_BY_FWNAME) { + /* lookup the parent clock by its fw_name */ + parent_data->index = -1; + parent_data->fw_name = clk->parent_name; + } else if (pidx == PARENT_BY_NAME) { + /* lookup the parent clock by its global name */ + parent_data->index = -1; + parent_data->name = clk->parent_name; + } else if (pidx >= 0 && pidx < cells->num && !IS_ERR(cells->hws[pidx])) { + /* get the parent hw directly */ + parent_data->hw = cells->hws[pidx]; + } else { + /* no parent lookup by index: explicitly fail */ + return -EINVAL; + } + + return 0; +} + +static int eqc_probe_divider(struct device *dev, struct device_node *np, + const struct eqc_clock *clk, void __iomem *base, + struct clk_hw_onecell_data *cells) +{ + struct clk_parent_data parent_data; + struct clk_hw *hw; + int ret; + + ret = eqc_fill_parent_data(clk, cells, &parent_data); + if (ret) + return ret; + + hw = clk_hw_register_divider_table_parent_data(dev, clk->name, + &parent_data, 0, base + clk->div.reg, clk->div.shift, + clk->div.width, clk->div.flags, clk->div.table, NULL); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + cells->hws[clk->index] = hw; + return 0; +} + +static int eqc_probe_fixed_factor(struct device *dev, struct device_node *np, + const struct eqc_clock *clk, void __iomem *base, + struct clk_hw_onecell_data *cells) +{ + struct clk_parent_data parent_data; + struct clk_hw *hw; + int ret; + + ret = eqc_fill_parent_data(clk, cells, &parent_data); + if (ret) + return ret; + + hw = clk_hw_register_fixed_factor_pdata(dev, np, clk->name, &parent_data, 0, + clk->ff.mult, clk->ff.div, 0, 0); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + cells->hws[clk->index] = hw; + return 0; +} + +static int eqc_probe_pll_aintp(struct device *dev, struct device_node *np, + const struct eqc_clock *clk, void __iomem *base, + struct clk_hw_onecell_data *cells) +{ + struct clk_parent_data parent_data = { }; + unsigned long mult, div; + struct clk_hw *hw; + int ret; + + ret = eqc_pll_parse_aintp(base + clk->pll.reg, &mult, &div); + if (ret) + return ret; + + ret = eqc_fill_parent_data(clk, cells, &parent_data); + if (ret) + return ret; + + hw = clk_hw_register_fixed_factor_pdata(dev, np, clk->name, &parent_data, + 0, mult, div, 0, 0); + + if (IS_ERR(hw)) + return PTR_ERR(hw); + + cells->hws[clk->index] = hw; + return 0; +} + +static int eqc_probe_pll_fracg(struct device *dev, struct device_node *np, + const struct eqc_clock *clk, void __iomem *base, + struct clk_hw_onecell_data *cells) +{ + struct clk_parent_data parent_data; + unsigned long mult, div, acc; + struct clk_hw *hw; + int ret; + + ret = eqc_pll_parse_fracg(base + clk->pll.reg, &mult, &div, &acc); + if (ret) + return ret; + + ret = eqc_fill_parent_data(clk, cells, &parent_data); + if (ret) + return ret; + + hw = clk_hw_register_fixed_factor_pdata(dev, np, clk->name, &parent_data, 0, mult, + div, acc, CLK_FIXED_FACTOR_FIXED_ACCURACY); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + cells->hws[clk->index] = hw; + return 0; +} + +static int eqc_probe_pll_jfracr(struct device *dev, struct device_node *np, + const struct eqc_clock *clk, void __iomem *base, + struct clk_hw_onecell_data *cells) +{ + struct clk_parent_data parent_data = { }; + unsigned long mult, div, acc; + struct clk_hw *hw; + int ret; + + ret = eqc_pll_parse_jfracr(base + clk->pll.reg, &mult, &div, &acc); + if (ret) + return ret; + + ret = eqc_fill_parent_data(clk, cells, &parent_data); + if (ret) + return ret; + + hw = clk_hw_register_fixed_factor_pdata(dev, np, clk->name, &parent_data, 0, mult, + div, acc, CLK_FIXED_FACTOR_FIXED_ACCURACY); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + cells->hws[clk->index] = hw; + return 0; +} + static int eqc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -344,6 +515,7 @@ static int eqc_probe(struct platform_device *pdev) unsigned int i, clk_count; struct resource *res; void __iomem *base; + int ret; data = device_get_match_data(dev); if (!data) @@ -362,11 +534,10 @@ static int eqc_probe(struct platform_device *pdev) eqc_auxdev_create_optional(dev, base, data->pinctrl_auxdev_name); eqc_auxdev_create_optional(dev, base, data->eth_phy_auxdev_name); - if (data->pll_count + data->div_count + data->fixed_factor_count == 0) + if (data->clk_count == 0) return 0; /* Zero clocks, we are done. */ - clk_count = data->pll_count + data->div_count + - data->fixed_factor_count + data->early_clk_count; + clk_count = data->clk_count + data->early_clk_count; cells = kzalloc_flex(*cells, hws, clk_count); if (!cells) return -ENOMEM; @@ -377,31 +548,96 @@ static int eqc_probe(struct platform_device *pdev) for (i = 0; i < clk_count; i++) cells->hws[i] = ERR_PTR(-EINVAL); - eqc_probe_init_plls(dev, data, base, cells); + for (i = 0; i < data->clk_count; i++) { + const struct eqc_clock *clk = &data->clks[i]; - eqc_probe_init_divs(dev, data, base, cells); - - eqc_probe_init_fixed_factors(dev, data, cells); + if (clk->probe) + ret = clk->probe(dev, NULL, clk, base, cells); + else + ret = -EINVAL; + if (ret) + dev_warn(dev, "failed probing clock %s: %d\n", clk->name, ret); + } return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, cells); } -/* Required early for GIC timer (pll-cpu) and UARTs (pll-per). */ -static const struct eqc_pll eqc_eyeq5_early_plls[] = { - { .index = EQ5C_PLL_CPU, .name = "pll-cpu", .reg64 = 0x02C }, - { .index = EQ5C_PLL_PER, .name = "pll-per", .reg64 = 0x05C }, -}; +#define DIV(_index, _parent_idx, _name, _parent_name, \ + _reg, _shift, _width) \ + { \ + .index = _index, \ + .parent_idx = _parent_idx, \ + .name = _name, \ + .parent_name = _parent_name, \ + .probe = eqc_probe_divider, \ + .unregister = clk_hw_unregister_divider, \ + .div.reg = _reg, \ + .div.shift = _shift, \ + .div.width = _width, \ + .div.flags = CLK_DIVIDER_EVEN_INTEGERS, \ + .div.table = NULL, \ + } -static const struct eqc_pll eqc_eyeq5_plls[] = { - { .index = EQ5C_PLL_VMP, .name = "pll-vmp", .reg64 = 0x034 }, - { .index = EQ5C_PLL_PMA, .name = "pll-pma", .reg64 = 0x03C }, - { .index = EQ5C_PLL_VDI, .name = "pll-vdi", .reg64 = 0x044 }, - { .index = EQ5C_PLL_DDR0, .name = "pll-ddr0", .reg64 = 0x04C }, - { .index = EQ5C_PLL_PCI, .name = "pll-pci", .reg64 = 0x054 }, - { .index = EQ5C_PLL_PMAC, .name = "pll-pmac", .reg64 = 0x064 }, - { .index = EQ5C_PLL_MPC, .name = "pll-mpc", .reg64 = 0x06C }, - { .index = EQ5C_PLL_DDR1, .name = "pll-ddr1", .reg64 = 0x074 }, -}; +#define DIV_TABLE_RO(_index, _parent_idx, _name, _parent_name, \ + _reg, _shift, _width, _table) \ + { \ + .index = _index, \ + .parent_idx = _parent_idx, \ + .name = _name, \ + .parent_name = _parent_name, \ + .probe = eqc_probe_divider, \ + .unregister = clk_hw_unregister_divider, \ + .div.reg = _reg, \ + .div.shift = _shift, \ + .div.width = _width, \ + .div.flags = CLK_DIVIDER_READ_ONLY, \ + .div.table = _table, \ + } + +#define FF(_index, _parent_idx, _name, _parent_name, _mult, _div) \ + { \ + .index = _index, \ + .parent_idx = _parent_idx, \ + .name = _name, \ + .parent_name = _parent_name, \ + .probe = eqc_probe_fixed_factor, \ + .unregister = clk_hw_unregister_fixed_factor, \ + .ff.mult = _mult, \ + .ff.div = _div, \ + } + +#define PLL_AINTP(_index, _parent_idx, _name, _parent_name, _reg) \ + { \ + .index = _index, \ + .parent_idx = _parent_idx, \ + .name = _name, \ + .parent_name = _parent_name, \ + .probe = eqc_probe_pll_aintp, \ + .unregister = clk_hw_unregister_fixed_factor, \ + .pll.reg = _reg, \ + } + +#define PLL_FRACG(_index, _parent_idx, _name, _parent_name, _reg) \ + { \ + .index = _index, \ + .parent_idx = _parent_idx, \ + .name = _name, \ + .parent_name = _parent_name, \ + .probe = eqc_probe_pll_fracg, \ + .unregister = clk_hw_unregister_fixed_factor, \ + .pll.reg = _reg, \ + } + +#define PLL_JFRACR(_index, _parent_idx, _name, _parent_name, _reg) \ + { \ + .index = _index, \ + .parent_idx = _parent_idx, \ + .name = _name, \ + .parent_name = _parent_name, \ + .probe = eqc_probe_pll_jfracr, \ + .unregister = clk_hw_unregister_fixed_factor, \ + .pll.reg = _reg, \ + } enum { /* @@ -440,267 +676,501 @@ enum { EQ5C_PER_FCMU_A, }; -static const struct eqc_fixed_factor eqc_eyeq5_early_fixed_factors[] = { - /* EQ5C_PLL_CPU children */ - { EQ5C_CPU_OCC, "occ-cpu", 1, 1, EQ5C_PLL_CPU }, - { EQ5C_CPU_SI_CSS0, "si-css0", 1, 1, EQ5C_CPU_OCC }, - { EQ5C_CPU_CORE0, "core0", 1, 1, EQ5C_CPU_SI_CSS0 }, - { EQ5C_CPU_CORE1, "core1", 1, 1, EQ5C_CPU_SI_CSS0 }, - { EQ5C_CPU_CORE2, "core2", 1, 1, EQ5C_CPU_SI_CSS0 }, - { EQ5C_CPU_CORE3, "core3", 1, 1, EQ5C_CPU_SI_CSS0 }, +/* Required early for GIC timer (pll-cpu) and UARTs (pll-per). */ +static const struct eqc_clock eqc_eyeq5_early_clks[] = { + PLL_FRACG(EQ5C_PLL_CPU, PARENT_BY_FWNAME, "pll-cpu", "ref", 0x02C), + PLL_FRACG(EQ5C_PLL_PER, PARENT_BY_FWNAME, "pll-per", "ref", 0x05C), - /* EQ5C_PLL_PER children */ - { EQ5C_PER_OCC, "occ-periph", 1, 16, EQ5C_PLL_PER }, - { EQ5C_PER_UART, "uart", 1, 1, EQ5C_PER_OCC }, + FF(EQ5C_CPU_OCC, EQ5C_PLL_CPU, "occ-cpu", NULL, 1, 1), + FF(EQ5C_CPU_SI_CSS0, EQ5C_CPU_OCC, "si-css0", NULL, 1, 1), + FF(EQ5C_CPU_CORE0, EQ5C_CPU_SI_CSS0, "core0", NULL, 1, 1), + FF(EQ5C_CPU_CORE1, EQ5C_CPU_SI_CSS0, "core1", NULL, 1, 1), + FF(EQ5C_CPU_CORE2, EQ5C_CPU_SI_CSS0, "core2", NULL, 1, 1), + FF(EQ5C_CPU_CORE3, EQ5C_CPU_SI_CSS0, "core3", NULL, 1, 1), + + FF(EQ5C_PER_OCC, EQ5C_PLL_PER, "occ-periph", NULL, 1, 16), + FF(EQ5C_PER_UART, EQ5C_PER_OCC, "uart", NULL, 1, 1), }; -static const struct eqc_fixed_factor eqc_eyeq5_fixed_factors[] = { - /* EQ5C_PLL_CPU children */ - { EQ5C_CPU_CPC, "cpc", 1, 1, EQ5C_CPU_SI_CSS0 }, - { EQ5C_CPU_CM, "cm", 1, 1, EQ5C_CPU_SI_CSS0 }, - { EQ5C_CPU_MEM, "mem", 1, 1, EQ5C_CPU_SI_CSS0 }, - { EQ5C_CPU_OCC_ISRAM, "occ-isram", 1, 2, EQ5C_PLL_CPU }, - { EQ5C_CPU_ISRAM, "isram", 1, 1, EQ5C_CPU_OCC_ISRAM }, - { EQ5C_CPU_OCC_DBU, "occ-dbu", 1, 10, EQ5C_PLL_CPU }, - { EQ5C_CPU_SI_DBU_TP, "si-dbu-tp", 1, 1, EQ5C_CPU_OCC_DBU }, +static const struct eqc_clock eqc_eyeq5_clks[] = { + PLL_FRACG(EQ5C_PLL_VMP, PARENT_BY_FWNAME, "pll-vmp", "ref", 0x034), + PLL_FRACG(EQ5C_PLL_PMA, PARENT_BY_FWNAME, "pll-pma", "ref", 0x03C), + PLL_FRACG(EQ5C_PLL_VDI, PARENT_BY_FWNAME, "pll-vdi", "ref", 0x044), + PLL_FRACG(EQ5C_PLL_DDR0, PARENT_BY_FWNAME, "pll-ddr0", "ref", 0x04C), + PLL_FRACG(EQ5C_PLL_PCI, PARENT_BY_FWNAME, "pll-pci", "ref", 0x054), + PLL_FRACG(EQ5C_PLL_PMAC, PARENT_BY_FWNAME, "pll-pmac", "ref", 0x064), + PLL_FRACG(EQ5C_PLL_MPC, PARENT_BY_FWNAME, "pll-mpc", "ref", 0x06C), + PLL_FRACG(EQ5C_PLL_DDR1, PARENT_BY_FWNAME, "pll-ddr1", "ref", 0x074), - /* EQ5C_PLL_VDI children */ - { EQ5C_VDI_OCC_VDI, "occ-vdi", 1, 2, EQ5C_PLL_VDI }, - { EQ5C_VDI_VDI, "vdi", 1, 1, EQ5C_VDI_OCC_VDI }, - { EQ5C_VDI_OCC_CAN_SER, "occ-can-ser", 1, 16, EQ5C_PLL_VDI }, - { EQ5C_VDI_CAN_SER, "can-ser", 1, 1, EQ5C_VDI_OCC_CAN_SER }, - { EQ5C_VDI_I2C_SER, "i2c-ser", 1, 20, EQ5C_PLL_VDI }, + DIV(EQ5C_DIV_OSPI, PARENT_BY_NAME, "div-ospi", "pll-per", 0x11C, 0, 4), - /* EQ5C_PLL_PER children */ - { EQ5C_PER_PERIPH, "periph", 1, 1, EQ5C_PER_OCC }, - { EQ5C_PER_CAN, "can", 1, 1, EQ5C_PER_OCC }, - { EQ5C_PER_SPI, "spi", 1, 1, EQ5C_PER_OCC }, - { EQ5C_PER_I2C, "i2c", 1, 1, EQ5C_PER_OCC }, - { EQ5C_PER_TIMER, "timer", 1, 1, EQ5C_PER_OCC }, - { EQ5C_PER_GPIO, "gpio", 1, 1, EQ5C_PER_OCC }, - { EQ5C_PER_EMMC, "emmc-sys", 1, 10, EQ5C_PLL_PER }, - { EQ5C_PER_CCF, "ccf-ctrl", 1, 4, EQ5C_PLL_PER }, - { EQ5C_PER_OCC_MJPEG, "occ-mjpeg", 1, 2, EQ5C_PLL_PER }, - { EQ5C_PER_HSM, "hsm", 1, 1, EQ5C_PER_OCC_MJPEG }, - { EQ5C_PER_MJPEG, "mjpeg", 1, 1, EQ5C_PER_OCC_MJPEG }, - { EQ5C_PER_FCMU_A, "fcmu-a", 1, 20, EQ5C_PLL_PER }, - { EQ5C_PER_OCC_PCI, "occ-pci-sys", 1, 8, EQ5C_PLL_PER }, -}; + FF(EQ5C_CPU_CPC, PARENT_BY_NAME, "cpc", "si-css0", 1, 1), + FF(EQ5C_CPU_CM, PARENT_BY_NAME, "cm", "si-css0", 1, 1), + FF(EQ5C_CPU_MEM, PARENT_BY_NAME, "mem", "si-css0", 1, 1), + FF(EQ5C_CPU_OCC_ISRAM, PARENT_BY_NAME, "occ-isram", "pll-cpu", 1, 2), + FF(EQ5C_CPU_ISRAM, EQ5C_CPU_OCC_ISRAM, "isram", NULL, 1, 1), + FF(EQ5C_CPU_OCC_DBU, PARENT_BY_NAME, "occ-dbu", "pll-cpu", 1, 10), + FF(EQ5C_CPU_SI_DBU_TP, EQ5C_CPU_OCC_DBU, "si-dbu-tp", NULL, 1, 1), -static const struct eqc_div eqc_eyeq5_divs[] = { - { - .index = EQ5C_DIV_OSPI, - .name = "div-ospi", - .parent = EQ5C_PLL_PER, - .reg = 0x11C, - .shift = 0, - .width = 4, - }, + FF(EQ5C_VDI_OCC_VDI, PARENT_BY_NAME, "occ-vdi", "pll-vdi", 1, 2), + FF(EQ5C_VDI_VDI, EQ5C_VDI_OCC_VDI, "vdi", NULL, 1, 1), + FF(EQ5C_VDI_OCC_CAN_SER, PARENT_BY_NAME, "occ-can-ser", "pll-vdi", 1, 16), + FF(EQ5C_VDI_CAN_SER, EQ5C_VDI_OCC_CAN_SER, "can-ser", NULL, 1, 1), + FF(EQ5C_VDI_I2C_SER, PARENT_BY_NAME, "i2c-ser", "pll-vdi", 1, 20), + + FF(EQ5C_PER_PERIPH, PARENT_BY_NAME, "periph", "occ-periph", 1, 1), + FF(EQ5C_PER_CAN, PARENT_BY_NAME, "can", "occ-periph", 1, 1), + FF(EQ5C_PER_SPI, PARENT_BY_NAME, "spi", "occ-periph", 1, 1), + FF(EQ5C_PER_I2C, PARENT_BY_NAME, "i2c", "occ-periph", 1, 1), + FF(EQ5C_PER_TIMER, PARENT_BY_NAME, "timer", "occ-periph", 1, 1), + FF(EQ5C_PER_GPIO, PARENT_BY_NAME, "gpio", "occ-periph", 1, 1), + FF(EQ5C_PER_EMMC, PARENT_BY_NAME, "emmc-sys", "pll-per", 1, 10), + FF(EQ5C_PER_CCF, PARENT_BY_NAME, "ccf-ctrl", "pll-per", 1, 4), + FF(EQ5C_PER_OCC_MJPEG, PARENT_BY_NAME, "occ-mjpeg", "pll-per", 1, 2), + FF(EQ5C_PER_HSM, EQ5C_PER_OCC_MJPEG, "hsm", NULL, 1, 1), + FF(EQ5C_PER_MJPEG, EQ5C_PER_OCC_MJPEG, "mjpeg", NULL, 1, 1), + FF(EQ5C_PER_FCMU_A, PARENT_BY_NAME, "fcmu-a", "pll-per", 1, 20), + FF(EQ5C_PER_OCC_PCI, PARENT_BY_NAME, "occ-pci-sys", "pll-per", 1, 8), }; static const struct eqc_early_match_data eqc_eyeq5_early_match_data __initconst = { - .early_pll_count = ARRAY_SIZE(eqc_eyeq5_early_plls), - .early_plls = eqc_eyeq5_early_plls, + .early_clk_count = ARRAY_SIZE(eqc_eyeq5_early_clks), + .early_clks = eqc_eyeq5_early_clks, - .early_fixed_factor_count = ARRAY_SIZE(eqc_eyeq5_early_fixed_factors), - .early_fixed_factors = eqc_eyeq5_early_fixed_factors, - - .late_clk_count = ARRAY_SIZE(eqc_eyeq5_plls) + ARRAY_SIZE(eqc_eyeq5_divs) + - ARRAY_SIZE(eqc_eyeq5_fixed_factors), + .late_clk_count = ARRAY_SIZE(eqc_eyeq5_clks), }; static const struct eqc_match_data eqc_eyeq5_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq5_plls), - .plls = eqc_eyeq5_plls, - - .div_count = ARRAY_SIZE(eqc_eyeq5_divs), - .divs = eqc_eyeq5_divs, - - .fixed_factor_count = ARRAY_SIZE(eqc_eyeq5_fixed_factors), - .fixed_factors = eqc_eyeq5_fixed_factors, + .clk_count = ARRAY_SIZE(eqc_eyeq5_clks), + .clks = eqc_eyeq5_clks, .reset_auxdev_name = "reset", .pinctrl_auxdev_name = "pinctrl", .eth_phy_auxdev_name = "phy", - .early_clk_count = ARRAY_SIZE(eqc_eyeq5_early_plls) + - ARRAY_SIZE(eqc_eyeq5_early_fixed_factors), + .early_clk_count = ARRAY_SIZE(eqc_eyeq5_early_clks), }; -static const struct eqc_pll eqc_eyeq6l_plls[] = { - { .index = EQ6LC_PLL_DDR, .name = "pll-ddr", .reg64 = 0x02C }, - { .index = EQ6LC_PLL_CPU, .name = "pll-cpu", .reg64 = 0x034 }, /* also acc */ - { .index = EQ6LC_PLL_PER, .name = "pll-per", .reg64 = 0x03C }, - { .index = EQ6LC_PLL_VDI, .name = "pll-vdi", .reg64 = 0x044 }, +static const struct eqc_clock eqc_eyeq6l_clks[] = { + PLL_FRACG(EQ6LC_PLL_DDR, PARENT_BY_FWNAME, "pll-ddr", "ref", 0x02C), + PLL_FRACG(EQ6LC_PLL_CPU, PARENT_BY_FWNAME, "pll-cpu", "ref", 0x034), + PLL_FRACG(EQ6LC_PLL_PER, PARENT_BY_FWNAME, "pll-per", "ref", 0x03C), + PLL_FRACG(EQ6LC_PLL_VDI, PARENT_BY_FWNAME, "pll-vdi", "ref", 0x044), }; static const struct eqc_match_data eqc_eyeq6l_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq6l_plls), - .plls = eqc_eyeq6l_plls, + .clk_count = ARRAY_SIZE(eqc_eyeq6l_clks), + .clks = eqc_eyeq6l_clks, .reset_auxdev_name = "reset", }; -static const struct eqc_pll eqc_eyeq6lplus_early_plls[] = { - { .index = EQ6LPC_PLL_CPU, .name = "pll-cpu", .reg64 = 0x058 }, +static const struct eqc_clock eqc_eyeq6lplus_early_clks[] = { + PLL_FRACG(EQ6LPC_PLL_CPU, PARENT_BY_FWNAME, "pll-cpu", "ref", 0x058), + + FF(EQ6LPC_CPU_OCC, EQ6LPC_PLL_CPU, "occ-cpu", NULL, 1, 1), }; -static const struct eqc_pll eqc_eyeq6lplus_plls[] = { - { .index = EQ6LPC_PLL_DDR, .name = "pll-ddr", .reg64 = 0x02C }, - { .index = EQ6LPC_PLL_ACC, .name = "pll-acc", .reg64 = 0x034 }, - { .index = EQ6LPC_PLL_PER, .name = "pll-per", .reg64 = 0x03C }, - { .index = EQ6LPC_PLL_VDI, .name = "pll-vdi", .reg64 = 0x044 }, -}; +static const struct eqc_clock eqc_eyeq6lplus_clks[] = { + PLL_FRACG(EQ6LPC_PLL_DDR, PARENT_BY_FWNAME, "pll-ddr", "ref", 0x02C), + PLL_FRACG(EQ6LPC_PLL_ACC, PARENT_BY_FWNAME, "pll-acc", "ref", 0x034), + PLL_FRACG(EQ6LPC_PLL_PER, PARENT_BY_FWNAME, "pll-per", "ref", 0x03C), + PLL_FRACG(EQ6LPC_PLL_VDI, PARENT_BY_FWNAME, "pll-vdi", "ref", 0x044), -static const struct eqc_fixed_factor eqc_eyeq6lplus_early_fixed_factors[] = { - { EQ6LPC_CPU_OCC, "occ-cpu", 1, 1, EQ6LPC_PLL_CPU }, -}; + FF(EQ6LPC_DDR_OCC, EQ6LPC_PLL_DDR, "occ-ddr", NULL, 1, 1), -static const struct eqc_fixed_factor eqc_eyeq6lplus_fixed_factors[] = { - { EQ6LPC_DDR_OCC, "occ-ddr", 1, 1, EQ6LPC_PLL_DDR }, + FF(EQ6LPC_ACC_VDI, EQ6LPC_PLL_ACC, "vdi-div", NULL, 1, 10), + FF(EQ6LPC_ACC_OCC, EQ6LPC_PLL_ACC, "occ-acc", NULL, 1, 1), + FF(EQ6LPC_ACC_FCMU, EQ6LPC_ACC_OCC, "fcmu-a-clk", NULL, 1, 10), - { EQ6LPC_ACC_VDI, "vdi-div", 1, 10, EQ6LPC_PLL_ACC }, - { EQ6LPC_ACC_OCC, "occ-acc", 1, 1, EQ6LPC_PLL_ACC }, - { EQ6LPC_ACC_FCMU, "fcmu-a-clk", 1, 10, EQ6LPC_ACC_OCC }, + FF(EQ6LPC_PER_OCC, EQ6LPC_PLL_PER, "occ-per", NULL, 1, 1), + FF(EQ6LPC_PER_I2C_SER, EQ6LPC_PER_OCC, "i2c-ser-clk", NULL, 1, 10), + FF(EQ6LPC_PER_PCLK, EQ6LPC_PER_OCC, "pclk", NULL, 1, 4), + FF(EQ6LPC_PER_TSU, EQ6LPC_PER_OCC, "tsu-clk", NULL, 1, 8), + FF(EQ6LPC_PER_OSPI, EQ6LPC_PER_OCC, "ospi-ref-clk", NULL, 1, 10), + FF(EQ6LPC_PER_GPIO, EQ6LPC_PER_OCC, "gpio-clk", NULL, 1, 4), + FF(EQ6LPC_PER_TIMER, EQ6LPC_PER_OCC, "timer-clk", NULL, 1, 4), + FF(EQ6LPC_PER_I2C, EQ6LPC_PER_OCC, "i2c-clk", NULL, 1, 4), + FF(EQ6LPC_PER_UART, EQ6LPC_PER_OCC, "uart-clk", NULL, 1, 4), + FF(EQ6LPC_PER_SPI, EQ6LPC_PER_OCC, "spi-clk", NULL, 1, 4), + FF(EQ6LPC_PER_PERIPH, EQ6LPC_PER_OCC, "periph-clk", NULL, 1, 1), - { EQ6LPC_PER_OCC, "occ-per", 1, 1, EQ6LPC_PLL_PER }, - { EQ6LPC_PER_I2C_SER, "i2c-ser-clk", 1, 10, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_PCLK, "pclk", 1, 4, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_TSU, "tsu-clk", 1, 8, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_OSPI, "ospi-ref-clk", 1, 10, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_GPIO, "gpio-clk", 1, 4, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_TIMER, "timer-clk", 1, 4, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_I2C, "i2c-clk", 1, 4, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_UART, "uart-clk", 1, 4, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_SPI, "spi-clk", 1, 4, EQ6LPC_PER_OCC }, - { EQ6LPC_PER_PERIPH, "periph-clk", 1, 1, EQ6LPC_PER_OCC }, - - { EQ6LPC_VDI_OCC, "occ-vdi", 1, 1, EQ6LPC_PLL_VDI }, + FF(EQ6LPC_VDI_OCC, EQ6LPC_PLL_VDI, "occ-vdi", NULL, 1, 1), }; static const struct eqc_early_match_data eqc_eyeq6lplus_early_match_data __initconst = { - .early_pll_count = ARRAY_SIZE(eqc_eyeq6lplus_early_plls), - .early_plls = eqc_eyeq6lplus_early_plls, + .early_clk_count = ARRAY_SIZE(eqc_eyeq6lplus_early_clks), + .early_clks = eqc_eyeq6lplus_early_clks, - .early_fixed_factor_count = ARRAY_SIZE(eqc_eyeq6lplus_early_fixed_factors), - .early_fixed_factors = eqc_eyeq6lplus_early_fixed_factors, - - .late_clk_count = ARRAY_SIZE(eqc_eyeq6lplus_plls) + - ARRAY_SIZE(eqc_eyeq6lplus_fixed_factors), + .late_clk_count = ARRAY_SIZE(eqc_eyeq6lplus_clks), }; static const struct eqc_match_data eqc_eyeq6lplus_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq6lplus_plls), - .plls = eqc_eyeq6lplus_plls, - - .fixed_factor_count = ARRAY_SIZE(eqc_eyeq6lplus_fixed_factors), - .fixed_factors = eqc_eyeq6lplus_fixed_factors, + .clk_count = ARRAY_SIZE(eqc_eyeq6lplus_clks), + .clks = eqc_eyeq6lplus_clks, .reset_auxdev_name = "reset", .pinctrl_auxdev_name = "pinctrl", - .early_clk_count = ARRAY_SIZE(eqc_eyeq6lplus_early_plls) + - ARRAY_SIZE(eqc_eyeq6lplus_early_fixed_factors), + .early_clk_count = ARRAY_SIZE(eqc_eyeq6lplus_early_clks), }; static const struct eqc_match_data eqc_eyeq6h_west_match_data = { .reset_auxdev_name = "reset_west", }; -static const struct eqc_pll eqc_eyeq6h_east_plls[] = { - { .index = 0, .name = "pll-east", .reg64 = 0x074 }, +static const struct eqc_clock eqc_eyeq6h_east_clks[] = { + PLL_FRACG(0, PARENT_BY_FWNAME, "pll-east", "ref", 0x074), }; static const struct eqc_match_data eqc_eyeq6h_east_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq6h_east_plls), - .plls = eqc_eyeq6h_east_plls, + .clk_count = ARRAY_SIZE(eqc_eyeq6h_east_clks), + .clks = eqc_eyeq6h_east_clks, .reset_auxdev_name = "reset_east", }; -static const struct eqc_pll eqc_eyeq6h_south_plls[] = { - { .index = EQ6HC_SOUTH_PLL_VDI, .name = "pll-vdi", .reg64 = 0x000 }, - { .index = EQ6HC_SOUTH_PLL_PCIE, .name = "pll-pcie", .reg64 = 0x008 }, - { .index = EQ6HC_SOUTH_PLL_PER, .name = "pll-per", .reg64 = 0x010 }, - { .index = EQ6HC_SOUTH_PLL_ISP, .name = "pll-isp", .reg64 = 0x018 }, -}; +static const struct eqc_clock eqc_eyeq6h_south_clks[] = { + PLL_FRACG(EQ6HC_SOUTH_PLL_VDI, PARENT_BY_FWNAME, "pll-vdi", "ref", 0x000), + PLL_FRACG(EQ6HC_SOUTH_PLL_PCIE, PARENT_BY_FWNAME, "pll-pcie", "ref", 0x008), + PLL_FRACG(EQ6HC_SOUTH_PLL_PER, PARENT_BY_FWNAME, "pll-per", "ref", 0x010), + PLL_FRACG(EQ6HC_SOUTH_PLL_ISP, PARENT_BY_FWNAME, "pll-isp", "ref", 0x018), -static const struct eqc_div eqc_eyeq6h_south_divs[] = { - { - .index = EQ6HC_SOUTH_DIV_EMMC, - .name = "div-emmc", - .parent = EQ6HC_SOUTH_PLL_PER, - .reg = 0x070, - .shift = 4, - .width = 4, - }, - { - .index = EQ6HC_SOUTH_DIV_OSPI_REF, - .name = "div-ospi-ref", - .parent = EQ6HC_SOUTH_PLL_PER, - .reg = 0x090, - .shift = 4, - .width = 4, - }, - { - .index = EQ6HC_SOUTH_DIV_OSPI_SYS, - .name = "div-ospi-sys", - .parent = EQ6HC_SOUTH_PLL_PER, - .reg = 0x090, - .shift = 8, - .width = 1, - }, - { - .index = EQ6HC_SOUTH_DIV_TSU, - .name = "div-tsu", - .parent = EQ6HC_SOUTH_PLL_PCIE, - .reg = 0x098, - .shift = 4, - .width = 8, - }, + DIV(EQ6HC_SOUTH_DIV_EMMC, EQ6HC_SOUTH_PLL_PER, "div-emmc", NULL, 0x070, 4, 4), + DIV(EQ6HC_SOUTH_DIV_OSPI_REF, EQ6HC_SOUTH_PLL_PER, "div-ospi-ref", NULL, 0x090, 4, 4), + DIV(EQ6HC_SOUTH_DIV_OSPI_SYS, EQ6HC_SOUTH_PLL_PER, "div-ospi-sys", NULL, 0x090, 8, 1), + DIV(EQ6HC_SOUTH_DIV_TSU, EQ6HC_SOUTH_PLL_PCIE, "div-tsu", NULL, 0x098, 4, 8), }; static const struct eqc_match_data eqc_eyeq6h_south_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq6h_south_plls), - .plls = eqc_eyeq6h_south_plls, - - .div_count = ARRAY_SIZE(eqc_eyeq6h_south_divs), - .divs = eqc_eyeq6h_south_divs, + .clk_count = ARRAY_SIZE(eqc_eyeq6h_south_clks), + .clks = eqc_eyeq6h_south_clks, }; -static const struct eqc_pll eqc_eyeq6h_ddr0_plls[] = { - { .index = 0, .name = "pll-ddr0", .reg64 = 0x074 }, +static const struct eqc_clock eqc_eyeq6h_ddr0_clks[] = { + PLL_FRACG(0, PARENT_BY_FWNAME, "pll-ddr0", "ref", 0x074), }; static const struct eqc_match_data eqc_eyeq6h_ddr0_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq6h_ddr0_plls), - .plls = eqc_eyeq6h_ddr0_plls, + .clk_count = ARRAY_SIZE(eqc_eyeq6h_ddr0_clks), + .clks = eqc_eyeq6h_ddr0_clks, }; -static const struct eqc_pll eqc_eyeq6h_ddr1_plls[] = { - { .index = 0, .name = "pll-ddr1", .reg64 = 0x074 }, +static const struct eqc_clock eqc_eyeq6h_ddr1_clks[] = { + PLL_FRACG(0, PARENT_BY_FWNAME, "pll-ddr1", "ref", 0x074), }; static const struct eqc_match_data eqc_eyeq6h_ddr1_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq6h_ddr1_plls), - .plls = eqc_eyeq6h_ddr1_plls, + .clk_count = ARRAY_SIZE(eqc_eyeq6h_ddr1_clks), + .clks = eqc_eyeq6h_ddr1_clks, }; -static const struct eqc_pll eqc_eyeq6h_acc_plls[] = { - { .index = EQ6HC_ACC_PLL_XNN, .name = "pll-xnn", .reg64 = 0x040 }, - { .index = EQ6HC_ACC_PLL_VMP, .name = "pll-vmp", .reg64 = 0x050 }, - { .index = EQ6HC_ACC_PLL_PMA, .name = "pll-pma", .reg64 = 0x05C }, - { .index = EQ6HC_ACC_PLL_MPC, .name = "pll-mpc", .reg64 = 0x068 }, - { .index = EQ6HC_ACC_PLL_NOC, .name = "pll-noc", .reg64 = 0x070 }, +static const struct eqc_clock eqc_eyeq6h_acc_clks[] = { + PLL_FRACG(EQ6HC_ACC_PLL_XNN, PARENT_BY_FWNAME, "pll-xnn", "ref", 0x040), + PLL_FRACG(EQ6HC_ACC_PLL_VMP, PARENT_BY_FWNAME, "pll-vmp", "ref", 0x050), + PLL_FRACG(EQ6HC_ACC_PLL_PMA, PARENT_BY_FWNAME, "pll-pma", "ref", 0x05C), + PLL_FRACG(EQ6HC_ACC_PLL_MPC, PARENT_BY_FWNAME, "pll-mpc", "ref", 0x068), + PLL_FRACG(EQ6HC_ACC_PLL_NOC, PARENT_BY_FWNAME, "pll-noc", "ref", 0x070), }; static const struct eqc_match_data eqc_eyeq6h_acc_match_data = { - .pll_count = ARRAY_SIZE(eqc_eyeq6h_acc_plls), - .plls = eqc_eyeq6h_acc_plls, + .clk_count = ARRAY_SIZE(eqc_eyeq6h_acc_clks), + .clks = eqc_eyeq6h_acc_clks, .reset_auxdev_name = "reset_acc", }; +static const struct eqc_clock eqc_eyeq7h_acc0_clks[] = { + PLL_AINTP(EQ7HC_ACC_PLL_VMP, PARENT_BY_FWNAME, "pll-acc0-vmp", "ref_100p0", 0x400), + PLL_AINTP(EQ7HC_ACC_PLL_MPC, PARENT_BY_FWNAME, "pll-acc0-mpc", "ref_100p0", 0x404), + PLL_AINTP(EQ7HC_ACC_PLL_PMA, PARENT_BY_FWNAME, "pll-acc0-pma", "ref_100p0", 0x408), + PLL_AINTP(EQ7HC_ACC_PLL_NOC, PARENT_BY_FWNAME, "pll-acc0-noc-acc", "ref_106p6", 0x40c), + + FF(EQ7HC_ACC_DIV_PMA, EQ7HC_ACC_PLL_PMA, "acc0_pma", NULL, 1, 2), + FF(EQ7HC_ACC_DIV_NCORE, EQ7HC_ACC_PLL_NOC, "acc0_ncore", NULL, 1, 2), + FF(EQ7HC_ACC_DIV_CFG, EQ7HC_ACC_PLL_NOC, "acc0_cfg", NULL, 1, 8), +}; + +static const struct eqc_match_data eqc_eyeq7h_acc0_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_acc0_clks), + .clks = eqc_eyeq7h_acc0_clks, + + .reset_auxdev_name = "reset_acc0", +}; + +static const struct eqc_clock eqc_eyeq7h_acc1_clks[] = { + PLL_AINTP(EQ7HC_ACC_PLL_VMP, PARENT_BY_FWNAME, "pll-acc1-vmp", "ref_100p0", 0x400), + PLL_AINTP(EQ7HC_ACC_PLL_MPC, PARENT_BY_FWNAME, "pll-acc1-mpc", "ref_100p0", 0x404), + PLL_AINTP(EQ7HC_ACC_PLL_PMA, PARENT_BY_FWNAME, "pll-acc1-pma", "ref_100p0", 0x408), + PLL_AINTP(EQ7HC_ACC_PLL_NOC, PARENT_BY_FWNAME, "pll-acc1-noc-acc", "ref_106p6", 0x40c), +}; + +static const struct eqc_match_data eqc_eyeq7h_acc1_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_acc1_clks), + .clks = eqc_eyeq7h_acc1_clks, + + .reset_auxdev_name = "reset_acc1", +}; + +static const struct clk_div_table eqc_eyeq7h_ddr_apb_div_table[] = { + { .val = 0, .div = 8 }, + { .val = 1, .div = 128 }, + { .val = 0, .div = 0 }, +}; + +static const struct clk_div_table eqc_eyeq7h_ddr_ref_div_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 8 }, + { .val = 0, .div = 0 }, +}; + +static const struct clk_div_table eqc_eyeq7h_ddr_dfi_div_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 32 }, + { .val = 0, .div = 0 }, +}; + +static const struct eqc_clock eqc_eyeq7h_ddr0_clks[] = { + PLL_AINTP(EQ7HC_DDR_PLL, PARENT_BY_FWNAME, "pll-ddr0", "ref", 0x0), + + /* A single bit configures the 3 dividers below */ + DIV_TABLE_RO(EQ7HC_DDR_DIV_APB, EQ7HC_DDR_PLL, "div-ddr0_apb", NULL, + 0x08, 10, 1, eqc_eyeq7h_ddr_apb_div_table), + DIV_TABLE_RO(EQ7HC_DDR_DIV_PLLREF, EQ7HC_DDR_PLL, "div-ddr0_pllref", NULL, + 0x08, 10, 1, eqc_eyeq7h_ddr_ref_div_table), + DIV_TABLE_RO(EQ7HC_DDR_DIV_DFI, EQ7HC_DDR_PLL, "div-ddr0-dfi", NULL, + 0x08, 10, 1, eqc_eyeq7h_ddr_dfi_div_table), +}; + +static const struct eqc_match_data eqc_eyeq7h_ddr0_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_ddr0_clks), + .clks = eqc_eyeq7h_ddr0_clks, + + .reset_auxdev_name = "reset_ddr0", +}; + +static const struct eqc_clock eqc_eyeq7h_ddr1_clks[] = { + PLL_AINTP(EQ7HC_DDR_PLL, PARENT_BY_FWNAME, "pll-ddr1", "ref", 0x0), + + /* A single bit configures the 3 dividers below */ + DIV_TABLE_RO(EQ7HC_DDR_DIV_APB, EQ7HC_DDR_PLL, "div-ddr1_apb", NULL, + 0x08, 10, 1, eqc_eyeq7h_ddr_apb_div_table), + DIV_TABLE_RO(EQ7HC_DDR_DIV_PLLREF, EQ7HC_DDR_PLL, "div-ddr1_pllref", NULL, + 0x08, 10, 1, eqc_eyeq7h_ddr_ref_div_table), + DIV_TABLE_RO(EQ7HC_DDR_DIV_DFI, EQ7HC_DDR_PLL, "div-ddr1-dfi", NULL, + 0x08, 10, 1, eqc_eyeq7h_ddr_dfi_div_table), +}; + +static const struct eqc_match_data eqc_eyeq7h_ddr1_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_ddr1_clks), + .clks = eqc_eyeq7h_ddr1_clks, + + .reset_auxdev_name = "reset_ddr1", +}; + +static const struct eqc_clock eqc_eyeq7h_east_clocks[] = { + PLL_JFRACR(EQ7HC_EAST_PLL_106P6, PARENT_BY_FWNAME, "pll-106p6-e", "ref", 0x00), + + FF(EQ7HC_EAST_DIV_REF_106P6, EQ7HC_EAST_PLL_106P6, "ref_106p6_e", NULL, 1, 40), + + PLL_AINTP(EQ7HC_EAST_PLL_NOC, EQ7HC_EAST_DIV_REF_106P6, "pll-noc-e", NULL, 0x30), + PLL_AINTP(EQ7HC_EAST_PLL_ISP, PARENT_BY_FWNAME, "pll-isp", "ref_100p0", 0x38), + PLL_AINTP(EQ7HC_EAST_PLL_VEU, PARENT_BY_FWNAME, "pll-veu", "ref_100p0", 0x40), + + FF(EQ7HC_EAST_DIV_REF_DDR_PHY, EQ7HC_EAST_PLL_106P6, "ref_ddr_phy_e", NULL, 1, 2), + + FF(EQ7HC_EAST_DIV_CORE, EQ7HC_EAST_PLL_NOC, "core_e", NULL, 1, 2), + FF(EQ7HC_EAST_DIV_CORE_MBIST, EQ7HC_EAST_PLL_NOC, "core_mbist_e", NULL, 1, 2), + FF(EQ7HC_EAST_DIV_ISRAM_MBIST, EQ7HC_EAST_PLL_NOC, "isram_mbist_e", NULL, 1, 2), + FF(EQ7HC_EAST_DIV_CFG, EQ7HC_EAST_PLL_NOC, "cfg_e", NULL, 1, 4), + + FF(EQ7HC_EAST_DIV_VEU_CORE, EQ7HC_EAST_PLL_VEU, "veu_core", NULL, 1, 4), + FF(EQ7HC_EAST_DIV_VEU_MBIST, EQ7HC_EAST_PLL_VEU, "veu_mbist", NULL, 1, 4), + FF(EQ7HC_EAST_DIV_VEU_OCP, EQ7HC_EAST_PLL_VEU, "veu_ocp", NULL, 1, 16), + + FF(EQ7HC_EAST_DIV_LBITS, EQ7HC_EAST_PLL_ISP, "lbits_e", NULL, 1, 48), + FF(EQ7HC_EAST_DIV_ISP0_CORE, EQ7HC_EAST_PLL_ISP, "isp0_core", NULL, 1, 2), +}; + +static const struct eqc_match_data eqc_eyeq7h_east_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_east_clocks), + .clks = eqc_eyeq7h_east_clocks, + + .reset_auxdev_name = "reset_east", +}; + +static const struct eqc_clock eqc_eyeq7h_mips0_clks[] = { + PLL_AINTP(EQ7HC_MIPS_PLL_CPU, PARENT_BY_FWNAME, "pll-cpu0", "ref", 0x0), + + FF(EQ7HC_MIPS_DIV_CM, EQ7HC_MIPS_PLL_CPU, "mips0_cm", NULL, 1, 2), +}; + +static const struct eqc_match_data eqc_eyeq7h_mips0_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_mips0_clks), + .clks = eqc_eyeq7h_mips0_clks, +}; + +static const struct eqc_clock eqc_eyeq7h_mips1_clks[] = { + PLL_AINTP(EQ7HC_MIPS_PLL_CPU, PARENT_BY_FWNAME, "pll-cpu1", "ref", 0x0), + + FF(EQ7HC_MIPS_DIV_CM, EQ7HC_MIPS_PLL_CPU, "mips1_cm", NULL, 1, 2), +}; + +static const struct eqc_match_data eqc_eyeq7h_mips1_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_mips1_clks), + .clks = eqc_eyeq7h_mips1_clks, +}; + +static const struct eqc_clock eqc_eyeq7h_mips2_clks[] = { + PLL_AINTP(EQ7HC_MIPS_PLL_CPU, PARENT_BY_FWNAME, "pll-cpu2", "ref", 0x0), + + FF(EQ7HC_MIPS_DIV_CM, EQ7HC_MIPS_PLL_CPU, "mips2_cm", NULL, 1, 2), +}; + +static const struct eqc_match_data eqc_eyeq7h_mips2_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_mips2_clks), + .clks = eqc_eyeq7h_mips2_clks, +}; + +static const struct eqc_clock eqc_eyeq7h_periph_east_clks[] = { + PLL_AINTP(EQ7HC_PERIPH_EAST_PLL_PER, PARENT_BY_FWNAME, "pll-periph_east_per", "ref", 0x0), + + FF(EQ7HC_PERIPH_EAST_DIV_PER, EQ7HC_PERIPH_EAST_PLL_PER, "periph_e", NULL, 1, 10), +}; + +static const struct eqc_match_data eqc_eyeq7h_periph_east_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_periph_east_clks), + .clks = eqc_eyeq7h_periph_east_clks, + + .reset_auxdev_name = "reset_periph_east", +}; + +static const struct eqc_clock eqc_eyeq7h_periph_west_clks[] = { + PLL_AINTP(EQ7HC_PERIPH_WEST_PLL_PER, PARENT_BY_FWNAME, + "pll-periph_west_per", "ref_100p0", 0x0), + PLL_AINTP(EQ7HC_PERIPH_WEST_PLL_I2S, PARENT_BY_FWNAME, + "pll-periph_west_i2s", "ref_106p6", 0x4), + + FF(EQ7HC_PERIPH_WEST_DIV_PER, EQ7HC_PERIPH_WEST_PLL_PER, "periph_w", NULL, 1, 10), + FF(EQ7HC_PERIPH_WEST_DIV_I2S, EQ7HC_PERIPH_WEST_PLL_I2S, "periph_i2s_ser_w", NULL, 1, 100), +}; + +static const struct eqc_match_data eqc_eyeq7h_periph_west_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_periph_west_clks), + .clks = eqc_eyeq7h_periph_west_clks, + + .reset_auxdev_name = "reset_periph_west", +}; + +static const struct eqc_clock eqc_eyeq7h_south_clks[] = { + PLL_JFRACR(EQ7HC_SOUTH_PLL_100P0, PARENT_BY_FWNAME, "pll-100p0", "ref", 0x40), + + FF(EQ7HC_SOUTH_DIV_REF_100P0, EQ7HC_SOUTH_PLL_100P0, "ref_100p0", NULL, 1, 48), + + PLL_AINTP(EQ7HC_SOUTH_PLL_XSPI, EQ7HC_SOUTH_DIV_REF_100P0, "pll-xspi", NULL, 0x10), + PLL_AINTP(EQ7HC_SOUTH_PLL_VDIO, EQ7HC_SOUTH_DIV_REF_100P0, "pll-vdio", NULL, 0x18), + PLL_AINTP(EQ7HC_SOUTH_PLL_PER, EQ7HC_SOUTH_DIV_REF_100P0, "pll-per-s", NULL, 0x20), + + FF(EQ7HC_SOUTH_DIV_VDO_DSI_SYS, EQ7HC_SOUTH_PLL_100P0, "vdo_dsi_sys", NULL, 1, 9), + FF(EQ7HC_SOUTH_DIV_PMA_CMN_REF, EQ7HC_SOUTH_PLL_100P0, "pma_cmn_ref", NULL, 1, 48), + FF(EQ7HC_SOUTH_DIV_REF_UFS, EQ7HC_SOUTH_PLL_100P0, "ref_ufs", NULL, 1, 250), + FF(EQ7HC_SOUTH_DIV_XSPI_SYS, EQ7HC_SOUTH_PLL_XSPI, "xspi_sys", NULL, 1, 8), + FF(EQ7HC_SOUTH_DIV_XSPI_MBIST, EQ7HC_SOUTH_PLL_XSPI, "xspi_mbist", NULL, 1, 8), + FF(EQ7HC_SOUTH_DIV_NOC_S, EQ7HC_SOUTH_PLL_PER, "noc_s", NULL, 1, 2), + FF(EQ7HC_SOUTH_DIV_PCIE_SYS, EQ7HC_SOUTH_PLL_PER, "pcie_sys", NULL, 1, 4), + FF(EQ7HC_SOUTH_DIV_PCIE_SYS_MBIST, EQ7HC_SOUTH_PLL_PER, "pcie_sys_mbist", NULL, 1, 4), + FF(EQ7HC_SOUTH_DIV_PCIE_GBE_PHY, EQ7HC_SOUTH_PLL_PER, "pcie_gbe_phy_apb", NULL, 1, 16), + FF(EQ7HC_SOUTH_DIV_UFS_CORE, EQ7HC_SOUTH_PLL_PER, "ufs_core", NULL, 1, 8), + FF(EQ7HC_SOUTH_DIV_UFS_SMS, EQ7HC_SOUTH_PLL_PER, "ufs_sms", NULL, 1, 5), + FF(EQ7HC_SOUTH_DIV_UFS_ROM_SMS, EQ7HC_SOUTH_PLL_PER, "ufs_rom_sms", NULL, 1, 5), + FF(EQ7HC_SOUTH_DIV_ETH_SYS, EQ7HC_SOUTH_PLL_PER, "eth_sys", NULL, 1, 8), + FF(EQ7HC_SOUTH_DIV_ETH_MBIST, EQ7HC_SOUTH_PLL_PER, "eth_mbist", NULL, 1, 8), + FF(EQ7HC_SOUTH_DIV_CFG_S, EQ7HC_SOUTH_PLL_PER, "cfg_s", NULL, 1, 8), + FF(EQ7HC_SOUTH_DIV_TSU, EQ7HC_SOUTH_PLL_PER, "tsu", NULL, 1, 64), + FF(EQ7HC_SOUTH_DIV_VDIO, EQ7HC_SOUTH_PLL_VDIO, "vdio", NULL, 1, 4), + FF(EQ7HC_SOUTH_DIV_VDIO_CORE, EQ7HC_SOUTH_PLL_VDIO, "vdio_core", NULL, 1, 4), + FF(EQ7HC_SOUTH_DIV_VDIO_CORE_MBIST, EQ7HC_SOUTH_PLL_VDIO, "vdio_core_mbist", NULL, 1, 4), + FF(EQ7HC_SOUTH_DIV_VDO_CORE_MBIST, EQ7HC_SOUTH_PLL_VDIO, "vdo_core_mbist", NULL, 1, 4), + FF(EQ7HC_SOUTH_DIV_VDO_P, EQ7HC_SOUTH_PLL_VDIO, "vdo_p", NULL, 1, 40), + FF(EQ7HC_SOUTH_DIV_VDIO_CFG, EQ7HC_SOUTH_PLL_VDIO, "vdio_cfg", NULL, 1, 150), + FF(EQ7HC_SOUTH_DIV_VDIO_TXCLKESC, EQ7HC_SOUTH_PLL_VDIO, "vdio_txclkesc", NULL, 1, 8), +}; + +static const struct eqc_match_data eqc_eyeq7h_south_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_south_clks), + .clks = eqc_eyeq7h_south_clks, + + .reset_auxdev_name = "reset_south", +}; + +static const struct eqc_clock eqc_eyeq7h_west_clks[] = { + PLL_JFRACR(EQ7HC_WEST_PLL_106P6, PARENT_BY_FWNAME, "pll-106p6-w", "ref", 0x0), + + FF(EQ7HC_WEST_DIV_REF_106P6, EQ7HC_WEST_PLL_106P6, "ref_106p6_w", NULL, 1, 40), + + PLL_AINTP(EQ7HC_WEST_PLL_NOC, EQ7HC_WEST_DIV_REF_106P6, "pll-noc-w", NULL, 0x30), + PLL_AINTP(EQ7HC_WEST_PLL_GPU, PARENT_BY_FWNAME, "pll-gpu", "ref_100p0", 0x38), + PLL_AINTP(EQ7HC_WEST_PLL_SSI, PARENT_BY_FWNAME, "pll-ssi", "ref_100p0", 0x40), + + FF(EQ7HC_WEST_DIV_GPU, EQ7HC_WEST_PLL_GPU, "gpu", NULL, 1, 2), + FF(EQ7HC_WEST_DIV_GPU_MBIST, EQ7HC_WEST_PLL_GPU, "gpu_mbist", NULL, 1, 2), + FF(EQ7HC_WEST_DIV_LBITS, EQ7HC_WEST_PLL_GPU, "lbits_w", NULL, 1, 40), + FF(EQ7HC_WEST_DIV_MIPS_TIMER, EQ7HC_WEST_PLL_SSI, "mips_timer", NULL, 1, 24), + FF(EQ7HC_WEST_DIV_SSI_CORE, EQ7HC_WEST_PLL_SSI, "ssi_core", NULL, 1, 2), + FF(EQ7HC_WEST_DIV_SSI_CORE_MBIST, EQ7HC_WEST_PLL_SSI, "ssi_core_mbist", NULL, 1, 2), + FF(EQ7HC_WEST_DIV_SSI_ROM, EQ7HC_WEST_PLL_SSI, "ssi_rom", NULL, 1, 8), + FF(EQ7HC_WEST_DIV_SSI_ROM_MBIST, EQ7HC_WEST_PLL_SSI, "ssi_rom_mbist", NULL, 1, 8), + FF(EQ7HC_WEST_DIV_REF_DDR_PHY, EQ7HC_WEST_PLL_106P6, "ref_ddr_phy_w", NULL, 1, 2), + FF(EQ7HC_WEST_DIV_CORE, EQ7HC_WEST_PLL_NOC, "core_w", NULL, 1, 2), + FF(EQ7HC_WEST_DIV_CORE_MBIST, EQ7HC_WEST_PLL_NOC, "core_mbist_w", NULL, 1, 2), + FF(EQ7HC_WEST_DIV_CFG, EQ7HC_WEST_PLL_NOC, "cfg_w", NULL, 1, 4), + FF(EQ7HC_WEST_DIV_CAU, EQ7HC_WEST_PLL_NOC, "cau_w", NULL, 1, 8), + FF(EQ7HC_WEST_DIV_CAU_MBIST, EQ7HC_WEST_PLL_NOC, "cau_mbist_w", NULL, 1, 8), +}; + +static const struct eqc_match_data eqc_eyeq7h_west_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_west_clks), + .clks = eqc_eyeq7h_west_clks, + + .reset_auxdev_name = "reset_west", +}; + +static const struct eqc_clock eqc_eyeq7h_xnn0_clks[] = { + PLL_AINTP(EQ7HC_XNN_PLL_XNN0, PARENT_BY_FWNAME, "pll-xnn0-0", "ref_100p0", 0x400), + PLL_AINTP(EQ7HC_XNN_PLL_XNN1, PARENT_BY_FWNAME, "pll-xnn0-1", "ref_100p0", 0x404), + PLL_AINTP(EQ7HC_XNN_PLL_XNN2, PARENT_BY_FWNAME, "pll-xnn0-2", "ref_100p0", 0x408), + PLL_AINTP(EQ7HC_XNN_PLL_CLSTR, PARENT_BY_FWNAME, "pll-xnn0-clstr", "ref_106p6", 0x410), + + FF(EQ7HC_XNN_DIV_XNN0, EQ7HC_XNN_PLL_XNN0, "xnn0", NULL, 1, 2), + FF(EQ7HC_XNN_DIV_XNN1, EQ7HC_XNN_PLL_XNN1, "xnn1", NULL, 1, 2), + FF(EQ7HC_XNN_DIV_XNN2, EQ7HC_XNN_PLL_XNN2, "xnn2", NULL, 1, 2), + FF(EQ7HC_XNN_DIV_CLSTR, EQ7HC_XNN_PLL_CLSTR, "xnn0_clstr", NULL, 1, 2), + FF(EQ7HC_XNN_DIV_I2, EQ7HC_XNN_PLL_CLSTR, "xnn0_i2", NULL, 1, 4), + FF(EQ7HC_XNN_DIV_I2_SMS, EQ7HC_XNN_PLL_CLSTR, "xnn0_i2_sms", NULL, 1, 4), + FF(EQ7HC_XNN_DIV_CFG, EQ7HC_XNN_PLL_CLSTR, "xnn0_cfg", NULL, 1, 8), +}; + +static const struct eqc_match_data eqc_eyeq7h_xnn0_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_xnn0_clks), + .clks = eqc_eyeq7h_xnn0_clks, + + .reset_auxdev_name = "reset_xnn0", +}; + +static const struct eqc_clock eqc_eyeq7h_xnn1_clks[] = { + PLL_AINTP(EQ7HC_XNN_PLL_XNN0, PARENT_BY_FWNAME, "pll-xnn1-0", "ref_100p0", 0x400), + PLL_AINTP(EQ7HC_XNN_PLL_XNN1, PARENT_BY_FWNAME, "pll-xnn1-1", "ref_100p0", 0x404), + PLL_AINTP(EQ7HC_XNN_PLL_XNN2, PARENT_BY_FWNAME, "pll-xnn1-2", "ref_100p0", 0x408), + PLL_AINTP(EQ7HC_XNN_PLL_CLSTR, PARENT_BY_FWNAME, "pll-xnn1-clstr", "ref_106p6", 0x410), +}; + +static const struct eqc_match_data eqc_eyeq7h_xnn1_match_data = { + .clk_count = ARRAY_SIZE(eqc_eyeq7h_xnn1_clks), + .clks = eqc_eyeq7h_xnn1_clks, + + .reset_auxdev_name = "reset_xnn1", +}; + static const struct of_device_id eqc_match_table[] = { { .compatible = "mobileye,eyeq5-olb", .data = &eqc_eyeq5_match_data }, { .compatible = "mobileye,eyeq6l-olb", .data = &eqc_eyeq6l_match_data }, @@ -711,6 +1181,22 @@ static const struct of_device_id eqc_match_table[] = { { .compatible = "mobileye,eyeq6h-ddr0-olb", .data = &eqc_eyeq6h_ddr0_match_data }, { .compatible = "mobileye,eyeq6h-ddr1-olb", .data = &eqc_eyeq6h_ddr1_match_data }, { .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqc_eyeq6h_acc_match_data }, + { .compatible = "mobileye,eyeq7h-acc0-olb", .data = &eqc_eyeq7h_acc0_match_data }, + { .compatible = "mobileye,eyeq7h-acc1-olb", .data = &eqc_eyeq7h_acc1_match_data }, + { .compatible = "mobileye,eyeq7h-ddr0-olb", .data = &eqc_eyeq7h_ddr0_match_data }, + { .compatible = "mobileye,eyeq7h-ddr1-olb", .data = &eqc_eyeq7h_ddr1_match_data }, + { .compatible = "mobileye,eyeq7h-east-olb", .data = &eqc_eyeq7h_east_match_data }, + { .compatible = "mobileye,eyeq7h-mips0-olb", .data = &eqc_eyeq7h_mips0_match_data }, + { .compatible = "mobileye,eyeq7h-mips1-olb", .data = &eqc_eyeq7h_mips1_match_data }, + { .compatible = "mobileye,eyeq7h-mips2-olb", .data = &eqc_eyeq7h_mips2_match_data }, + { .compatible = "mobileye,eyeq7h-periph-east-olb", + .data = &eqc_eyeq7h_periph_east_match_data }, + { .compatible = "mobileye,eyeq7h-periph-west-olb", + .data = &eqc_eyeq7h_periph_west_match_data }, + { .compatible = "mobileye,eyeq7h-south-olb", .data = &eqc_eyeq7h_south_match_data }, + { .compatible = "mobileye,eyeq7h-west-olb", .data = &eqc_eyeq7h_west_match_data }, + { .compatible = "mobileye,eyeq7h-xnn0-olb", .data = &eqc_eyeq7h_xnn0_match_data }, + { .compatible = "mobileye,eyeq7h-xnn1-olb", .data = &eqc_eyeq7h_xnn1_match_data }, {} }; @@ -725,38 +1211,28 @@ static struct platform_driver eqc_driver = { builtin_platform_driver(eqc_driver); /* Required early for GIC timer. */ -static const struct eqc_pll eqc_eyeq6h_central_early_plls[] = { - { .index = EQ6HC_CENTRAL_PLL_CPU, .name = "pll-cpu", .reg64 = 0x02C }, -}; +static const struct eqc_clock eqc_eyeq6h_central_early_clks[] = { + PLL_FRACG(EQ6HC_CENTRAL_PLL_CPU, PARENT_BY_FWNAME, "pll-cpu", "ref", 0x02C), -static const struct eqc_fixed_factor eqc_eyeq6h_central_early_fixed_factors[] = { - { EQ6HC_CENTRAL_CPU_OCC, "occ-cpu", 1, 1, EQ6HC_CENTRAL_PLL_CPU }, + FF(EQ6HC_CENTRAL_CPU_OCC, EQ6HC_CENTRAL_PLL_CPU, "occ-cpu", NULL, 1, 1), }; static const struct eqc_early_match_data eqc_eyeq6h_central_early_match_data __initconst = { - .early_pll_count = ARRAY_SIZE(eqc_eyeq6h_central_early_plls), - .early_plls = eqc_eyeq6h_central_early_plls, - - .early_fixed_factor_count = ARRAY_SIZE(eqc_eyeq6h_central_early_fixed_factors), - .early_fixed_factors = eqc_eyeq6h_central_early_fixed_factors, + .early_clk_count = ARRAY_SIZE(eqc_eyeq6h_central_early_clks), + .early_clks = eqc_eyeq6h_central_early_clks, }; /* Required early for UART. */ -static const struct eqc_pll eqc_eyeq6h_west_early_plls[] = { - { .index = EQ6HC_WEST_PLL_PER, .name = "pll-west", .reg64 = 0x074 }, -}; +static const struct eqc_clock eqc_eyeq6h_west_early_clks[] = { + PLL_FRACG(EQ6HC_WEST_PLL_PER, PARENT_BY_FWNAME, "pll-west", "ref", 0x074), -static const struct eqc_fixed_factor eqc_eyeq6h_west_early_fixed_factors[] = { - { EQ6HC_WEST_PER_OCC, "west-per-occ", 1, 10, EQ6HC_WEST_PLL_PER }, - { EQ6HC_WEST_PER_UART, "west-per-uart", 1, 1, EQ6HC_WEST_PER_OCC }, + FF(EQ6HC_WEST_PER_OCC, EQ6HC_WEST_PLL_PER, "west-per-occ", NULL, 1, 10), + FF(EQ6HC_WEST_PER_UART, EQ6HC_WEST_PER_OCC, "west-per-uart", NULL, 1, 1), }; static const struct eqc_early_match_data eqc_eyeq6h_west_early_match_data __initconst = { - .early_pll_count = ARRAY_SIZE(eqc_eyeq6h_west_early_plls), - .early_plls = eqc_eyeq6h_west_early_plls, - - .early_fixed_factor_count = ARRAY_SIZE(eqc_eyeq6h_west_early_fixed_factors), - .early_fixed_factors = eqc_eyeq6h_west_early_fixed_factors, + .early_clk_count = ARRAY_SIZE(eqc_eyeq6h_west_early_clks), + .early_clks = eqc_eyeq6h_west_early_clks, }; static void __init eqc_early_init(struct device_node *np, @@ -767,8 +1243,7 @@ static void __init eqc_early_init(struct device_node *np, void __iomem *base; int ret; - clk_count = early_data->early_pll_count + early_data->early_fixed_factor_count + - early_data->late_clk_count; + clk_count = early_data->early_clk_count + early_data->late_clk_count; cells = kzalloc_flex(*cells, hws, clk_count); if (!cells) { ret = -ENOMEM; @@ -794,44 +1269,15 @@ static void __init eqc_early_init(struct device_node *np, goto err; } - for (i = 0; i < early_data->early_pll_count; i++) { - const struct eqc_pll *pll = &early_data->early_plls[i]; - unsigned long mult, div, acc; - struct clk_hw *hw; - u32 r0, r1; - u64 val; + for (i = 0; i < early_data->early_clk_count; i++) { + const struct eqc_clock *clk = &early_data->early_clks[i]; - val = readq(base + pll->reg64); - r0 = val; - r1 = val >> 32; - - ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc); + if (clk->probe) + ret = clk->probe(NULL, np, clk, base, cells); + else + ret = -EINVAL; if (ret) { - pr_err("failed parsing state of %s\n", pll->name); - goto err; - } - - hw = clk_hw_register_fixed_factor_with_accuracy_fwname(NULL, - np, pll->name, "ref", 0, mult, div, acc); - cells->hws[pll->index] = hw; - if (IS_ERR(hw)) { - pr_err("failed registering %s: %pe\n", pll->name, hw); - ret = PTR_ERR(hw); - goto err; - } - } - - for (i = 0; i < early_data->early_fixed_factor_count; i++) { - const struct eqc_fixed_factor *ff = &early_data->early_fixed_factors[i]; - struct clk_hw *parent_hw = cells->hws[ff->parent]; - struct clk_hw *hw; - - hw = clk_hw_register_fixed_factor_parent_hw(NULL, ff->name, - parent_hw, 0, ff->mult, ff->div); - cells->hws[ff->index] = hw; - if (IS_ERR(hw)) { - pr_err("failed registering %s: %pe\n", ff->name, hw); - ret = PTR_ERR(hw); + pr_err("failed registering %s\n", clk->name); goto err; } } @@ -857,12 +1303,12 @@ static void __init eqc_early_init(struct device_node *np, if (cells) { of_clk_del_provider(np); - for (i = 0; i < early_data->early_pll_count; i++) { - const struct eqc_pll *pll = &early_data->early_plls[i]; - struct clk_hw *hw = cells->hws[pll->index]; + for (i = 0; i < early_data->early_clk_count; i++) { + const struct eqc_clock *clk = &early_data->early_clks[i]; + struct clk_hw *hw = cells->hws[clk->index]; - if (!IS_ERR_OR_NULL(hw)) - clk_hw_unregister_fixed_factor(hw); + if (!IS_ERR_OR_NULL(hw) && clk->unregister) + clk->unregister(hw); } kfree(cells); diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 850e8b95f352..ae473e0af903 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -36,10 +36,14 @@ static int clk_factor_determine_rate(struct clk_hw *hw, struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + struct clk_hw *parent_hw = clk_hw_get_parent(hw); unsigned long best_parent; + if (!parent_hw) + return -EINVAL; + best_parent = (req->rate / fix->mult) * fix->div; - req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent); + req->best_parent_rate = clk_hw_round_rate(parent_hw, best_parent); } req->rate = (req->best_parent_rate / fix->div) * fix->mult; @@ -90,7 +94,7 @@ static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void * clk_hw_unregister(&fix->hw); } -static struct clk_hw * +struct clk_hw * __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *pdata, @@ -124,13 +128,13 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, init.name = name; init.ops = &clk_fixed_factor_ops; init.flags = flags; - if (parent_name) - init.parent_names = &parent_name; - else if (parent_hw) - init.parent_hws = &parent_hw; + init.parent_names = parent_name ? &parent_name : NULL; + init.parent_hws = parent_hw ? &parent_hw : NULL; + init.parent_data = pdata; + if (parent_name || parent_hw || pdata) + init.num_parents = 1; else - init.parent_data = pdata; - init.num_parents = 1; + init.num_parents = 0; hw = &fix->hw; if (dev) @@ -148,6 +152,7 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, return hw; } +EXPORT_SYMBOL_GPL(__clk_hw_register_fixed_factor); /** * devm_clk_hw_register_fixed_factor_index - Register a fixed factor clock with @@ -173,52 +178,6 @@ struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev, } EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_index); -/** - * devm_clk_hw_register_fixed_factor_parent_hw - Register a fixed factor clock with - * pointer to parent clock - * @dev: device that is registering this clock - * @name: name of this clock - * @parent_hw: pointer to parent clk - * @flags: fixed factor flags - * @mult: multiplier - * @div: divider - * - * Return: Pointer to fixed factor clk_hw structure that was registered or - * an error pointer. - */ -struct clk_hw *devm_clk_hw_register_fixed_factor_parent_hw(struct device *dev, - const char *name, const struct clk_hw *parent_hw, - unsigned long flags, unsigned int mult, unsigned int div) -{ - const struct clk_parent_data pdata = { .index = -1 }; - - return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, parent_hw, - &pdata, flags, mult, div, 0, 0, true); -} -EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_parent_hw); - -struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev, - const char *name, const struct clk_hw *parent_hw, - unsigned long flags, unsigned int mult, unsigned int div) -{ - const struct clk_parent_data pdata = { .index = -1 }; - - return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, parent_hw, - &pdata, flags, mult, div, 0, 0, false); -} -EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_parent_hw); - -struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, - const char *name, const char *parent_name, unsigned long flags, - unsigned int mult, unsigned int div) -{ - const struct clk_parent_data pdata = { .index = -1 }; - - return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL, - &pdata, flags, mult, div, 0, 0, false); -} -EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor); - struct clk_hw *clk_hw_register_fixed_factor_fwname(struct device *dev, struct device_node *np, const char *name, const char *fw_name, unsigned long flags, unsigned int mult, unsigned int div) @@ -292,17 +251,6 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw) } EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor); -struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev, - const char *name, const char *parent_name, unsigned long flags, - unsigned int mult, unsigned int div) -{ - const struct clk_parent_data pdata = { .index = -1 }; - - return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL, - &pdata, flags, mult, div, 0, 0, true); -} -EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor); - struct clk_hw *devm_clk_hw_register_fixed_factor_fwname(struct device *dev, struct device_node *np, const char *name, const char *fw_name, unsigned long flags, unsigned int mult, unsigned int div) diff --git a/drivers/reset/reset-eyeq.c b/drivers/reset/reset-eyeq.c index 7b9ab574bd65..f2533086bb76 100644 --- a/drivers/reset/reset-eyeq.c +++ b/drivers/reset/reset-eyeq.c @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Reset driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms. + * Reset driver for the Mobileye EyeQ5, EyeQ6L, EyeQ6H and EyeQ7H platforms. * * Controllers live in a shared register region called OLB. EyeQ5 and EyeQ6L * have a single OLB instance for a single reset controller. EyeQ6H has seven - * OLB instances; three host reset controllers. + * OLB instances; three host reset controllers. EyeQ7H has fourteen OLB instances; + * eleven host reset controllers. * * Each reset controller has one or more domain. Domains are of a given type * (see enum eqr_domain_type), with a valid offset mask (up to 32 resets per @@ -73,6 +74,43 @@ * 9. PMA0 10. PMA1 11. MPC0 12. MPC1 * 13. MPC2 14. MPC3 15. PERIPH * + * Known resets in EyeQ7H acc domain 0 (type EQR_EYEQ7H_ACRP) + * 0. VMP0 1. XVMP1 2. VMP2 3. VMP3 + * 4. MPC0 5. MPC1 6. PMA0 7. PMA1 + * + * Known resets in EyeQ7H acc domain 1 (type EQR_EYEQ7H_ACC) + * 0. NCORE0 1. NCORE1 2. NCORE0_M 3. NCORE1_M + * 4. NCORE_NOC 5. VMP_NOC 6. MPC_NOC 7. PMA_NOC + * + * Known resets in EyeQ7H ddr (type EQR_EYEQ7H_CFG) + * 0. APB 1. DMI 2. DFI 3. PHY_SMS + * 4. CTL_SMS + * + * Known resets in EyeQ7H east (type EQR_EYEQ7H_CFG) + * 0. ISP 1. VEU 2. LBIST + * + * Known resets in EyeQ7H periph (type EQR_EYEQ6H_SARCR) + * 0. gpio 1.EXT TIMER 2.UART 3. SPI + * 4. I2C0 5. I2C1 6.I2C2 7. I2S + * + * Known resets in EyeQ7H south domain 0 (type EQR_EYEQ7H_CFG) + * 0. PCI_PHY 1. PCI_CTL 2. S_NOC 3. GBE_PHY + * 4. GBE_CTL + * + * Known resets in EyeQ7H south domain 1 (type EQR_EYEQ7H_CFG) + * 0. XSPI 1. UFS 2. VDIO + * + * Known resets in EyeQ7H west (type EQR_EYEQ7H_CFG) + * 0. GPU 1. CAU 2. LBIST 3. GPU_LBIST + * + * Known resets in EyeQ7H xnn domain 0 (type EQR_EYEQ7H_ACRP) + * 0. XNN0 1. XNN1 2.XNN2 + * + * Known resets in EyeQ7H xnn domain 1 (type EQR_EYEQ7H_ACC) + * 0. XNN0 1. XNN1 2. XNN2 3. XNN3 + * 4. NCORE 5. L2_0 6. L2_1 7. SMS_0 + * 8. SMS_1 + * * Abbreviations: * - PMA: Programmable Macro Array * - MPC: Multi-threaded Processing Clusters @@ -113,6 +151,11 @@ enum eqr_domain_type { EQR_EYEQ5_ACRP, EQR_EYEQ5_PCIE, EQR_EYEQ6H_SARCR, + EQR_EYEQ7H_ACC, + EQR_EYEQ7H_ACRP, + EQR_EYEQ7H_CFG, + + EQR_NB_DOM_TYPES /* number of domain types, keep at the end */ }; /* @@ -137,16 +180,34 @@ enum eqr_domain_type { #define EQR_EYEQ6H_SARCR_RST_STATUS (0x008) #define EQR_EYEQ6H_SARCR_CLK_REQUEST (0x00C) +/* + * Domain type EQR_EYEQ7H_ACC register offsets. + */ +#define EQR_EYEQ7H_ACC_CLK_EN (0x000) +#define EQR_EYEQ7H_ACC_RST_EN (0x004) + +/* + * Domain type EQR_EYEQ7H_ACRP register masks. + * Registers are: base + 4 * offset. + */ +#define EQR_EYEQ7H_ACRP_PD_REQ BIT(0) +#define EQR_EYEQ7H_ACRP_MBIST_CFG GENMASK(3, 1) +#define EQR_EYEQ7H_ACRP_ST_POWER_DOWN BIT(13) +#define EQR_EYEQ7H_ACRP_ST_ACTIVE BIT(14) + struct eqr_busy_wait_timings { unsigned long sleep_us; unsigned long timeout_us; }; -static const struct eqr_busy_wait_timings eqr_timings[] = { +static const struct eqr_busy_wait_timings eqr_timings[EQR_NB_DOM_TYPES] = { [EQR_EYEQ5_SARCR] = {1, 10}, [EQR_EYEQ5_ACRP] = {1, 40 * USEC_PER_MSEC}, /* LBIST implies long timeout. */ /* EQR_EYEQ5_PCIE does no busy waiting. */ [EQR_EYEQ6H_SARCR] = {1, 400}, + /* EQR_EYEQ7H_ACC does no busy waiting. */ + [EQR_EYEQ7H_ACRP] = {1, 40 * USEC_PER_MSEC}, + /* EQR_EYEQ7H_CFG does no busy waiting. */ }; #define EQR_MAX_DOMAIN_COUNT 3 @@ -220,10 +281,6 @@ static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev, sleep_us, timeout_us); break; - case EQR_EYEQ5_PCIE: - ret = 0; /* No busy waiting. */ - break; - case EQR_EYEQ6H_SARCR: /* * Wait until both bits change: @@ -240,6 +297,23 @@ static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev, &rst_status, &clk_status); break; + case EQR_EYEQ7H_ACRP: + reg = base + 4 * offset; + if (assert) + mask = EQR_EYEQ7H_ACRP_ST_POWER_DOWN; + else + mask = EQR_EYEQ7H_ACRP_ST_ACTIVE; + + ret = readl_poll_timeout(reg, val, !!(val & mask), + sleep_us, timeout_us); + break; + + case EQR_EYEQ5_PCIE: + case EQR_EYEQ7H_ACC: + case EQR_EYEQ7H_CFG: + ret = 0; /* No busy waiting. */ + break; + default: WARN_ON(1); ret = -EINVAL; @@ -284,6 +358,28 @@ static void eqr_assert_locked(struct eqr_private *priv, u32 domain, u32 offset) writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST); break; + case EQR_EYEQ7H_ACC: + /* RST_REQUEST and CLK_REQUEST must be kept in sync. */ + val = readl(base + EQR_EYEQ7H_ACC_RST_EN); + val &= ~BIT(offset); + writel(val, base + EQR_EYEQ7H_ACC_RST_EN); + writel(val, base + EQR_EYEQ7H_ACC_CLK_EN); + break; + + case EQR_EYEQ7H_ACRP: + /* set powerdown and leave MBIST bits at zero */ + reg = base + 4 * offset; + val = readl(reg) & ~EQR_EYEQ7H_ACRP_MBIST_CFG; + writel(val | EQR_EYEQ7H_ACRP_PD_REQ, reg); + break; + + case EQR_EYEQ7H_CFG: + /* clear clock enable and NRESET bits */ + val = readl(base); + val &= ~GENMASK(2 * offset + 1, 2 * offset); + writel(val, base); + break; + default: WARN_ON(1); break; @@ -338,6 +434,28 @@ static void eqr_deassert_locked(struct eqr_private *priv, u32 domain, writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST); break; + case EQR_EYEQ7H_ACC: + /* RST_REQUEST and CLK_REQUEST must be kept in sync. */ + val = readl(base + EQR_EYEQ7H_ACC_RST_EN); + val |= BIT(offset); + writel(val, base + EQR_EYEQ7H_ACC_RST_EN); + writel(val, base + EQR_EYEQ7H_ACC_CLK_EN); + break; + + case EQR_EYEQ7H_ACRP: + /* clear powerdown and leave MBIST bits at zero */ + reg = base + 4 * offset; + val = readl(reg) & ~EQR_EYEQ7H_ACRP_MBIST_CFG; + writel(val & ~EQR_EYEQ7H_ACRP_PD_REQ, reg); + break; + + case EQR_EYEQ7H_CFG: + /* set clock enable and NRESET bits */ + val = readl(base); + val |= GENMASK(2 * offset + 1, 2 * offset); + writel(val, base); + break; + default: WARN_ON(1); break; @@ -384,6 +502,14 @@ static int eqr_status(struct reset_controller_dev *rcdev, unsigned long id) case EQR_EYEQ6H_SARCR: reg = base + EQR_EYEQ6H_SARCR_RST_STATUS; return !(readl(reg) & BIT(offset)); + case EQR_EYEQ7H_ACC: + reg = base + EQR_EYEQ7H_ACC_RST_EN; + return !(readl(reg) & BIT(offset)); + case EQR_EYEQ7H_ACRP: + reg = base + 4 * offset; + return !(readl(reg) & EQR_EYEQ7H_ACRP_ST_ACTIVE); + case EQR_EYEQ7H_CFG: + return !(readl(base) & BIT(2 * offset)); default: return -EINVAL; } @@ -557,6 +683,113 @@ static const struct eqr_match_data eqr_eyeq6h_acc_data = { .domains = eqr_eyeq6h_acc_domains, }; +static const struct eqr_domain_descriptor eqr_eyeq7h_acc_domains[] = { + { + .type = EQR_EYEQ7H_ACRP, + .valid_mask = 0xFF, + .offset = 0x000, + }, + { + .type = EQR_EYEQ7H_ACC, + .valid_mask = 0xFF, + .offset = 0x060, + }, +}; + +static const struct eqr_match_data eqr_eyeq7h_acc_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq7h_acc_domains), + .domains = eqr_eyeq7h_acc_domains, +}; + +static const struct eqr_domain_descriptor eqr_eyeq7h_ddr_domains[] = { + { + .type = EQR_EYEQ7H_CFG, + .valid_mask = 0x1F, + .offset = 0x008, + }, +}; + +static const struct eqr_match_data eqr_eyeq7h_ddr_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq7h_ddr_domains), + .domains = eqr_eyeq7h_ddr_domains, +}; + +static const struct eqr_domain_descriptor eqr_eyeq7h_east_domains[] = { + { + .type = EQR_EYEQ7H_CFG, + .valid_mask = 0x7, + .offset = 0x060, + }, +}; + +static const struct eqr_match_data eqr_eyeq7h_east_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq7h_east_domains), + .domains = eqr_eyeq7h_east_domains, +}; + +/* Periph OLBs each have an instance. */ +static const struct eqr_domain_descriptor eqr_eyeq7h_per_domains[] = { + { + .type = EQR_EYEQ6H_SARCR, + .valid_mask = 0xFF, + .offset = 0x030, + }, +}; + +static const struct eqr_match_data eqr_eyeq7h_per_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq7h_per_domains), + .domains = eqr_eyeq7h_per_domains, +}; + +static const struct eqr_domain_descriptor eqr_eyeq7h_south_domains[] = { + { + .type = EQR_EYEQ7H_CFG, + .valid_mask = 0x1F, + .offset = 0x070, + }, + { + .type = EQR_EYEQ7H_CFG, + .valid_mask = 0x7, + .offset = 0x074, + }, +}; + +static const struct eqr_match_data eqr_eyeq7h_south_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq7h_south_domains), + .domains = eqr_eyeq7h_south_domains, +}; + +static const struct eqr_domain_descriptor eqr_eyeq7h_west_domains[] = { + { + .type = EQR_EYEQ7H_CFG, + .valid_mask = 0xf, + .offset = 0x068, + }, +}; + +static const struct eqr_match_data eqr_eyeq7h_west_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq7h_west_domains), + .domains = eqr_eyeq7h_west_domains, +}; + +static const struct eqr_domain_descriptor eqr_eyeq7h_xnn_domains[] = { + { + .type = EQR_EYEQ7H_ACRP, + .valid_mask = 0x7, + .offset = 0x000, + }, + { + .type = EQR_EYEQ7H_ACC, + .valid_mask = 0x1FF, + .offset = 0x060, + }, +}; + +static const struct eqr_match_data eqr_eyeq7h_xnn_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq7h_xnn_domains), + .domains = eqr_eyeq7h_xnn_domains, +}; + /* * Table describes OLB system-controller compatibles. * It does not get used to match against devicetree node. @@ -568,15 +801,35 @@ static const struct of_device_id eqr_match_table[] = { { .compatible = "mobileye,eyeq6h-west-olb", .data = &eqr_eyeq6h_we_data }, { .compatible = "mobileye,eyeq6h-east-olb", .data = &eqr_eyeq6h_we_data }, { .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqr_eyeq6h_acc_data }, + { .compatible = "mobileye,eyeq7h-acc0-olb", .data = &eqr_eyeq7h_acc_data }, + { .compatible = "mobileye,eyeq7h-acc1-olb", .data = &eqr_eyeq7h_acc_data }, + { .compatible = "mobileye,eyeq7h-ddr0-olb", .data = &eqr_eyeq7h_ddr_data }, + { .compatible = "mobileye,eyeq7h-ddr1-olb", .data = &eqr_eyeq7h_ddr_data }, + { .compatible = "mobileye,eyeq7h-east-olb", .data = &eqr_eyeq7h_east_data }, + { .compatible = "mobileye,eyeq7h-periph-east-olb", .data = &eqr_eyeq7h_per_data }, + { .compatible = "mobileye,eyeq7h-periph-west-olb", .data = &eqr_eyeq7h_per_data }, + { .compatible = "mobileye,eyeq7h-south-olb", .data = &eqr_eyeq7h_south_data }, + { .compatible = "mobileye,eyeq7h-west-olb", .data = &eqr_eyeq7h_west_data }, + { .compatible = "mobileye,eyeq7h-xnn0-olb", .data = &eqr_eyeq7h_xnn_data }, + { .compatible = "mobileye,eyeq7h-xnn1-olb", .data = &eqr_eyeq7h_xnn_data }, {} }; MODULE_DEVICE_TABLE(of, eqr_match_table); static const struct auxiliary_device_id eqr_id_table[] = { { .name = "clk_eyeq.reset" }, - { .name = "clk_eyeq.reset_west" }, - { .name = "clk_eyeq.reset_east" }, { .name = "clk_eyeq.reset_acc" }, + { .name = "clk_eyeq.reset_acc0" }, + { .name = "clk_eyeq.reset_acc1" }, + { .name = "clk_eyeq.reset_ddr0" }, + { .name = "clk_eyeq.reset_ddr1" }, + { .name = "clk_eyeq.reset_east" }, + { .name = "clk_eyeq.reset_periph_east" }, + { .name = "clk_eyeq.reset_periph_west" }, + { .name = "clk_eyeq.reset_south" }, + { .name = "clk_eyeq.reset_west" }, + { .name = "clk_eyeq.reset_xnn0" }, + { .name = "clk_eyeq.reset_xnn1" }, {} }; MODULE_DEVICE_TABLE(auxiliary, eqr_id_table); diff --git a/include/dt-bindings/clock/mobileye,eyeq7h-clk.h b/include/dt-bindings/clock/mobileye,eyeq7h-clk.h new file mode 100644 index 000000000000..76e06a0abd02 --- /dev/null +++ b/include/dt-bindings/clock/mobileye,eyeq7h-clk.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2025 Mobileye Vision Technologies Ltd. + */ + +#ifndef _DT_BINDINGS_CLOCK_MOBILEYE_EYEQ7H_CLK_H +#define _DT_BINDINGS_CLOCK_MOBILEYE_EYEQ7H_CLK_H + +/* ACC0 and ACC1 OLBs PLL and dividers */ +#define EQ7HC_ACC_PLL_VMP 0 +#define EQ7HC_ACC_PLL_MPC 1 +#define EQ7HC_ACC_PLL_PMA 2 +#define EQ7HC_ACC_PLL_NOC 3 +#define EQ7HC_ACC_DIV_PMA 4 +#define EQ7HC_ACC_DIV_NCORE 5 +#define EQ7HC_ACC_DIV_CFG 6 + +/* DDR0 and DDR1 OLBs PLL and dividers */ +#define EQ7HC_DDR_PLL 0 +#define EQ7HC_DDR_DIV_APB 1 +#define EQ7HC_DDR_DIV_PLLREF 2 +#define EQ7HC_DDR_DIV_DFI 3 + +/* east OLB PLL and dividers */ +#define EQ7HC_EAST_PLL_106P6 0 +#define EQ7HC_EAST_DIV_REF_106P6 1 +#define EQ7HC_EAST_PLL_NOC 2 +#define EQ7HC_EAST_PLL_ISP 3 +#define EQ7HC_EAST_PLL_VEU 4 +#define EQ7HC_EAST_DIV_REF_DDR_PHY 5 +#define EQ7HC_EAST_DIV_CORE 6 +#define EQ7HC_EAST_DIV_CORE_MBIST 7 +#define EQ7HC_EAST_DIV_ISRAM_MBIST 8 +#define EQ7HC_EAST_DIV_CFG 9 +#define EQ7HC_EAST_DIV_VEU_CORE 10 +#define EQ7HC_EAST_DIV_VEU_MBIST 11 +#define EQ7HC_EAST_DIV_VEU_OCP 12 +#define EQ7HC_EAST_DIV_LBITS 13 +#define EQ7HC_EAST_DIV_ISP0_CORE 14 + +/* MIPS0, MIPS1 and MIPS2 OLBs PLL and dividers */ +#define EQ7HC_MIPS_PLL_CPU 0 +#define EQ7HC_MIPS_DIV_CM 1 + +/* periph east OLB PLL and dividers */ +#define EQ7HC_PERIPH_EAST_PLL_PER 0 +#define EQ7HC_PERIPH_EAST_DIV_PER 1 + +/* periph west OLB PLL and dividers */ +#define EQ7HC_PERIPH_WEST_PLL_PER 0 +#define EQ7HC_PERIPH_WEST_PLL_I2S 1 +#define EQ7HC_PERIPH_WEST_DIV_PER 2 +#define EQ7HC_PERIPH_WEST_DIV_I2S 3 + +/* south OLB PLL and dividers */ +#define EQ7HC_SOUTH_PLL_100P0 0 +#define EQ7HC_SOUTH_DIV_REF_100P0 1 +#define EQ7HC_SOUTH_PLL_XSPI 2 +#define EQ7HC_SOUTH_PLL_VDIO 3 +#define EQ7HC_SOUTH_PLL_PER 4 +#define EQ7HC_SOUTH_DIV_VDO_DSI_SYS 5 +#define EQ7HC_SOUTH_DIV_PMA_CMN_REF 6 +#define EQ7HC_SOUTH_DIV_REF_UFS 7 +#define EQ7HC_SOUTH_DIV_XSPI_SYS 8 +#define EQ7HC_SOUTH_DIV_XSPI_MBIST 9 +#define EQ7HC_SOUTH_DIV_NOC_S 10 +#define EQ7HC_SOUTH_DIV_PCIE_SYS 11 +#define EQ7HC_SOUTH_DIV_PCIE_SYS_MBIST 12 +#define EQ7HC_SOUTH_DIV_PCIE_GBE_PHY 13 +#define EQ7HC_SOUTH_DIV_UFS_CORE 14 +#define EQ7HC_SOUTH_DIV_UFS_SMS 15 +#define EQ7HC_SOUTH_DIV_UFS_ROM_SMS 16 +#define EQ7HC_SOUTH_DIV_ETH_SYS 17 +#define EQ7HC_SOUTH_DIV_ETH_MBIST 18 +#define EQ7HC_SOUTH_DIV_CFG_S 19 +#define EQ7HC_SOUTH_DIV_TSU 20 +#define EQ7HC_SOUTH_DIV_VDIO 21 +#define EQ7HC_SOUTH_DIV_VDIO_CORE 22 +#define EQ7HC_SOUTH_DIV_VDIO_CORE_MBIST 23 +#define EQ7HC_SOUTH_DIV_VDO_CORE_MBIST 24 +#define EQ7HC_SOUTH_DIV_VDO_P 25 +#define EQ7HC_SOUTH_DIV_VDIO_CFG 26 +#define EQ7HC_SOUTH_DIV_VDIO_TXCLKESC 27 + +/* west OLB PLL and dividers */ +#define EQ7HC_WEST_PLL_106P6 0 +#define EQ7HC_WEST_DIV_REF_106P6 1 +#define EQ7HC_WEST_PLL_NOC 2 +#define EQ7HC_WEST_PLL_GPU 3 +#define EQ7HC_WEST_PLL_SSI 4 +#define EQ7HC_WEST_DIV_GPU 5 +#define EQ7HC_WEST_DIV_GPU_MBIST 6 +#define EQ7HC_WEST_DIV_LBITS 7 +#define EQ7HC_WEST_DIV_MIPS_TIMER 8 +#define EQ7HC_WEST_DIV_SSI_CORE 9 +#define EQ7HC_WEST_DIV_SSI_CORE_MBIST 10 +#define EQ7HC_WEST_DIV_SSI_ROM 11 +#define EQ7HC_WEST_DIV_SSI_ROM_MBIST 12 +#define EQ7HC_WEST_DIV_REF_DDR_PHY 13 +#define EQ7HC_WEST_DIV_CORE 14 +#define EQ7HC_WEST_DIV_CORE_MBIST 15 +#define EQ7HC_WEST_DIV_CFG 16 +#define EQ7HC_WEST_DIV_CAU 17 +#define EQ7HC_WEST_DIV_CAU_MBIST 18 + +/* XNN0 and XNN1 OLBs PLL and dividers */ +#define EQ7HC_XNN_PLL_XNN0 0 +#define EQ7HC_XNN_PLL_XNN1 1 +#define EQ7HC_XNN_PLL_XNN2 2 +#define EQ7HC_XNN_PLL_CLSTR 3 +#define EQ7HC_XNN_DIV_XNN0 4 +#define EQ7HC_XNN_DIV_XNN1 5 +#define EQ7HC_XNN_DIV_XNN2 6 +#define EQ7HC_XNN_DIV_CLSTR 7 +#define EQ7HC_XNN_DIV_I2 8 +#define EQ7HC_XNN_DIV_I2_SMS 9 +#define EQ7HC_XNN_DIV_CFG 10 + +#endif diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index b01a38fef8cf..aba71f5dcc21 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1152,13 +1152,16 @@ struct clk_fixed_factor { #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw) extern const struct clk_ops clk_fixed_factor_ops; +struct clk_hw * +__clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, + const char *name, const char *parent_name, + const struct clk_hw *parent_hw, const struct clk_parent_data *pdata, + unsigned long flags, unsigned int mult, unsigned int div, + unsigned long acc, unsigned int fixflags, bool devm); struct clk *clk_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div); void clk_unregister_fixed_factor(struct clk *clk); -struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, - const char *name, const char *parent_name, unsigned long flags, - unsigned int mult, unsigned int div); struct clk_hw *clk_hw_register_fixed_factor_fwname(struct device *dev, struct device_node *np, const char *name, const char *fw_name, unsigned long flags, unsigned int mult, unsigned int div); @@ -1170,9 +1173,6 @@ struct clk_hw *clk_hw_register_fixed_factor_index(struct device *dev, const char *name, unsigned int index, unsigned long flags, unsigned int mult, unsigned int div); void clk_hw_unregister_fixed_factor(struct clk_hw *hw); -struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev, - const char *name, const char *parent_name, unsigned long flags, - unsigned int mult, unsigned int div); struct clk_hw *devm_clk_hw_register_fixed_factor_fwname(struct device *dev, struct device_node *np, const char *name, const char *fw_name, unsigned long flags, unsigned int mult, unsigned int div); @@ -1184,13 +1184,45 @@ struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev, const char *name, unsigned int index, unsigned long flags, unsigned int mult, unsigned int div); -struct clk_hw *devm_clk_hw_register_fixed_factor_parent_hw(struct device *dev, - const char *name, const struct clk_hw *parent_hw, - unsigned long flags, unsigned int mult, unsigned int div); +#define clk_hw_register_fixed_factor(dev, name, parent_name, \ + flags, mult, div) \ + __clk_hw_register_fixed_factor((dev), NULL, (name), (parent_name), \ + NULL, NULL, (flags), (mult), (div), \ + 0, 0, false) +#define clk_hw_register_fixed_factor_pdata(dev, np, name, pdata, \ + flags, mult, div, acc, fixflags) \ + __clk_hw_register_fixed_factor((dev), (np), (name), NULL, NULL, \ + (pdata), (flags), (mult), (div), \ + (acc), (fixflags), false) +#define devm_clk_hw_register_fixed_factor(dev, name, parent_name, flags, \ + mult, div) \ + __clk_hw_register_fixed_factor((dev), NULL, (name), (parent_name), \ + NULL, NULL, (flags), (mult), (div), 0, \ + 0, true) +/** + * devm_clk_hw_register_fixed_factor_parent_hw - Register a fixed factor clock with + * pointer to parent clock + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_hw: pointer to parent clk + * @flags: fixed factor flags + * @mult: multiplier + * @div: divider + * + * Return: Pointer to fixed factor clk_hw structure that was registered or + * an error pointer. + */ +#define devm_clk_hw_register_fixed_factor_parent_hw(dev, name, parent_hw, \ + flags, mult, div) \ + __clk_hw_register_fixed_factor((dev), NULL, (name), NULL, \ + (parent_hw), NULL, (flags), (mult), \ + (div), 0, 0, true) -struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev, - const char *name, const struct clk_hw *parent_hw, - unsigned long flags, unsigned int mult, unsigned int div); +#define clk_hw_register_fixed_factor_parent_hw(dev, name, parent_hw, flags, \ + mult, div) \ + __clk_hw_register_fixed_factor((dev), NULL, (name), NULL, \ + (parent_hw), NULL, (flags), (mult), \ + (div), 0, 0, false) /** * struct clk_fractional_divider - adjustable fractional divider clock *