Merge branches 'clk-spreadtrum', 'clk-mvebu-dvfs', 'clk-qoriq', 'clk-imx' and 'clk-qcom-ipq8074' into clk-next

* clk-spreadtrum:
  clk: sprd: add clocks support for SC9860
  clk: sprd: Add dt-bindings include file for SC9860
  dt-bindings: Add Spreadtrum clock binding documentation
  clk: sprd: add adjustable pll support
  clk: sprd: add composite clock support
  clk: sprd: add divider clock support
  clk: sprd: add mux clock support
  clk: sprd: add gate clock support
  clk: sprd: Add common infrastructure
  clk: move clock common macros out from vendor directories

* clk-mvebu-dvfs:
  clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks
  clk: mvebu: armada-37xx-periph: prepare cpu clk to be used with DVFS
  clk: mvebu: armada-37xx-periph: cosmetic changes

* clk-qoriq:
  clk: qoriq: add more divider clocks support

* clk-imx:
  clk: imx51: uart4, uart5 gates only exist on imx50, imx53

* clk-qcom-ipq8074:
  clk: qcom: ipq8074: add misc resets for PCIE and NSS
  dt-bindings: clock: qcom: add misc resets for PCIE and NSS
  clk: qcom: ipq8074: add GP and Crypto clocks
  clk: qcom: ipq8074: add NSS ethernet port clocks
  clk: qcom: ipq8074: add NSS clocks
  clk: qcom: ipq8074: add PCIE, USB and SDCC clocks
  clk: qcom: ipq8074: add remaining PLL’s
  dt-bindings: clock: qcom: add remaining clocks for IPQ8074
  clk: qcom: ipq8074: fix missing GPLL0 divider width
  clk: qcom: add parent map for regmap mux
  clk: qcom: add read-only divider operations
This commit is contained in:
Stephen Boyd 2018-01-26 16:41:47 -08:00
34 changed files with 7941 additions and 81 deletions

View File

@ -78,6 +78,7 @@ second cell is the clock index for the specified type.
2 hwaccel index (n in CLKCGnHWACSR)
3 fman 0 for fm1, 1 for fm2
4 platform pll 0=pll, 1=pll/2, 2=pll/3, 3=pll/4
4=pll/5, 5=pll/6, 6=pll/7, 7=pll/8
5 coreclk must be 0
3. Example

View File

@ -0,0 +1,63 @@
Spreadtrum Clock Binding
------------------------
Required properties:
- compatible: should contain the following compatible strings:
- "sprd,sc9860-pmu-gate"
- "sprd,sc9860-pll"
- "sprd,sc9860-ap-clk"
- "sprd,sc9860-aon-prediv"
- "sprd,sc9860-apahb-gate"
- "sprd,sc9860-aon-gate"
- "sprd,sc9860-aonsecure-clk"
- "sprd,sc9860-agcp-gate"
- "sprd,sc9860-gpu-clk"
- "sprd,sc9860-vsp-clk"
- "sprd,sc9860-vsp-gate"
- "sprd,sc9860-cam-clk"
- "sprd,sc9860-cam-gate"
- "sprd,sc9860-disp-clk"
- "sprd,sc9860-disp-gate"
- "sprd,sc9860-apapb-gate"
- #clock-cells: must be 1
- clocks : Should be the input parent clock(s) phandle for the clock, this
property here just simply shows which clock group the clocks'
parents are in, since each clk node would represent many clocks
which are defined in the driver. The detailed dependency
relationship (i.e. how many parents and which are the parents)
are implemented in driver code.
Optional properties:
- reg: Contain the registers base address and length. It must be configured
only if no 'sprd,syscon' under the node.
- sprd,syscon: phandle to the syscon which is in the same address area with
the clock, and so we can get regmap for the clocks from the
syscon device.
Example:
pmu_gate: pmu-gate {
compatible = "sprd,sc9860-pmu-gate";
sprd,syscon = <&pmu_regs>;
clocks = <&ext_26m>;
#clock-cells = <1>;
};
pll: pll {
compatible = "sprd,sc9860-pll";
sprd,syscon = <&ana_regs>;
clocks = <&pmu_gate 0>;
#clock-cells = <1>;
};
ap_clk: clock-controller@20000000 {
compatible = "sprd,sc9860-ap-clk";
reg = <0 0x20000000 0 0x400>;
clocks = <&ext_26m>, <&pll 0>,
<&pmu_gate 0>;
#clock-cells = <1>;
};

View File

@ -236,6 +236,7 @@ source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/samsung/Kconfig"
source "drivers/clk/sprd/Kconfig"
source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"

View File

@ -85,6 +85,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_ARCH_SIRF) += sirf/
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_SPRD) += sprd/
obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/

View File

@ -41,7 +41,7 @@ struct clockgen_pll_div {
};
struct clockgen_pll {
struct clockgen_pll_div div[4];
struct clockgen_pll_div div[8];
};
#define CLKSEL_VALID 1
@ -1127,6 +1127,13 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
struct clk *clk;
int ret;
/*
* For platform PLL, there are 8 divider clocks.
* For core PLL, there are 4 divider clocks at most.
*/
if (idx != PLATFORM_PLL && i >= 4)
break;
snprintf(pll->div[i].name, sizeof(pll->div[i].name),
"cg-pll%d-div%d", idx, i + 1);

View File

@ -257,10 +257,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
clk[IMX5_CLK_VPU_SEL] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
clk[IMX5_CLK_VPU_GATE] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
clk[IMX5_CLK_VPU_REFERENCE_GATE] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
clk[IMX5_CLK_UART4_IPG_GATE] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
clk[IMX5_CLK_UART4_PER_GATE] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
clk[IMX5_CLK_UART5_IPG_GATE] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
clk[IMX5_CLK_UART5_PER_GATE] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
clk[IMX5_CLK_GPC_DVFS] = imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
clk[IMX5_CLK_SSI_APM] = imx_clk_mux("ssi_apm", MXC_CCM_CSCMR1, 8, 2, ssi_apm_sels, ARRAY_SIZE(ssi_apm_sels));
@ -361,6 +357,10 @@ static void __init mx50_clocks_init(struct device_node *np)
clk[IMX5_CLK_USB_PHY1_GATE] = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
clk[IMX5_CLK_USB_PHY2_GATE] = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
clk[IMX5_CLK_I2C3_GATE] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
clk[IMX5_CLK_UART4_IPG_GATE] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
clk[IMX5_CLK_UART4_PER_GATE] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
clk[IMX5_CLK_UART5_IPG_GATE] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
clk[IMX5_CLK_UART5_PER_GATE] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
clk[IMX5_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
@ -562,6 +562,10 @@ static void __init mx53_clocks_init(struct device_node *np)
clk[IMX5_CLK_IEEE1588_PRED] = imx_clk_divider("ieee1588_pred", "ieee1588_sel", MXC_CCM_CSCDR2, 6, 3);
clk[IMX5_CLK_IEEE1588_PODF] = imx_clk_divider("ieee1588_podf", "ieee1588_pred", MXC_CCM_CSCDR2, 0, 6);
clk[IMX5_CLK_IEEE1588_GATE] = imx_clk_gate2("ieee1588_serial_gate", "ieee1588_podf", MXC_CCM_CCGR7, 6);
clk[IMX5_CLK_UART4_IPG_GATE] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
clk[IMX5_CLK_UART4_PER_GATE] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
clk[IMX5_CLK_UART5_IPG_GATE] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
clk[IMX5_CLK_UART5_PER_GATE] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
clk[IMX5_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));

View File

@ -21,9 +21,11 @@
*/
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#define TBG_SEL 0x0
@ -33,6 +35,26 @@
#define CLK_SEL 0x10
#define CLK_DIS 0x14
#define LOAD_LEVEL_NR 4
#define ARMADA_37XX_NB_L0L1 0x18
#define ARMADA_37XX_NB_L2L3 0x1C
#define ARMADA_37XX_NB_TBG_DIV_OFF 13
#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
#define ARMADA_37XX_NB_CLK_SEL_OFF 11
#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
#define ARMADA_37XX_NB_TBG_SEL_OFF 9
#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
#define ARMADA_37XX_NB_CONFIG_SHIFT 16
#define ARMADA_37XX_NB_DYN_MOD 0x24
#define ARMADA_37XX_NB_DFS_EN 31
#define ARMADA_37XX_NB_CPU_LOAD 0x30
#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
#define ARMADA_37XX_DVFS_LOAD_0 0
#define ARMADA_37XX_DVFS_LOAD_1 1
#define ARMADA_37XX_DVFS_LOAD_2 2
#define ARMADA_37XX_DVFS_LOAD_3 3
struct clk_periph_driver_data {
struct clk_hw_onecell_data *hw_data;
spinlock_t lock;
@ -46,7 +68,18 @@ struct clk_double_div {
u8 shift2;
};
struct clk_pm_cpu {
struct clk_hw hw;
void __iomem *reg_mux;
u8 shift_mux;
u32 mask_mux;
void __iomem *reg_div;
u8 shift_div;
struct regmap *nb_pm_base;
};
#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw)
struct clk_periph_data {
const char *name;
@ -55,6 +88,7 @@ struct clk_periph_data {
struct clk_hw *mux_hw;
struct clk_hw *rate_hw;
struct clk_hw *gate_hw;
struct clk_hw *muxrate_hw;
bool is_double_div;
};
@ -79,7 +113,9 @@ static const struct clk_div_table clk_table2[] = {
{ .val = 1, .div = 4, },
{ .val = 0, .div = 0, }, /* last entry */
};
static const struct clk_ops clk_double_div_ops;
static const struct clk_ops clk_pm_cpu_ops;
#define PERIPH_GATE(_name, _bit) \
struct clk_gate gate_##_name = { \
@ -121,6 +157,18 @@ struct clk_divider rate_##_name = { \
} \
};
#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2) \
struct clk_pm_cpu muxrate_##_name = { \
.reg_mux = (void *)TBG_SEL, \
.mask_mux = 3, \
.shift_mux = _shift1, \
.reg_div = (void *)_reg, \
.shift_div = _shift2, \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_pm_cpu_ops, \
} \
};
#define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\
static PERIPH_GATE(_name, _bit); \
static PERIPH_MUX(_name, _shift); \
@ -135,10 +183,6 @@ static PERIPH_DIV(_name, _reg, _shift1, _table);
static PERIPH_GATE(_name, _bit); \
static PERIPH_DIV(_name, _reg, _shift, _table);
#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \
static PERIPH_MUX(_name, _shift); \
static PERIPH_DIV(_name, _reg, _shift_div, _table);
#define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\
static PERIPH_MUX(_name, _shift); \
static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
@ -179,13 +223,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
.rate_hw = &rate_##_name.hw, \
}
#define REF_CLK_MUX_DIV(_name) \
#define REF_CLK_PM_CPU(_name) \
{ .name = #_name, \
.parent_names = (const char *[]){ "TBG-A-P", \
"TBG-B-P", "TBG-A-S", "TBG-B-S"}, \
.num_parents = 4, \
.mux_hw = &mux_##_name.hw, \
.rate_hw = &rate_##_name.hw, \
.muxrate_hw = &muxrate_##_name.hw, \
}
#define REF_CLK_MUX_DD(_name) \
@ -215,9 +258,9 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV_SEL0, DIV_SEL0, 15, 12);
PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6);
PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6);
PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28);
static struct clk_periph_data data_nb[] ={
static struct clk_periph_data data_nb[] = {
REF_CLK_FULL_DD(mmc),
REF_CLK_FULL_DD(sata_host),
REF_CLK_FULL_DD(sec_at),
@ -234,7 +277,7 @@ static struct clk_periph_data data_nb[] ={
REF_CLK_FULL(trace),
REF_CLK_FULL(counter),
REF_CLK_FULL_DD(eip97),
REF_CLK_MUX_DIV(cpu),
REF_CLK_PM_CPU(cpu),
{ },
};
@ -281,7 +324,7 @@ static unsigned int get_div(void __iomem *reg, int shift)
}
static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
unsigned long parent_rate)
{
struct clk_double_div *double_div = to_clk_double_div(hw);
unsigned int div;
@ -296,6 +339,222 @@ static const struct clk_ops clk_double_div_ops = {
.recalc_rate = clk_double_div_recalc_rate,
};
static void armada_3700_pm_dvfs_update_regs(unsigned int load_level,
unsigned int *reg,
unsigned int *offset)
{
if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
*reg = ARMADA_37XX_NB_L0L1;
else
*reg = ARMADA_37XX_NB_L2L3;
if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
load_level == ARMADA_37XX_DVFS_LOAD_2)
*offset += ARMADA_37XX_NB_CONFIG_SHIFT;
}
static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base)
{
unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD;
if (IS_ERR(base))
return false;
regmap_read(base, reg, &val);
return !!(val & BIT(ARMADA_37XX_NB_DFS_EN));
}
static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base)
{
unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF;
unsigned int load_level, div;
/*
* This function is always called after the function
* armada_3700_pm_dvfs_is_enabled, so no need to check again
* if the base is valid.
*/
regmap_read(base, reg, &load_level);
/*
* The register and the offset inside this register accessed to
* read the current divider depend on the load level
*/
load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
regmap_read(base, reg, &div);
return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK;
}
static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base)
{
unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF;
unsigned int load_level, sel;
/*
* This function is always called after the function
* armada_3700_pm_dvfs_is_enabled, so no need to check again
* if the base is valid
*/
regmap_read(base, reg, &load_level);
/*
* The register and the offset inside this register accessed to
* read the current divider depend on the load level
*/
load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
regmap_read(base, reg, &sel);
return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK;
}
static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
int num_parents = clk_hw_get_num_parents(hw);
u32 val;
if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) {
val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base);
} else {
val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
val &= pm_cpu->mask_mux;
}
if (val >= num_parents)
return -EINVAL;
return val;
}
static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
struct regmap *base = pm_cpu->nb_pm_base;
int load_level;
/*
* We set the clock parent only if the DVFS is available but
* not enabled.
*/
if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base))
return -EINVAL;
/* Set the parent clock for all the load level */
for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
unsigned int reg, mask, val,
offset = ARMADA_37XX_NB_TBG_SEL_OFF;
armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
val = index << offset;
mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset;
regmap_update_bits(base, reg, mask, val);
}
return 0;
}
static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
unsigned int div;
if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base))
div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base);
else
div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
return DIV_ROUND_UP_ULL((u64)parent_rate, div);
}
static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
struct regmap *base = pm_cpu->nb_pm_base;
unsigned int div = *parent_rate / rate;
unsigned int load_level;
/* only available when DVFS is enabled */
if (!armada_3700_pm_dvfs_is_enabled(base))
return -EINVAL;
for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF;
armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
regmap_read(base, reg, &val);
val >>= offset;
val &= ARMADA_37XX_NB_TBG_DIV_MASK;
if (val == div)
/*
* We found a load level matching the target
* divider, switch to this load level and
* return.
*/
return *parent_rate / div;
}
/* We didn't find any valid divider */
return -EINVAL;
}
static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
struct regmap *base = pm_cpu->nb_pm_base;
unsigned int div = parent_rate / rate;
unsigned int load_level;
/* only available when DVFS is enabled */
if (!armada_3700_pm_dvfs_is_enabled(base))
return -EINVAL;
for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
unsigned int reg, mask, val,
offset = ARMADA_37XX_NB_TBG_DIV_OFF;
armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
regmap_read(base, reg, &val);
val >>= offset;
val &= ARMADA_37XX_NB_TBG_DIV_MASK;
if (val == div) {
/*
* We found a load level matching the target
* divider, switch to this load level and
* return.
*/
reg = ARMADA_37XX_NB_CPU_LOAD;
mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
regmap_update_bits(base, reg, mask, load_level);
return rate;
}
}
/* We didn't find any valid divider */
return -EINVAL;
}
static const struct clk_ops clk_pm_cpu_ops = {
.get_parent = clk_pm_cpu_get_parent,
.set_parent = clk_pm_cpu_set_parent,
.round_rate = clk_pm_cpu_round_rate,
.set_rate = clk_pm_cpu_set_rate,
.recalc_rate = clk_pm_cpu_recalc_rate,
};
static const struct of_device_id armada_3700_periph_clock_of_match[] = {
{ .compatible = "marvell,armada-3700-periph-clock-nb",
.data = data_nb, },
@ -303,6 +562,7 @@ static const struct of_device_id armada_3700_periph_clock_of_match[] = {
.data = data_sb, },
{ }
};
static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
void __iomem *reg, spinlock_t *lock,
struct device *dev, struct clk_hw **hw)
@ -354,10 +614,29 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
}
}
if (data->muxrate_hw) {
struct clk_pm_cpu *pmcpu_clk;
struct clk_hw *muxrate_hw = data->muxrate_hw;
struct regmap *map;
pmcpu_clk = to_clk_pm_cpu(muxrate_hw);
pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div;
mux_hw = muxrate_hw;
rate_hw = muxrate_hw;
mux_ops = muxrate_hw->init->ops;
rate_ops = muxrate_hw->init->ops;
map = syscon_regmap_lookup_by_compatible(
"marvell,armada-3700-nb-pm");
pmcpu_clk->nb_pm_base = map;
}
*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
data->num_parents, mux_hw,
mux_ops, rate_hw, rate_ops,
gate_hw, gate_ops, CLK_IGNORE_UNUSED);
data->num_parents, mux_hw,
mux_ops, rate_hw, rate_ops,
gate_hw, gate_ops, CLK_IGNORE_UNUSED);
if (IS_ERR(*hw))
return PTR_ERR(*hw);
@ -406,12 +685,11 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
if (armada_3700_add_composite_clk(&data[i], reg,
&driver_data->lock, dev, hw))
dev_err(dev, "Can't register periph clock %s\n",
data[i].name);
data[i].name);
}
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
driver_data->hw_data);
driver_data->hw_data);
if (ret) {
for (i = 0; i < num_periph; i++)
clk_hw_unregister(driver_data->hw_data->hws[i]);

View File

@ -25,16 +25,6 @@ struct freq_tbl {
u16 n;
};
/**
* struct parent_map - map table for PLL source select configuration values
* @src: source PLL
* @cfg: configuration value
*/
struct parent_map {
u8 src;
u8 cfg;
};
/**
* struct mn - M/N:D counter
* @mnctr_en_bit: bit to enable mn counter

View File

@ -23,6 +23,29 @@ static inline struct clk_regmap_div *to_clk_regmap_div(struct clk_hw *hw)
return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr);
}
static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_regmap_div *divider = to_clk_regmap_div(hw);
struct clk_regmap *clkr = &divider->clkr;
u32 div;
struct clk_hw *hw_parent = clk_hw_get_parent(hw);
regmap_read(clkr->regmap, divider->reg, &div);
div >>= divider->shift;
div &= BIT(divider->width) - 1;
div += 1;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
if (!hw_parent)
return -EINVAL;
*prate = clk_hw_round_rate(hw_parent, rate * div);
}
return DIV_ROUND_UP_ULL((u64)*prate, div);
}
static long div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
@ -68,3 +91,9 @@ const struct clk_ops clk_regmap_div_ops = {
.recalc_rate = div_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_div_ops);
const struct clk_ops clk_regmap_div_ro_ops = {
.round_rate = div_round_ro_rate,
.recalc_rate = div_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_div_ro_ops);

View File

@ -25,5 +25,6 @@ struct clk_regmap_div {
};
extern const struct clk_ops clk_regmap_div_ops;
extern const struct clk_ops clk_regmap_div_ro_ops;
#endif

View File

@ -35,6 +35,9 @@ static u8 mux_get_parent(struct clk_hw *hw)
val >>= mux->shift;
val &= mask;
if (mux->parent_map)
return qcom_find_src_index(hw, mux->parent_map, val);
return val;
}
@ -45,6 +48,9 @@ static int mux_set_parent(struct clk_hw *hw, u8 index)
unsigned int mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
unsigned int val;
if (mux->parent_map)
index = mux->parent_map[index].cfg;
val = index;
val <<= mux->shift;

View File

@ -16,11 +16,13 @@
#include <linux/clk-provider.h>
#include "clk-regmap.h"
#include "common.h"
struct clk_regmap_mux {
u32 reg;
u32 shift;
u32 width;
const struct parent_map *parent_map;
struct clk_regmap clkr;
};

View File

@ -20,7 +20,6 @@ struct qcom_reset_map;
struct regmap;
struct freq_tbl;
struct clk_hw;
struct parent_map;
#define PLL_LOCK_COUNT_SHIFT 8
#define PLL_LOCK_COUNT_MASK 0x3f
@ -39,6 +38,16 @@ struct qcom_cc_desc {
size_t num_gdscs;
};
/**
* struct parent_map - map table for source select configuration values
* @src: source
* @cfg: configuration value
*/
struct parent_map {
u8 src;
u8 cfg;
};
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
unsigned long rate);
extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,

File diff suppressed because it is too large Load Diff

14
drivers/clk/sprd/Kconfig Normal file
View File

@ -0,0 +1,14 @@
config SPRD_COMMON_CLK
tristate "Clock support for Spreadtrum SoCs"
depends on ARCH_SPRD || COMPILE_TEST
default ARCH_SPRD
if SPRD_COMMON_CLK
# SoC Drivers
config SPRD_SC9860_CLK
tristate "Support for the Spreadtrum SC9860 clocks"
depends on (ARM64 && ARCH_SPRD) || COMPILE_TEST
default ARM64 && ARCH_SPRD
endif

11
drivers/clk/sprd/Makefile Normal file
View File

@ -0,0 +1,11 @@
obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
clk-sprd-y += common.o
clk-sprd-y += gate.o
clk-sprd-y += mux.o
clk-sprd-y += div.o
clk-sprd-y += composite.o
clk-sprd-y += pll.o
## SoC support
obj-$(CONFIG_SPRD_SC9860_CLK) += sc9860-clk.o

96
drivers/clk/sprd/common.c Normal file
View File

@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum clock infrastructure
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
#include "common.h"
static const struct regmap_config sprdclk_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0xffff,
.fast_io = true,
};
static void sprd_clk_set_regmap(const struct sprd_clk_desc *desc,
struct regmap *regmap)
{
int i;
struct sprd_clk_common *cclk;
for (i = 0; i < desc->num_clk_clks; i++) {
cclk = desc->clk_clks[i];
if (!cclk)
continue;
cclk->regmap = regmap;
}
}
int sprd_clk_regmap_init(struct platform_device *pdev,
const struct sprd_clk_desc *desc)
{
void __iomem *base;
struct device_node *node = pdev->dev.of_node;
struct regmap *regmap;
if (of_find_property(node, "sprd,syscon", NULL)) {
regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
if (IS_ERR_OR_NULL(regmap)) {
pr_err("%s: failed to get syscon regmap\n", __func__);
return PTR_ERR(regmap);
}
} else {
base = of_iomap(node, 0);
regmap = devm_regmap_init_mmio(&pdev->dev, base,
&sprdclk_regmap_config);
if (IS_ERR_OR_NULL(regmap)) {
pr_err("failed to init regmap\n");
return PTR_ERR(regmap);
}
}
sprd_clk_set_regmap(desc, regmap);
return 0;
}
EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
{
int i, ret;
struct clk_hw *hw;
for (i = 0; i < clkhw->num; i++) {
hw = clkhw->hws[i];
if (!hw)
continue;
ret = devm_clk_hw_register(dev, hw);
if (ret) {
dev_err(dev, "Couldn't register clock %d - %s\n",
i, hw->init->name);
return ret;
}
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);
if (ret)
dev_err(dev, "Failed to add clock provider\n");
return ret;
}
EXPORT_SYMBOL_GPL(sprd_clk_probe);
MODULE_LICENSE("GPL v2");

38
drivers/clk/sprd/common.h Normal file
View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum clock infrastructure
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#ifndef _SPRD_CLK_COMMON_H_
#define _SPRD_CLK_COMMON_H_
#include <linux/clk-provider.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
struct device_node;
struct sprd_clk_common {
struct regmap *regmap;
u32 reg;
struct clk_hw hw;
};
struct sprd_clk_desc {
struct sprd_clk_common **clk_clks;
unsigned long num_clk_clks;
struct clk_hw_onecell_data *hw_clks;
};
static inline struct sprd_clk_common *
hw_to_sprd_clk_common(const struct clk_hw *hw)
{
return container_of(hw, struct sprd_clk_common, hw);
}
int sprd_clk_regmap_init(struct platform_device *pdev,
const struct sprd_clk_desc *desc);
int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw);
#endif /* _SPRD_CLK_COMMON_H_ */

View File

@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum composite clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#include <linux/clk-provider.h>
#include "composite.h"
static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct sprd_comp *cc = hw_to_sprd_comp(hw);
return sprd_div_helper_round_rate(&cc->common, &cc->div,
rate, parent_rate);
}
static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct sprd_comp *cc = hw_to_sprd_comp(hw);
return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate);
}
static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct sprd_comp *cc = hw_to_sprd_comp(hw);
return sprd_div_helper_set_rate(&cc->common, &cc->div,
rate, parent_rate);
}
static u8 sprd_comp_get_parent(struct clk_hw *hw)
{
struct sprd_comp *cc = hw_to_sprd_comp(hw);
return sprd_mux_helper_get_parent(&cc->common, &cc->mux);
}
static int sprd_comp_set_parent(struct clk_hw *hw, u8 index)
{
struct sprd_comp *cc = hw_to_sprd_comp(hw);
return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index);
}
const struct clk_ops sprd_comp_ops = {
.get_parent = sprd_comp_get_parent,
.set_parent = sprd_comp_set_parent,
.round_rate = sprd_comp_round_rate,
.recalc_rate = sprd_comp_recalc_rate,
.set_rate = sprd_comp_set_rate,
};
EXPORT_SYMBOL_GPL(sprd_comp_ops);

View File

@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum composite clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#ifndef _SPRD_COMPOSITE_H_
#define _SPRD_COMPOSITE_H_
#include "common.h"
#include "mux.h"
#include "div.h"
struct sprd_comp {
struct sprd_mux_ssel mux;
struct sprd_div_internal div;
struct sprd_clk_common common;
};
#define SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, _table, \
_mshift, _mwidth, _dshift, _dwidth, _flags) \
struct sprd_comp _struct = { \
.mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \
.div = _SPRD_DIV_CLK(_dshift, _dwidth), \
.common = { \
.regmap = NULL, \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS(_name, \
_parent, \
&sprd_comp_ops, \
_flags), \
} \
}
#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _mshift, \
_mwidth, _dshift, _dwidth, _flags) \
SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, \
NULL, _mshift, _mwidth, \
_dshift, _dwidth, _flags)
static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw)
{
struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
return container_of(common, struct sprd_comp, common);
}
extern const struct clk_ops sprd_comp_ops;
#endif /* _SPRD_COMPOSITE_H_ */

90
drivers/clk/sprd/div.c Normal file
View File

@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum divider clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#include <linux/clk-provider.h>
#include "div.h"
long sprd_div_helper_round_rate(struct sprd_clk_common *common,
const struct sprd_div_internal *div,
unsigned long rate,
unsigned long *parent_rate)
{
return divider_round_rate(&common->hw, rate, parent_rate,
NULL, div->width, 0);
}
EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct sprd_div *cd = hw_to_sprd_div(hw);
return sprd_div_helper_round_rate(&cd->common, &cd->div,
rate, parent_rate);
}
unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
const struct sprd_div_internal *div,
unsigned long parent_rate)
{
unsigned long val;
unsigned int reg;
regmap_read(common->regmap, common->reg, &reg);
val = reg >> div->shift;
val &= (1 << div->width) - 1;
return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0);
}
EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct sprd_div *cd = hw_to_sprd_div(hw);
return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
}
int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
const struct sprd_div_internal *div,
unsigned long rate,
unsigned long parent_rate)
{
unsigned long val;
unsigned int reg;
val = divider_get_val(rate, parent_rate, NULL,
div->width, 0);
regmap_read(common->regmap, common->reg, &reg);
reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
regmap_write(common->regmap, common->reg,
reg | (val << div->shift));
return 0;
}
EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct sprd_div *cd = hw_to_sprd_div(hw);
return sprd_div_helper_set_rate(&cd->common, &cd->div,
rate, parent_rate);
}
const struct clk_ops sprd_div_ops = {
.recalc_rate = sprd_div_recalc_rate,
.round_rate = sprd_div_round_rate,
.set_rate = sprd_div_set_rate,
};
EXPORT_SYMBOL_GPL(sprd_div_ops);

75
drivers/clk/sprd/div.h Normal file
View File

@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum divider clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#ifndef _SPRD_DIV_H_
#define _SPRD_DIV_H_
#include "common.h"
/**
* struct sprd_div_internal - Internal divider description
* @shift: Bit offset of the divider in its register
* @width: Width of the divider field in its register
*
* That structure represents a single divider, and is meant to be
* embedded in other structures representing the various clock
* classes.
*/
struct sprd_div_internal {
u8 shift;
u8 width;
};
#define _SPRD_DIV_CLK(_shift, _width) \
{ \
.shift = _shift, \
.width = _width, \
}
struct sprd_div {
struct sprd_div_internal div;
struct sprd_clk_common common;
};
#define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \
_shift, _width, _flags) \
struct sprd_div _struct = { \
.div = _SPRD_DIV_CLK(_shift, _width), \
.common = { \
.regmap = NULL, \
.reg = _reg, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&sprd_div_ops, \
_flags), \
} \
}
static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw)
{
struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
return container_of(common, struct sprd_div, common);
}
long sprd_div_helper_round_rate(struct sprd_clk_common *common,
const struct sprd_div_internal *div,
unsigned long rate,
unsigned long *parent_rate);
unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
const struct sprd_div_internal *div,
unsigned long parent_rate);
int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
const struct sprd_div_internal *div,
unsigned long rate,
unsigned long parent_rate);
extern const struct clk_ops sprd_div_ops;
#endif /* _SPRD_DIV_H_ */

111
drivers/clk/sprd/gate.c Normal file
View File

@ -0,0 +1,111 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum gate clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include "gate.h"
static void clk_gate_toggle(const struct sprd_gate *sg, bool en)
{
const struct sprd_clk_common *common = &sg->common;
unsigned int reg;
bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false;
set ^= en;
regmap_read(common->regmap, common->reg, &reg);
if (set)
reg |= sg->enable_mask;
else
reg &= ~sg->enable_mask;
regmap_write(common->regmap, common->reg, reg);
}
static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en)
{
const struct sprd_clk_common *common = &sg->common;
bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
unsigned int offset;
set ^= en;
/*
* Each set/clear gate clock has three registers:
* common->reg - base register
* common->reg + offset - set register
* common->reg + 2 * offset - clear register
*/
offset = set ? sg->sc_offset : sg->sc_offset * 2;
regmap_write(common->regmap, common->reg + offset,
sg->enable_mask);
}
static void sprd_gate_disable(struct clk_hw *hw)
{
struct sprd_gate *sg = hw_to_sprd_gate(hw);
clk_gate_toggle(sg, false);
}
static int sprd_gate_enable(struct clk_hw *hw)
{
struct sprd_gate *sg = hw_to_sprd_gate(hw);
clk_gate_toggle(sg, true);
return 0;
}
static void sprd_sc_gate_disable(struct clk_hw *hw)
{
struct sprd_gate *sg = hw_to_sprd_gate(hw);
clk_sc_gate_toggle(sg, false);
}
static int sprd_sc_gate_enable(struct clk_hw *hw)
{
struct sprd_gate *sg = hw_to_sprd_gate(hw);
clk_sc_gate_toggle(sg, true);
return 0;
}
static int sprd_gate_is_enabled(struct clk_hw *hw)
{
struct sprd_gate *sg = hw_to_sprd_gate(hw);
struct sprd_clk_common *common = &sg->common;
unsigned int reg;
regmap_read(common->regmap, common->reg, &reg);
if (sg->flags & CLK_GATE_SET_TO_DISABLE)
reg ^= sg->enable_mask;
reg &= sg->enable_mask;
return reg ? 1 : 0;
}
const struct clk_ops sprd_gate_ops = {
.disable = sprd_gate_disable,
.enable = sprd_gate_enable,
.is_enabled = sprd_gate_is_enabled,
};
EXPORT_SYMBOL_GPL(sprd_gate_ops);
const struct clk_ops sprd_sc_gate_ops = {
.disable = sprd_sc_gate_disable,
.enable = sprd_sc_gate_enable,
.is_enabled = sprd_gate_is_enabled,
};
EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);

59
drivers/clk/sprd/gate.h Normal file
View File

@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum gate clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#ifndef _SPRD_GATE_H_
#define _SPRD_GATE_H_
#include "common.h"
struct sprd_gate {
u32 enable_mask;
u16 flags;
u16 sc_offset;
struct sprd_clk_common common;
};
#define SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
_enable_mask, _flags, _gate_flags, _ops) \
struct sprd_gate _struct = { \
.enable_mask = _enable_mask, \
.sc_offset = _sc_offset, \
.flags = _gate_flags, \
.common = { \
.regmap = NULL, \
.reg = _reg, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
_ops, \
_flags), \
} \
}
#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, \
_enable_mask, _flags, _gate_flags) \
SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, 0, \
_enable_mask, _flags, _gate_flags, \
&sprd_gate_ops)
#define SPRD_SC_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \
_enable_mask, _flags, _gate_flags) \
SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
_enable_mask, _flags, _gate_flags, \
&sprd_sc_gate_ops)
static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw)
{
struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
return container_of(common, struct sprd_gate, common);
}
extern const struct clk_ops sprd_gate_ops;
extern const struct clk_ops sprd_sc_gate_ops;
#endif /* _SPRD_GATE_H_ */

76
drivers/clk/sprd/mux.c Normal file
View File

@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum multiplexer clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include "mux.h"
u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
const struct sprd_mux_ssel *mux)
{
unsigned int reg;
u8 parent;
int num_parents;
int i;
regmap_read(common->regmap, common->reg, &reg);
parent = reg >> mux->shift;
parent &= (1 << mux->width) - 1;
if (!mux->table)
return parent;
num_parents = clk_hw_get_num_parents(&common->hw);
for (i = 0; i < num_parents - 1; i++)
if (parent >= mux->table[i] && parent < mux->table[i + 1])
return i;
return num_parents - 1;
}
EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent);
static u8 sprd_mux_get_parent(struct clk_hw *hw)
{
struct sprd_mux *cm = hw_to_sprd_mux(hw);
return sprd_mux_helper_get_parent(&cm->common, &cm->mux);
}
int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
const struct sprd_mux_ssel *mux,
u8 index)
{
unsigned int reg;
if (mux->table)
index = mux->table[index];
regmap_read(common->regmap, common->reg, &reg);
reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift);
regmap_write(common->regmap, common->reg,
reg | (index << mux->shift));
return 0;
}
EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent);
static int sprd_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct sprd_mux *cm = hw_to_sprd_mux(hw);
return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index);
}
const struct clk_ops sprd_mux_ops = {
.get_parent = sprd_mux_get_parent,
.set_parent = sprd_mux_set_parent,
.determine_rate = __clk_mux_determine_rate,
};
EXPORT_SYMBOL_GPL(sprd_mux_ops);

74
drivers/clk/sprd/mux.h Normal file
View File

@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum multiplexer clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#ifndef _SPRD_MUX_H_
#define _SPRD_MUX_H_
#include "common.h"
/**
* struct sprd_mux_ssel - Mux clock's source select bits in its register
* @shift: Bit offset of the divider in its register
* @width: Width of the divider field in its register
* @table: For some mux clocks, not all sources are used on some special
* chips, this matches the value of mux clock's register and the
* sources which are used for this mux clock
*/
struct sprd_mux_ssel {
u8 shift;
u8 width;
const u8 *table;
};
struct sprd_mux {
struct sprd_mux_ssel mux;
struct sprd_clk_common common;
};
#define _SPRD_MUX_CLK(_shift, _width, _table) \
{ \
.shift = _shift, \
.width = _width, \
.table = _table, \
}
#define SPRD_MUX_CLK_TABLE(_struct, _name, _parents, _table, \
_reg, _shift, _width, \
_flags) \
struct sprd_mux _struct = { \
.mux = _SPRD_MUX_CLK(_shift, _width, _table), \
.common = { \
.regmap = NULL, \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS(_name, \
_parents, \
&sprd_mux_ops, \
_flags), \
} \
}
#define SPRD_MUX_CLK(_struct, _name, _parents, _reg, \
_shift, _width, _flags) \
SPRD_MUX_CLK_TABLE(_struct, _name, _parents, NULL, \
_reg, _shift, _width, _flags)
static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw)
{
struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
return container_of(common, struct sprd_mux, common);
}
extern const struct clk_ops sprd_mux_ops;
u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
const struct sprd_mux_ssel *mux);
int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
const struct sprd_mux_ssel *mux,
u8 index);
#endif /* _SPRD_MUX_H_ */

266
drivers/clk/sprd/pll.c Normal file
View File

@ -0,0 +1,266 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum pll clock driver
//
// Copyright (C) 2015~2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include "pll.h"
#define CLK_PLL_1M 1000000
#define CLK_PLL_10M (CLK_PLL_1M * 10)
#define pindex(pll, member) \
(pll->factors[member].shift / (8 * sizeof(pll->regs_num)))
#define pshift(pll, member) \
(pll->factors[member].shift % (8 * sizeof(pll->regs_num)))
#define pwidth(pll, member) \
pll->factors[member].width
#define pmask(pll, member) \
((pwidth(pll, member)) ? \
GENMASK(pwidth(pll, member) + pshift(pll, member) - 1, \
pshift(pll, member)) : 0)
#define pinternal(pll, cfg, member) \
(cfg[pindex(pll, member)] & pmask(pll, member))
#define pinternal_val(pll, cfg, member) \
(pinternal(pll, cfg, member) >> pshift(pll, member))
static inline unsigned int
sprd_pll_read(const struct sprd_pll *pll, u8 index)
{
const struct sprd_clk_common *common = &pll->common;
unsigned int val = 0;
if (WARN_ON(index >= pll->regs_num))
return 0;
regmap_read(common->regmap, common->reg + index * 4, &val);
return val;
}
static inline void
sprd_pll_write(const struct sprd_pll *pll, u8 index,
u32 msk, u32 val)
{
const struct sprd_clk_common *common = &pll->common;
unsigned int offset, reg;
int ret = 0;
if (WARN_ON(index >= pll->regs_num))
return;
offset = common->reg + index * 4;
ret = regmap_read(common->regmap, offset, &reg);
if (!ret)
regmap_write(common->regmap, offset, (reg & ~msk) | val);
}
static unsigned long pll_get_refin(const struct sprd_pll *pll)
{
u32 shift, mask, index, refin_id = 3;
const unsigned long refin[4] = { 2, 4, 13, 26 };
if (pwidth(pll, PLL_REFIN)) {
index = pindex(pll, PLL_REFIN);
shift = pshift(pll, PLL_REFIN);
mask = pmask(pll, PLL_REFIN);
refin_id = (sprd_pll_read(pll, index) & mask) >> shift;
if (refin_id > 3)
refin_id = 3;
}
return refin[refin_id];
}
static u32 pll_get_ibias(u64 rate, const u64 *table)
{
u32 i, num = table[0];
for (i = 1; i < num + 1; i++)
if (rate <= table[i])
break;
return (i == num + 1) ? num : i;
}
static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll,
unsigned long parent_rate)
{
u32 *cfg;
u32 i, mask, regs_num = pll->regs_num;
unsigned long rate, nint, kint = 0;
u64 refin;
u16 k1, k2;
cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
if (!cfg)
return -ENOMEM;
for (i = 0; i < regs_num; i++)
cfg[i] = sprd_pll_read(pll, i);
refin = pll_get_refin(pll);
if (pinternal(pll, cfg, PLL_PREDIV))
refin = refin * 2;
if (pwidth(pll, PLL_POSTDIV) &&
((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) ||
(!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV))))
refin = refin / 2;
if (!pinternal(pll, cfg, PLL_DIV_S)) {
rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M;
} else {
nint = pinternal_val(pll, cfg, PLL_NINT);
if (pinternal(pll, cfg, PLL_SDM_EN))
kint = pinternal_val(pll, cfg, PLL_KINT);
mask = pmask(pll, PLL_KINT);
k1 = pll->k1;
k2 = pll->k2;
rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1,
((mask >> __ffs(mask)) + 1)) *
k2 + refin * nint * CLK_PLL_1M;
}
return rate;
}
#define SPRD_PLL_WRITE_CHECK(pll, i, mask, val) \
(((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT))
static int _sprd_pll_set_rate(const struct sprd_pll *pll,
unsigned long rate,
unsigned long parent_rate)
{
struct reg_cfg *cfg;
int ret = 0;
u32 mask, shift, width, ibias_val, index;
u32 regs_num = pll->regs_num, i = 0;
unsigned long kint, nint;
u64 tmp, refin, fvco = rate;
cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
if (!cfg)
return -ENOMEM;
refin = pll_get_refin(pll);
mask = pmask(pll, PLL_PREDIV);
index = pindex(pll, PLL_PREDIV);
width = pwidth(pll, PLL_PREDIV);
if (width && (sprd_pll_read(pll, index) & mask))
refin = refin * 2;
mask = pmask(pll, PLL_POSTDIV);
index = pindex(pll, PLL_POSTDIV);
width = pwidth(pll, PLL_POSTDIV);
cfg[index].msk = mask;
if (width && ((pll->fflag == 1 && fvco <= pll->fvco) ||
(pll->fflag == 0 && fvco > pll->fvco)))
cfg[index].val |= mask;
if (width && fvco <= pll->fvco)
fvco = fvco * 2;
mask = pmask(pll, PLL_DIV_S);
index = pindex(pll, PLL_DIV_S);
cfg[index].val |= mask;
cfg[index].msk |= mask;
mask = pmask(pll, PLL_SDM_EN);
index = pindex(pll, PLL_SDM_EN);
cfg[index].val |= mask;
cfg[index].msk |= mask;
nint = do_div(fvco, refin * CLK_PLL_1M);
mask = pmask(pll, PLL_NINT);
index = pindex(pll, PLL_NINT);
shift = pshift(pll, PLL_NINT);
cfg[index].val |= (nint << shift) & mask;
cfg[index].msk |= mask;
mask = pmask(pll, PLL_KINT);
index = pindex(pll, PLL_KINT);
width = pwidth(pll, PLL_KINT);
shift = pshift(pll, PLL_KINT);
tmp = fvco - refin * nint * CLK_PLL_1M;
tmp = do_div(tmp, 10000) * ((mask >> shift) + 1);
kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100);
cfg[index].val |= (kint << shift) & mask;
cfg[index].msk |= mask;
ibias_val = pll_get_ibias(fvco, pll->itable);
mask = pmask(pll, PLL_IBIAS);
index = pindex(pll, PLL_IBIAS);
shift = pshift(pll, PLL_IBIAS);
cfg[index].val |= ibias_val << shift & mask;
cfg[index].msk |= mask;
for (i = 0; i < regs_num; i++) {
if (cfg[i].msk) {
sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val);
ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk,
cfg[i].val);
}
}
if (!ret)
udelay(pll->udelay);
return ret;
}
static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct sprd_pll *pll = hw_to_sprd_pll(hw);
return _sprd_pll_recalc_rate(pll, parent_rate);
}
static int sprd_pll_set_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate)
{
struct sprd_pll *pll = hw_to_sprd_pll(hw);
return _sprd_pll_set_rate(pll, rate, parent_rate);
}
static int sprd_pll_clk_prepare(struct clk_hw *hw)
{
struct sprd_pll *pll = hw_to_sprd_pll(hw);
udelay(pll->udelay);
return 0;
}
static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
const struct clk_ops sprd_pll_ops = {
.prepare = sprd_pll_clk_prepare,
.recalc_rate = sprd_pll_recalc_rate,
.round_rate = sprd_pll_round_rate,
.set_rate = sprd_pll_set_rate,
};
EXPORT_SYMBOL_GPL(sprd_pll_ops);

108
drivers/clk/sprd/pll.h Normal file
View File

@ -0,0 +1,108 @@
// SPDX-License-Identifier: GPL-2.0
//
// Spreadtrum pll clock driver
//
// Copyright (C) 2015~2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
#ifndef _SPRD_PLL_H_
#define _SPRD_PLL_H_
#include "common.h"
struct reg_cfg {
u32 val;
u32 msk;
};
struct clk_bit_field {
u8 shift;
u8 width;
};
enum {
PLL_LOCK_DONE,
PLL_DIV_S,
PLL_MOD_EN,
PLL_SDM_EN,
PLL_REFIN,
PLL_IBIAS,
PLL_N,
PLL_NINT,
PLL_KINT,
PLL_PREDIV,
PLL_POSTDIV,
PLL_FACT_MAX
};
/*
* struct sprd_pll - definition of adjustable pll clock
*
* @reg: registers used to set the configuration of pll clock,
* reg[0] shows how many registers this pll clock uses.
* @itable: pll ibias table, itable[0] means how many items this
* table includes
* @udelay delay time after setting rate
* @factors used to calculate the pll clock rate
* @fvco: fvco threshold rate
* @fflag: fvco flag
*/
struct sprd_pll {
u32 regs_num;
const u64 *itable;
const struct clk_bit_field *factors;
u16 udelay;
u16 k1;
u16 k2;
u16 fflag;
u64 fvco;
struct sprd_clk_common common;
};
#define SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \
_regs_num, _itable, _factors, \
_udelay, _k1, _k2, _fflag, _fvco) \
struct sprd_pll _struct = { \
.regs_num = _regs_num, \
.itable = _itable, \
.factors = _factors, \
.udelay = _udelay, \
.k1 = _k1, \
.k2 = _k2, \
.fflag = _fflag, \
.fvco = _fvco, \
.common = { \
.regmap = NULL, \
.reg = _reg, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&sprd_pll_ops, \
0), \
}, \
}
#define SPRD_PLL_WITH_ITABLE_K(_struct, _name, _parent, _reg, \
_regs_num, _itable, _factors, \
_udelay, _k1, _k2) \
SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \
_regs_num, _itable, _factors, \
_udelay, _k1, _k2, 0, 0)
#define SPRD_PLL_WITH_ITABLE_1K(_struct, _name, _parent, _reg, \
_regs_num, _itable, _factors, _udelay) \
SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg, \
_regs_num, _itable, _factors, \
_udelay, 1000, 1000, 0, 0)
static inline struct sprd_pll *hw_to_sprd_pll(struct clk_hw *hw)
{
struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
return container_of(common, struct sprd_pll, common);
}
extern const struct clk_ops sprd_pll_ops;
#endif /* _SPRD_PLL_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -31,35 +31,6 @@
struct device_node;
#define CLK_HW_INIT(_name, _parent, _ops, _flags) \
&(struct clk_init_data) { \
.flags = _flags, \
.name = _name, \
.parent_names = (const char *[]) { _parent }, \
.num_parents = 1, \
.ops = _ops, \
}
#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \
&(struct clk_init_data) { \
.flags = _flags, \
.name = _name, \
.parent_names = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
.ops = _ops, \
}
#define CLK_FIXED_FACTOR(_struct, _name, _parent, \
_div, _mult, _flags) \
struct clk_fixed_factor _struct = { \
.div = _div, \
.mult = _mult, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&clk_fixed_factor_ops, \
_flags), \
}
struct ccu_common {
void __iomem *base;
u16 reg;

View File

@ -14,24 +14,6 @@
#define PNAME(x) static const char *x[]
#define CLK_HW_INIT(_name, _parent, _ops, _flags) \
&(struct clk_init_data) { \
.flags = _flags, \
.name = _name, \
.parent_names = (const char *[]) { _parent }, \
.num_parents = 1, \
.ops = _ops, \
}
#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \
&(struct clk_init_data) { \
.flags = _flags, \
.name = _name, \
.parent_names = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
.ops = _ops, \
}
struct zx_pll_config {
unsigned long rate;
u32 cfg0;

View File

@ -58,6 +58,186 @@
#define GCC_QPIC_AHB_CLK 41
#define GCC_QPIC_CLK 42
#define PCNOC_BFDCD_CLK_SRC 43
#define GPLL2_MAIN 44
#define GPLL2 45
#define GPLL4_MAIN 46
#define GPLL4 47
#define GPLL6_MAIN 48
#define GPLL6 49
#define UBI32_PLL_MAIN 50
#define UBI32_PLL 51
#define NSS_CRYPTO_PLL_MAIN 52
#define NSS_CRYPTO_PLL 53
#define PCIE0_AXI_CLK_SRC 54
#define PCIE0_AUX_CLK_SRC 55
#define PCIE0_PIPE_CLK_SRC 56
#define PCIE1_AXI_CLK_SRC 57
#define PCIE1_AUX_CLK_SRC 58
#define PCIE1_PIPE_CLK_SRC 59
#define SDCC1_APPS_CLK_SRC 60
#define SDCC1_ICE_CORE_CLK_SRC 61
#define SDCC2_APPS_CLK_SRC 62
#define USB0_MASTER_CLK_SRC 63
#define USB0_AUX_CLK_SRC 64
#define USB0_MOCK_UTMI_CLK_SRC 65
#define USB0_PIPE_CLK_SRC 66
#define USB1_MASTER_CLK_SRC 67
#define USB1_AUX_CLK_SRC 68
#define USB1_MOCK_UTMI_CLK_SRC 69
#define USB1_PIPE_CLK_SRC 70
#define GCC_XO_CLK_SRC 71
#define SYSTEM_NOC_BFDCD_CLK_SRC 72
#define NSS_CE_CLK_SRC 73
#define NSS_NOC_BFDCD_CLK_SRC 74
#define NSS_CRYPTO_CLK_SRC 75
#define NSS_UBI0_CLK_SRC 76
#define NSS_UBI0_DIV_CLK_SRC 77
#define NSS_UBI1_CLK_SRC 78
#define NSS_UBI1_DIV_CLK_SRC 79
#define UBI_MPT_CLK_SRC 80
#define NSS_IMEM_CLK_SRC 81
#define NSS_PPE_CLK_SRC 82
#define NSS_PORT1_RX_CLK_SRC 83
#define NSS_PORT1_RX_DIV_CLK_SRC 84
#define NSS_PORT1_TX_CLK_SRC 85
#define NSS_PORT1_TX_DIV_CLK_SRC 86
#define NSS_PORT2_RX_CLK_SRC 87
#define NSS_PORT2_RX_DIV_CLK_SRC 88
#define NSS_PORT2_TX_CLK_SRC 89
#define NSS_PORT2_TX_DIV_CLK_SRC 90
#define NSS_PORT3_RX_CLK_SRC 91
#define NSS_PORT3_RX_DIV_CLK_SRC 92
#define NSS_PORT3_TX_CLK_SRC 93
#define NSS_PORT3_TX_DIV_CLK_SRC 94
#define NSS_PORT4_RX_CLK_SRC 95
#define NSS_PORT4_RX_DIV_CLK_SRC 96
#define NSS_PORT4_TX_CLK_SRC 97
#define NSS_PORT4_TX_DIV_CLK_SRC 98
#define NSS_PORT5_RX_CLK_SRC 99
#define NSS_PORT5_RX_DIV_CLK_SRC 100
#define NSS_PORT5_TX_CLK_SRC 101
#define NSS_PORT5_TX_DIV_CLK_SRC 102
#define NSS_PORT6_RX_CLK_SRC 103
#define NSS_PORT6_RX_DIV_CLK_SRC 104
#define NSS_PORT6_TX_CLK_SRC 105
#define NSS_PORT6_TX_DIV_CLK_SRC 106
#define CRYPTO_CLK_SRC 107
#define GP1_CLK_SRC 108
#define GP2_CLK_SRC 109
#define GP3_CLK_SRC 110
#define GCC_PCIE0_AHB_CLK 111
#define GCC_PCIE0_AUX_CLK 112
#define GCC_PCIE0_AXI_M_CLK 113
#define GCC_PCIE0_AXI_S_CLK 114
#define GCC_PCIE0_PIPE_CLK 115
#define GCC_SYS_NOC_PCIE0_AXI_CLK 116
#define GCC_PCIE1_AHB_CLK 117
#define GCC_PCIE1_AUX_CLK 118
#define GCC_PCIE1_AXI_M_CLK 119
#define GCC_PCIE1_AXI_S_CLK 120
#define GCC_PCIE1_PIPE_CLK 121
#define GCC_SYS_NOC_PCIE1_AXI_CLK 122
#define GCC_USB0_AUX_CLK 123
#define GCC_SYS_NOC_USB0_AXI_CLK 124
#define GCC_USB0_MASTER_CLK 125
#define GCC_USB0_MOCK_UTMI_CLK 126
#define GCC_USB0_PHY_CFG_AHB_CLK 127
#define GCC_USB0_PIPE_CLK 128
#define GCC_USB0_SLEEP_CLK 129
#define GCC_USB1_AUX_CLK 130
#define GCC_SYS_NOC_USB1_AXI_CLK 131
#define GCC_USB1_MASTER_CLK 132
#define GCC_USB1_MOCK_UTMI_CLK 133
#define GCC_USB1_PHY_CFG_AHB_CLK 134
#define GCC_USB1_PIPE_CLK 135
#define GCC_USB1_SLEEP_CLK 136
#define GCC_SDCC1_AHB_CLK 137
#define GCC_SDCC1_APPS_CLK 138
#define GCC_SDCC1_ICE_CORE_CLK 139
#define GCC_SDCC2_AHB_CLK 140
#define GCC_SDCC2_APPS_CLK 141
#define GCC_MEM_NOC_NSS_AXI_CLK 142
#define GCC_NSS_CE_APB_CLK 143
#define GCC_NSS_CE_AXI_CLK 144
#define GCC_NSS_CFG_CLK 145
#define GCC_NSS_CRYPTO_CLK 146
#define GCC_NSS_CSR_CLK 147
#define GCC_NSS_EDMA_CFG_CLK 148
#define GCC_NSS_EDMA_CLK 149
#define GCC_NSS_IMEM_CLK 150
#define GCC_NSS_NOC_CLK 151
#define GCC_NSS_PPE_BTQ_CLK 152
#define GCC_NSS_PPE_CFG_CLK 153
#define GCC_NSS_PPE_CLK 154
#define GCC_NSS_PPE_IPE_CLK 155
#define GCC_NSS_PTP_REF_CLK 156
#define GCC_NSSNOC_CE_APB_CLK 157
#define GCC_NSSNOC_CE_AXI_CLK 158
#define GCC_NSSNOC_CRYPTO_CLK 159
#define GCC_NSSNOC_PPE_CFG_CLK 160
#define GCC_NSSNOC_PPE_CLK 161
#define GCC_NSSNOC_QOSGEN_REF_CLK 162
#define GCC_NSSNOC_SNOC_CLK 163
#define GCC_NSSNOC_TIMEOUT_REF_CLK 164
#define GCC_NSSNOC_UBI0_AHB_CLK 165
#define GCC_NSSNOC_UBI1_AHB_CLK 166
#define GCC_UBI0_AHB_CLK 167
#define GCC_UBI0_AXI_CLK 168
#define GCC_UBI0_NC_AXI_CLK 169
#define GCC_UBI0_CORE_CLK 170
#define GCC_UBI0_MPT_CLK 171
#define GCC_UBI1_AHB_CLK 172
#define GCC_UBI1_AXI_CLK 173
#define GCC_UBI1_NC_AXI_CLK 174
#define GCC_UBI1_CORE_CLK 175
#define GCC_UBI1_MPT_CLK 176
#define GCC_CMN_12GPLL_AHB_CLK 177
#define GCC_CMN_12GPLL_SYS_CLK 178
#define GCC_MDIO_AHB_CLK 179
#define GCC_UNIPHY0_AHB_CLK 180
#define GCC_UNIPHY0_SYS_CLK 181
#define GCC_UNIPHY1_AHB_CLK 182
#define GCC_UNIPHY1_SYS_CLK 183
#define GCC_UNIPHY2_AHB_CLK 184
#define GCC_UNIPHY2_SYS_CLK 185
#define GCC_NSS_PORT1_RX_CLK 186
#define GCC_NSS_PORT1_TX_CLK 187
#define GCC_NSS_PORT2_RX_CLK 188
#define GCC_NSS_PORT2_TX_CLK 189
#define GCC_NSS_PORT3_RX_CLK 190
#define GCC_NSS_PORT3_TX_CLK 191
#define GCC_NSS_PORT4_RX_CLK 192
#define GCC_NSS_PORT4_TX_CLK 193
#define GCC_NSS_PORT5_RX_CLK 194
#define GCC_NSS_PORT5_TX_CLK 195
#define GCC_NSS_PORT6_RX_CLK 196
#define GCC_NSS_PORT6_TX_CLK 197
#define GCC_PORT1_MAC_CLK 198
#define GCC_PORT2_MAC_CLK 199
#define GCC_PORT3_MAC_CLK 200
#define GCC_PORT4_MAC_CLK 201
#define GCC_PORT5_MAC_CLK 202
#define GCC_PORT6_MAC_CLK 203
#define GCC_UNIPHY0_PORT1_RX_CLK 204
#define GCC_UNIPHY0_PORT1_TX_CLK 205
#define GCC_UNIPHY0_PORT2_RX_CLK 206
#define GCC_UNIPHY0_PORT2_TX_CLK 207
#define GCC_UNIPHY0_PORT3_RX_CLK 208
#define GCC_UNIPHY0_PORT3_TX_CLK 209
#define GCC_UNIPHY0_PORT4_RX_CLK 210
#define GCC_UNIPHY0_PORT4_TX_CLK 211
#define GCC_UNIPHY0_PORT5_RX_CLK 212
#define GCC_UNIPHY0_PORT5_TX_CLK 213
#define GCC_UNIPHY1_PORT5_RX_CLK 214
#define GCC_UNIPHY1_PORT5_TX_CLK 215
#define GCC_UNIPHY2_PORT6_RX_CLK 216
#define GCC_UNIPHY2_PORT6_TX_CLK 217
#define GCC_CRYPTO_AHB_CLK 218
#define GCC_CRYPTO_AXI_CLK 219
#define GCC_CRYPTO_CLK 220
#define GCC_GP1_CLK 221
#define GCC_GP2_CLK 222
#define GCC_GP3_CLK 223
#define GCC_BLSP1_BCR 0
#define GCC_BLSP1_QUP1_BCR 1
@ -148,5 +328,47 @@
#define GCC_APC0_VOLTAGE_DROOP_DETECTOR_BCR 86
#define GCC_APC1_VOLTAGE_DROOP_DETECTOR_BCR 87
#define GCC_SMMU_CATS_BCR 88
#define GCC_UBI0_AXI_ARES 89
#define GCC_UBI0_AHB_ARES 90
#define GCC_UBI0_NC_AXI_ARES 91
#define GCC_UBI0_DBG_ARES 92
#define GCC_UBI0_CORE_CLAMP_ENABLE 93
#define GCC_UBI0_CLKRST_CLAMP_ENABLE 94
#define GCC_UBI1_AXI_ARES 95
#define GCC_UBI1_AHB_ARES 96
#define GCC_UBI1_NC_AXI_ARES 97
#define GCC_UBI1_DBG_ARES 98
#define GCC_UBI1_CORE_CLAMP_ENABLE 99
#define GCC_UBI1_CLKRST_CLAMP_ENABLE 100
#define GCC_NSS_CFG_ARES 101
#define GCC_NSS_IMEM_ARES 102
#define GCC_NSS_NOC_ARES 103
#define GCC_NSS_CRYPTO_ARES 104
#define GCC_NSS_CSR_ARES 105
#define GCC_NSS_CE_APB_ARES 106
#define GCC_NSS_CE_AXI_ARES 107
#define GCC_NSSNOC_CE_APB_ARES 108
#define GCC_NSSNOC_CE_AXI_ARES 109
#define GCC_NSSNOC_UBI0_AHB_ARES 110
#define GCC_NSSNOC_UBI1_AHB_ARES 111
#define GCC_NSSNOC_SNOC_ARES 112
#define GCC_NSSNOC_CRYPTO_ARES 113
#define GCC_NSSNOC_ATB_ARES 114
#define GCC_NSSNOC_QOSGEN_REF_ARES 115
#define GCC_NSSNOC_TIMEOUT_REF_ARES 116
#define GCC_PCIE0_PIPE_ARES 117
#define GCC_PCIE0_SLEEP_ARES 118
#define GCC_PCIE0_CORE_STICKY_ARES 119
#define GCC_PCIE0_AXI_MASTER_ARES 120
#define GCC_PCIE0_AXI_SLAVE_ARES 121
#define GCC_PCIE0_AHB_ARES 122
#define GCC_PCIE0_AXI_MASTER_STICKY_ARES 123
#define GCC_PCIE1_PIPE_ARES 124
#define GCC_PCIE1_SLEEP_ARES 125
#define GCC_PCIE1_CORE_STICKY_ARES 126
#define GCC_PCIE1_AXI_MASTER_ARES 127
#define GCC_PCIE1_AXI_SLAVE_ARES 128
#define GCC_PCIE1_AHB_ARES 129
#define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130
#endif

View File

@ -0,0 +1,404 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
//
// Spreadtrum SC9860 platform clocks
//
// Copyright (C) 2017, Spreadtrum Communications Inc.
#ifndef _DT_BINDINGS_CLK_SC9860_H_
#define _DT_BINDINGS_CLK_SC9860_H_
#define CLK_FAC_4M 0
#define CLK_FAC_2M 1
#define CLK_FAC_1M 2
#define CLK_FAC_250K 3
#define CLK_FAC_RPLL0_26M 4
#define CLK_FAC_RPLL1_26M 5
#define CLK_FAC_RCO25M 6
#define CLK_FAC_RCO4M 7
#define CLK_FAC_RCO2M 8
#define CLK_FAC_3K2 9
#define CLK_FAC_1K 10
#define CLK_MPLL0_GATE 11
#define CLK_MPLL1_GATE 12
#define CLK_DPLL0_GATE 13
#define CLK_DPLL1_GATE 14
#define CLK_LTEPLL0_GATE 15
#define CLK_TWPLL_GATE 16
#define CLK_LTEPLL1_GATE 17
#define CLK_RPLL0_GATE 18
#define CLK_RPLL1_GATE 19
#define CLK_CPPLL_GATE 20
#define CLK_GPLL_GATE 21
#define CLK_PMU_GATE_NUM (CLK_GPLL_GATE + 1)
#define CLK_MPLL0 0
#define CLK_MPLL1 1
#define CLK_DPLL0 2
#define CLK_DPLL1 3
#define CLK_RPLL0 4
#define CLK_RPLL1 5
#define CLK_TWPLL 6
#define CLK_LTEPLL0 7
#define CLK_LTEPLL1 8
#define CLK_GPLL 9
#define CLK_CPPLL 10
#define CLK_GPLL_42M5 11
#define CLK_TWPLL_768M 12
#define CLK_TWPLL_384M 13
#define CLK_TWPLL_192M 14
#define CLK_TWPLL_96M 15
#define CLK_TWPLL_48M 16
#define CLK_TWPLL_24M 17
#define CLK_TWPLL_12M 18
#define CLK_TWPLL_512M 19
#define CLK_TWPLL_256M 20
#define CLK_TWPLL_128M 21
#define CLK_TWPLL_64M 22
#define CLK_TWPLL_307M2 23
#define CLK_TWPLL_153M6 24
#define CLK_TWPLL_76M8 25
#define CLK_TWPLL_51M2 26
#define CLK_TWPLL_38M4 27
#define CLK_TWPLL_19M2 28
#define CLK_L0_614M4 29
#define CLK_L0_409M6 30
#define CLK_L0_38M 31
#define CLK_L1_38M 32
#define CLK_RPLL0_192M 33
#define CLK_RPLL0_96M 34
#define CLK_RPLL0_48M 35
#define CLK_RPLL1_468M 36
#define CLK_RPLL1_192M 37
#define CLK_RPLL1_96M 38
#define CLK_RPLL1_64M 39
#define CLK_RPLL1_48M 40
#define CLK_DPLL0_50M 41
#define CLK_DPLL1_50M 42
#define CLK_CPPLL_50M 43
#define CLK_M0_39M 44
#define CLK_M1_63M 45
#define CLK_PLL_NUM (CLK_M1_63M + 1)
#define CLK_AP_APB 0
#define CLK_AP_USB3 1
#define CLK_UART0 2
#define CLK_UART1 3
#define CLK_UART2 4
#define CLK_UART3 5
#define CLK_UART4 6
#define CLK_I2C0 7
#define CLK_I2C1 8
#define CLK_I2C2 9
#define CLK_I2C3 10
#define CLK_I2C4 11
#define CLK_I2C5 12
#define CLK_SPI0 13
#define CLK_SPI1 14
#define CLK_SPI2 15
#define CLK_SPI3 16
#define CLK_IIS0 17
#define CLK_IIS1 18
#define CLK_IIS2 19
#define CLK_IIS3 20
#define CLK_AP_CLK_NUM (CLK_IIS3 + 1)
#define CLK_AON_APB 0
#define CLK_AUX0 1
#define CLK_AUX1 2
#define CLK_AUX2 3
#define CLK_PROBE 4
#define CLK_SP_AHB 5
#define CLK_CCI 6
#define CLK_GIC 7
#define CLK_CSSYS 8
#define CLK_SDIO0_2X 9
#define CLK_SDIO1_2X 10
#define CLK_SDIO2_2X 11
#define CLK_EMMC_2X 12
#define CLK_SDIO0_1X 13
#define CLK_SDIO1_1X 14
#define CLK_SDIO2_1X 15
#define CLK_EMMC_1X 16
#define CLK_ADI 17
#define CLK_PWM0 18
#define CLK_PWM1 19
#define CLK_PWM2 20
#define CLK_PWM3 21
#define CLK_EFUSE 22
#define CLK_CM3_UART0 23
#define CLK_CM3_UART1 24
#define CLK_THM 25
#define CLK_CM3_I2C0 26
#define CLK_CM3_I2C1 27
#define CLK_CM4_SPI 28
#define CLK_AON_I2C 29
#define CLK_AVS 30
#define CLK_CA53_DAP 31
#define CLK_CA53_TS 32
#define CLK_DJTAG_TCK 33
#define CLK_PMU 34
#define CLK_PMU_26M 35
#define CLK_DEBOUNCE 36
#define CLK_OTG2_REF 37
#define CLK_USB3_REF 38
#define CLK_AP_AXI 39
#define CLK_AON_PREDIV_NUM (CLK_AP_AXI + 1)
#define CLK_USB3_EB 0
#define CLK_USB3_SUSPEND_EB 1
#define CLK_USB3_REF_EB 2
#define CLK_DMA_EB 3
#define CLK_SDIO0_EB 4
#define CLK_SDIO1_EB 5
#define CLK_SDIO2_EB 6
#define CLK_EMMC_EB 7
#define CLK_ROM_EB 8
#define CLK_BUSMON_EB 9
#define CLK_CC63S_EB 10
#define CLK_CC63P_EB 11
#define CLK_CE0_EB 12
#define CLK_CE1_EB 13
#define CLK_APAHB_GATE_NUM (CLK_CE1_EB + 1)
#define CLK_AVS_LIT_EB 0
#define CLK_AVS_BIG_EB 1
#define CLK_AP_INTC5_EB 2
#define CLK_GPIO_EB 3
#define CLK_PWM0_EB 4
#define CLK_PWM1_EB 5
#define CLK_PWM2_EB 6
#define CLK_PWM3_EB 7
#define CLK_KPD_EB 8
#define CLK_AON_SYS_EB 9
#define CLK_AP_SYS_EB 10
#define CLK_AON_TMR_EB 11
#define CLK_AP_TMR0_EB 12
#define CLK_EFUSE_EB 13
#define CLK_EIC_EB 14
#define CLK_PUB1_REG_EB 15
#define CLK_ADI_EB 16
#define CLK_AP_INTC0_EB 17
#define CLK_AP_INTC1_EB 18
#define CLK_AP_INTC2_EB 19
#define CLK_AP_INTC3_EB 20
#define CLK_AP_INTC4_EB 21
#define CLK_SPLK_EB 22
#define CLK_MSPI_EB 23
#define CLK_PUB0_REG_EB 24
#define CLK_PIN_EB 25
#define CLK_AON_CKG_EB 26
#define CLK_GPU_EB 27
#define CLK_APCPU_TS0_EB 28
#define CLK_APCPU_TS1_EB 29
#define CLK_DAP_EB 30
#define CLK_I2C_EB 31
#define CLK_PMU_EB 32
#define CLK_THM_EB 33
#define CLK_AUX0_EB 34
#define CLK_AUX1_EB 35
#define CLK_AUX2_EB 36
#define CLK_PROBE_EB 37
#define CLK_GPU0_AVS_EB 38
#define CLK_GPU1_AVS_EB 39
#define CLK_APCPU_WDG_EB 40
#define CLK_AP_TMR1_EB 41
#define CLK_AP_TMR2_EB 42
#define CLK_DISP_EMC_EB 43
#define CLK_ZIP_EMC_EB 44
#define CLK_GSP_EMC_EB 45
#define CLK_OSC_AON_EB 46
#define CLK_LVDS_TRX_EB 47
#define CLK_LVDS_TCXO_EB 48
#define CLK_MDAR_EB 49
#define CLK_RTC4M0_CAL_EB 50
#define CLK_RCT100M_CAL_EB 51
#define CLK_DJTAG_EB 52
#define CLK_MBOX_EB 53
#define CLK_AON_DMA_EB 54
#define CLK_DBG_EMC_EB 55
#define CLK_LVDS_PLL_DIV_EN 56
#define CLK_DEF_EB 57
#define CLK_AON_APB_RSV0 58
#define CLK_ORP_JTAG_EB 59
#define CLK_VSP_EB 60
#define CLK_CAM_EB 61
#define CLK_DISP_EB 62
#define CLK_DBG_AXI_IF_EB 63
#define CLK_SDIO0_2X_EN 64
#define CLK_SDIO1_2X_EN 65
#define CLK_SDIO2_2X_EN 66
#define CLK_EMMC_2X_EN 67
#define CLK_AON_GATE_NUM (CLK_EMMC_2X_EN + 1)
#define CLK_LIT_MCU 0
#define CLK_BIG_MCU 1
#define CLK_AONSECURE_NUM (CLK_BIG_MCU + 1)
#define CLK_AGCP_IIS0_EB 0
#define CLK_AGCP_IIS1_EB 1
#define CLK_AGCP_IIS2_EB 2
#define CLK_AGCP_IIS3_EB 3
#define CLK_AGCP_UART_EB 4
#define CLK_AGCP_DMACP_EB 5
#define CLK_AGCP_DMAAP_EB 6
#define CLK_AGCP_ARC48K_EB 7
#define CLK_AGCP_SRC44P1K_EB 8
#define CLK_AGCP_MCDT_EB 9
#define CLK_AGCP_VBCIFD_EB 10
#define CLK_AGCP_VBC_EB 11
#define CLK_AGCP_SPINLOCK_EB 12
#define CLK_AGCP_ICU_EB 13
#define CLK_AGCP_AP_ASHB_EB 14
#define CLK_AGCP_CP_ASHB_EB 15
#define CLK_AGCP_AUD_EB 16
#define CLK_AGCP_AUDIF_EB 17
#define CLK_AGCP_GATE_NUM (CLK_AGCP_AUDIF_EB + 1)
#define CLK_GPU 0
#define CLK_GPU_NUM (CLK_GPU + 1)
#define CLK_AHB_VSP 0
#define CLK_VSP 1
#define CLK_VSP_ENC 2
#define CLK_VPP 3
#define CLK_VSP_26M 4
#define CLK_VSP_NUM (CLK_VSP_26M + 1)
#define CLK_VSP_DEC_EB 0
#define CLK_VSP_CKG_EB 1
#define CLK_VSP_MMU_EB 2
#define CLK_VSP_ENC_EB 3
#define CLK_VPP_EB 4
#define CLK_VSP_26M_EB 5
#define CLK_VSP_AXI_GATE 6
#define CLK_VSP_ENC_GATE 7
#define CLK_VPP_AXI_GATE 8
#define CLK_VSP_BM_GATE 9
#define CLK_VSP_ENC_BM_GATE 10
#define CLK_VPP_BM_GATE 11
#define CLK_VSP_GATE_NUM (CLK_VPP_BM_GATE + 1)
#define CLK_AHB_CAM 0
#define CLK_SENSOR0 1
#define CLK_SENSOR1 2
#define CLK_SENSOR2 3
#define CLK_MIPI_CSI0_EB 4
#define CLK_MIPI_CSI1_EB 5
#define CLK_CAM_NUM (CLK_MIPI_CSI1_EB + 1)
#define CLK_DCAM0_EB 0
#define CLK_DCAM1_EB 1
#define CLK_ISP0_EB 2
#define CLK_CSI0_EB 3
#define CLK_CSI1_EB 4
#define CLK_JPG0_EB 5
#define CLK_JPG1_EB 6
#define CLK_CAM_CKG_EB 7
#define CLK_CAM_MMU_EB 8
#define CLK_ISP1_EB 9
#define CLK_CPP_EB 10
#define CLK_MMU_PF_EB 11
#define CLK_ISP2_EB 12
#define CLK_DCAM2ISP_IF_EB 13
#define CLK_ISP2DCAM_IF_EB 14
#define CLK_ISP_LCLK_EB 15
#define CLK_ISP_ICLK_EB 16
#define CLK_ISP_MCLK_EB 17
#define CLK_ISP_PCLK_EB 18
#define CLK_ISP_ISP2DCAM_EB 19
#define CLK_DCAM0_IF_EB 20
#define CLK_CLK26M_IF_EB 21
#define CLK_CPHY0_GATE 22
#define CLK_MIPI_CSI0_GATE 23
#define CLK_CPHY1_GATE 24
#define CLK_MIPI_CSI1 25
#define CLK_DCAM0_AXI_GATE 26
#define CLK_DCAM1_AXI_GATE 27
#define CLK_SENSOR0_GATE 28
#define CLK_SENSOR1_GATE 29
#define CLK_JPG0_AXI_GATE 30
#define CLK_GPG1_AXI_GATE 31
#define CLK_ISP0_AXI_GATE 32
#define CLK_ISP1_AXI_GATE 33
#define CLK_ISP2_AXI_GATE 34
#define CLK_CPP_AXI_GATE 35
#define CLK_D0_IF_AXI_GATE 36
#define CLK_D2I_IF_AXI_GATE 37
#define CLK_I2D_IF_AXI_GATE 38
#define CLK_SPARE_AXI_GATE 39
#define CLK_SENSOR2_GATE 40
#define CLK_D0IF_IN_D_EN 41
#define CLK_D1IF_IN_D_EN 42
#define CLK_D0IF_IN_D2I_EN 43
#define CLK_D1IF_IN_D2I_EN 44
#define CLK_IA_IN_D2I_EN 45
#define CLK_IB_IN_D2I_EN 46
#define CLK_IC_IN_D2I_EN 47
#define CLK_IA_IN_I_EN 48
#define CLK_IB_IN_I_EN 49
#define CLK_IC_IN_I_EN 50
#define CLK_CAM_GATE_NUM (CLK_IC_IN_I_EN + 1)
#define CLK_AHB_DISP 0
#define CLK_DISPC0_DPI 1
#define CLK_DISPC1_DPI 2
#define CLK_DISP_NUM (CLK_DISPC1_DPI + 1)
#define CLK_DISPC0_EB 0
#define CLK_DISPC1_EB 1
#define CLK_DISPC_MMU_EB 2
#define CLK_GSP0_EB 3
#define CLK_GSP1_EB 4
#define CLK_GSP0_MMU_EB 5
#define CLK_GSP1_MMU_EB 6
#define CLK_DSI0_EB 7
#define CLK_DSI1_EB 8
#define CLK_DISP_CKG_EB 9
#define CLK_DISP_GPU_EB 10
#define CLK_GPU_MTX_EB 11
#define CLK_GSP_MTX_EB 12
#define CLK_TMC_MTX_EB 13
#define CLK_DISPC_MTX_EB 14
#define CLK_DPHY0_GATE 15
#define CLK_DPHY1_GATE 16
#define CLK_GSP0_A_GATE 17
#define CLK_GSP1_A_GATE 18
#define CLK_GSP0_F_GATE 19
#define CLK_GSP1_F_GATE 20
#define CLK_D_MTX_F_GATE 21
#define CLK_D_MTX_A_GATE 22
#define CLK_D_NOC_F_GATE 23
#define CLK_D_NOC_A_GATE 24
#define CLK_GSP_MTX_F_GATE 25
#define CLK_GSP_MTX_A_GATE 26
#define CLK_GSP_NOC_F_GATE 27
#define CLK_GSP_NOC_A_GATE 28
#define CLK_DISPM0IDLE_GATE 29
#define CLK_GSPM0IDLE_GATE 30
#define CLK_DISP_GATE_NUM (CLK_GSPM0IDLE_GATE + 1)
#define CLK_SIM0_EB 0
#define CLK_IIS0_EB 1
#define CLK_IIS1_EB 2
#define CLK_IIS2_EB 3
#define CLK_IIS3_EB 4
#define CLK_SPI0_EB 5
#define CLK_SPI1_EB 6
#define CLK_SPI2_EB 7
#define CLK_I2C0_EB 8
#define CLK_I2C1_EB 9
#define CLK_I2C2_EB 10
#define CLK_I2C3_EB 11
#define CLK_I2C4_EB 12
#define CLK_I2C5_EB 13
#define CLK_UART0_EB 14
#define CLK_UART1_EB 15
#define CLK_UART2_EB 16
#define CLK_UART3_EB 17
#define CLK_UART4_EB 18
#define CLK_AP_CKG_EB 19
#define CLK_SPI3_EB 20
#define CLK_APAPB_GATE_NUM (CLK_SPI3_EB + 1)
#endif /* _DT_BINDINGS_CLK_SC9860_H_ */

View File

@ -807,6 +807,44 @@ extern struct of_device_id __clk_of_table;
} \
OF_DECLARE_1(clk, name, compat, name##_of_clk_init_driver)
#define CLK_HW_INIT(_name, _parent, _ops, _flags) \
(&(struct clk_init_data) { \
.flags = _flags, \
.name = _name, \
.parent_names = (const char *[]) { _parent }, \
.num_parents = 1, \
.ops = _ops, \
})
#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \
(&(struct clk_init_data) { \
.flags = _flags, \
.name = _name, \
.parent_names = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
.ops = _ops, \
})
#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \
(&(struct clk_init_data) { \
.flags = _flags, \
.name = _name, \
.parent_names = NULL, \
.num_parents = 0, \
.ops = _ops, \
})
#define CLK_FIXED_FACTOR(_struct, _name, _parent, \
_div, _mult, _flags) \
struct clk_fixed_factor _struct = { \
.div = _div, \
.mult = _mult, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&clk_fixed_factor_ops, \
_flags), \
}
#ifdef CONFIG_OF
int of_clk_add_provider(struct device_node *np,
struct clk *(*clk_src_get)(struct of_phandle_args *args,