1*8d92085fSXuyang Dong // SPDX-License-Identifier: GPL-2.0
2*8d92085fSXuyang Dong /*
3*8d92085fSXuyang Dong * Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd..
4*8d92085fSXuyang Dong * All rights reserved.
5*8d92085fSXuyang Dong *
6*8d92085fSXuyang Dong * ESWIN EIC7700 HSP Clock Driver
7*8d92085fSXuyang Dong *
8*8d92085fSXuyang Dong * Authors: Xuyang Dong <dongxuyang@eswincomputing.com>
9*8d92085fSXuyang Dong */
10*8d92085fSXuyang Dong
11*8d92085fSXuyang Dong #include <linux/auxiliary_bus.h>
12*8d92085fSXuyang Dong #include <linux/clk-provider.h>
13*8d92085fSXuyang Dong #include <linux/platform_device.h>
14*8d92085fSXuyang Dong #include <linux/regmap.h>
15*8d92085fSXuyang Dong
16*8d92085fSXuyang Dong #include <dt-bindings/clock/eswin,eic7700-hspcrg.h>
17*8d92085fSXuyang Dong
18*8d92085fSXuyang Dong #include "common.h"
19*8d92085fSXuyang Dong
20*8d92085fSXuyang Dong #define EIC7700_HSP_SATA_REG 0x300
21*8d92085fSXuyang Dong #define EIC7700_HSP_MSHC0_REG 0x510
22*8d92085fSXuyang Dong #define EIC7700_HSP_MSHC1_REG 0x610
23*8d92085fSXuyang Dong #define EIC7700_HSP_MSHC2_REG 0x710
24*8d92085fSXuyang Dong #define EIC7700_HSP_USB0_REG 0x800
25*8d92085fSXuyang Dong #define EIC7700_HSP_USB0_REF_REG 0x83c
26*8d92085fSXuyang Dong #define EIC7700_HSP_USB1_REG 0x900
27*8d92085fSXuyang Dong #define EIC7700_HSP_USB1_REF_REG 0x93c
28*8d92085fSXuyang Dong
29*8d92085fSXuyang Dong #define USB_REF_XTAL24M 0x2a
30*8d92085fSXuyang Dong #define EIC7700_HSP_NR_CLKS (EIC7700_HSP_CLK_GATE_SATA + 1)
31*8d92085fSXuyang Dong
32*8d92085fSXuyang Dong struct eic7700_hsp_clk_gate {
33*8d92085fSXuyang Dong struct clk_hw hw;
34*8d92085fSXuyang Dong unsigned int id;
35*8d92085fSXuyang Dong struct regmap *regmap;
36*8d92085fSXuyang Dong unsigned int reg;
37*8d92085fSXuyang Dong unsigned int ref_reg;
38*8d92085fSXuyang Dong const char *name;
39*8d92085fSXuyang Dong const struct clk_parent_data *parent_data;
40*8d92085fSXuyang Dong unsigned long flags;
41*8d92085fSXuyang Dong unsigned int offset;
42*8d92085fSXuyang Dong unsigned int ref_offset;
43*8d92085fSXuyang Dong u8 bit_idx;
44*8d92085fSXuyang Dong };
45*8d92085fSXuyang Dong
46*8d92085fSXuyang Dong static const struct regmap_config eic7700_hsp_regmap_config = {
47*8d92085fSXuyang Dong .reg_bits = 32,
48*8d92085fSXuyang Dong .val_bits = 32,
49*8d92085fSXuyang Dong .max_register = 0x1ffc,
50*8d92085fSXuyang Dong .reg_stride = 4,
51*8d92085fSXuyang Dong .fast_io = true,
52*8d92085fSXuyang Dong .use_raw_spinlock = true,
53*8d92085fSXuyang Dong };
54*8d92085fSXuyang Dong
to_gate_clk(struct clk_hw * hw)55*8d92085fSXuyang Dong static inline struct eic7700_hsp_clk_gate *to_gate_clk(struct clk_hw *hw)
56*8d92085fSXuyang Dong {
57*8d92085fSXuyang Dong return container_of(hw, struct eic7700_hsp_clk_gate, hw);
58*8d92085fSXuyang Dong }
59*8d92085fSXuyang Dong
60*8d92085fSXuyang Dong #define EIC7700_HSP_GATE(_id, _name, _pdata, _flags, _offset, _idx, \
61*8d92085fSXuyang Dong _ref_offset) \
62*8d92085fSXuyang Dong { \
63*8d92085fSXuyang Dong .id = _id, \
64*8d92085fSXuyang Dong .name = _name, \
65*8d92085fSXuyang Dong .parent_data = _pdata, \
66*8d92085fSXuyang Dong .flags = _flags, \
67*8d92085fSXuyang Dong .offset = _offset, \
68*8d92085fSXuyang Dong .ref_offset = _ref_offset, \
69*8d92085fSXuyang Dong .bit_idx = _idx, \
70*8d92085fSXuyang Dong }
71*8d92085fSXuyang Dong
hsp_clk_gate_endisable(struct clk_hw * hw,bool enable)72*8d92085fSXuyang Dong static void hsp_clk_gate_endisable(struct clk_hw *hw, bool enable)
73*8d92085fSXuyang Dong {
74*8d92085fSXuyang Dong struct eic7700_hsp_clk_gate *gate = to_gate_clk(hw);
75*8d92085fSXuyang Dong
76*8d92085fSXuyang Dong if (enable) {
77*8d92085fSXuyang Dong /*
78*8d92085fSXuyang Dong * Hardware bug: The USB reference clock must be 24MHz.
79*8d92085fSXuyang Dong * The default register value after reset is invalid.
80*8d92085fSXuyang Dong * Workaround: Rewrite the correct value before enabling
81*8d92085fSXuyang Dong * the USB gate clock.
82*8d92085fSXuyang Dong */
83*8d92085fSXuyang Dong regmap_update_bits(gate->regmap, gate->ref_reg, 0x3f,
84*8d92085fSXuyang Dong USB_REF_XTAL24M);
85*8d92085fSXuyang Dong }
86*8d92085fSXuyang Dong regmap_assign_bits(gate->regmap, gate->reg, BIT(gate->bit_idx), enable);
87*8d92085fSXuyang Dong }
88*8d92085fSXuyang Dong
hsp_clk_gate_enable(struct clk_hw * hw)89*8d92085fSXuyang Dong static int hsp_clk_gate_enable(struct clk_hw *hw)
90*8d92085fSXuyang Dong {
91*8d92085fSXuyang Dong hsp_clk_gate_endisable(hw, true);
92*8d92085fSXuyang Dong
93*8d92085fSXuyang Dong return 0;
94*8d92085fSXuyang Dong }
95*8d92085fSXuyang Dong
hsp_clk_gate_disable(struct clk_hw * hw)96*8d92085fSXuyang Dong static void hsp_clk_gate_disable(struct clk_hw *hw)
97*8d92085fSXuyang Dong {
98*8d92085fSXuyang Dong hsp_clk_gate_endisable(hw, false);
99*8d92085fSXuyang Dong }
100*8d92085fSXuyang Dong
hsp_clk_gate_is_enabled(struct clk_hw * hw)101*8d92085fSXuyang Dong static int hsp_clk_gate_is_enabled(struct clk_hw *hw)
102*8d92085fSXuyang Dong {
103*8d92085fSXuyang Dong struct eic7700_hsp_clk_gate *gate = to_gate_clk(hw);
104*8d92085fSXuyang Dong unsigned int val;
105*8d92085fSXuyang Dong int ret;
106*8d92085fSXuyang Dong
107*8d92085fSXuyang Dong ret = regmap_read(gate->regmap, gate->reg, &val);
108*8d92085fSXuyang Dong if (ret != 0)
109*8d92085fSXuyang Dong return ret;
110*8d92085fSXuyang Dong
111*8d92085fSXuyang Dong return !!(val & BIT(gate->bit_idx));
112*8d92085fSXuyang Dong }
113*8d92085fSXuyang Dong
114*8d92085fSXuyang Dong static const struct clk_ops hsp_clk_gate_ops = {
115*8d92085fSXuyang Dong .enable = hsp_clk_gate_enable,
116*8d92085fSXuyang Dong .disable = hsp_clk_gate_disable,
117*8d92085fSXuyang Dong .is_enabled = hsp_clk_gate_is_enabled,
118*8d92085fSXuyang Dong };
119*8d92085fSXuyang Dong
120*8d92085fSXuyang Dong static struct clk_hw *
hsp_clk_register_gate(struct device * dev,unsigned int id,const char * name,const struct clk_parent_data * parent_data,unsigned long flags,struct regmap * regmap,unsigned int reg,unsigned int ref_reg,u8 bit_idx)121*8d92085fSXuyang Dong hsp_clk_register_gate(struct device *dev, unsigned int id, const char *name,
122*8d92085fSXuyang Dong const struct clk_parent_data *parent_data,
123*8d92085fSXuyang Dong unsigned long flags, struct regmap *regmap,
124*8d92085fSXuyang Dong unsigned int reg, unsigned int ref_reg, u8 bit_idx)
125*8d92085fSXuyang Dong {
126*8d92085fSXuyang Dong struct eic7700_hsp_clk_gate *gate;
127*8d92085fSXuyang Dong struct clk_init_data init = {};
128*8d92085fSXuyang Dong struct clk_hw *hw;
129*8d92085fSXuyang Dong int ret;
130*8d92085fSXuyang Dong
131*8d92085fSXuyang Dong gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
132*8d92085fSXuyang Dong if (!gate)
133*8d92085fSXuyang Dong return ERR_PTR(-ENOMEM);
134*8d92085fSXuyang Dong
135*8d92085fSXuyang Dong init.name = name;
136*8d92085fSXuyang Dong init.ops = &hsp_clk_gate_ops;
137*8d92085fSXuyang Dong init.flags = flags;
138*8d92085fSXuyang Dong init.parent_data = parent_data;
139*8d92085fSXuyang Dong init.num_parents = 1;
140*8d92085fSXuyang Dong
141*8d92085fSXuyang Dong gate->id = id;
142*8d92085fSXuyang Dong gate->regmap = regmap;
143*8d92085fSXuyang Dong gate->reg = reg;
144*8d92085fSXuyang Dong gate->ref_reg = ref_reg;
145*8d92085fSXuyang Dong gate->bit_idx = bit_idx;
146*8d92085fSXuyang Dong gate->hw.init = &init;
147*8d92085fSXuyang Dong
148*8d92085fSXuyang Dong hw = &gate->hw;
149*8d92085fSXuyang Dong ret = devm_clk_hw_register(dev, hw);
150*8d92085fSXuyang Dong if (ret)
151*8d92085fSXuyang Dong hw = ERR_PTR(ret);
152*8d92085fSXuyang Dong
153*8d92085fSXuyang Dong return hw;
154*8d92085fSXuyang Dong }
155*8d92085fSXuyang Dong
156*8d92085fSXuyang Dong static const struct clk_parent_data hsp_cfg[] = {
157*8d92085fSXuyang Dong { .index = 0 }
158*8d92085fSXuyang Dong };
159*8d92085fSXuyang Dong
160*8d92085fSXuyang Dong static const struct clk_parent_data hsp_mmc[] = {
161*8d92085fSXuyang Dong { .index = 1 }
162*8d92085fSXuyang Dong };
163*8d92085fSXuyang Dong
164*8d92085fSXuyang Dong static const struct clk_parent_data hsp_usb_sata[] = {
165*8d92085fSXuyang Dong { .index = 2 }
166*8d92085fSXuyang Dong };
167*8d92085fSXuyang Dong
168*8d92085fSXuyang Dong static struct eswin_fixed_factor_clock eic7700_hsp_factor_clks[] = {
169*8d92085fSXuyang Dong ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_CFG_DIV2, "factor_hsp_cfg_div2",
170*8d92085fSXuyang Dong hsp_cfg, 1, 2, 0),
171*8d92085fSXuyang Dong ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_CFG_DIV4, "factor_hsp_cfg_div4",
172*8d92085fSXuyang Dong hsp_cfg, 1, 4, 0),
173*8d92085fSXuyang Dong ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_MMC_DIV10, "factor_hsp_mmc_div10",
174*8d92085fSXuyang Dong hsp_mmc, 1, 10, 0),
175*8d92085fSXuyang Dong };
176*8d92085fSXuyang Dong
177*8d92085fSXuyang Dong static struct eswin_gate_clock eic7700_hsp_gate_clks[] = {
178*8d92085fSXuyang Dong ESWIN_GATE(EIC7700_HSP_CLK_GATE_SATA, "gate_clk_hsp_sata", hsp_usb_sata,
179*8d92085fSXuyang Dong CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
180*8d92085fSXuyang Dong EIC7700_HSP_SATA_REG, 28, 0),
181*8d92085fSXuyang Dong ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC0_TMR, "gate_clk_hsp_mshc0_tmr",
182*8d92085fSXuyang Dong hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
183*8d92085fSXuyang Dong EIC7700_HSP_MSHC0_REG, 8, 0),
184*8d92085fSXuyang Dong ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC1_TMR, "gate_clk_hsp_mshc1_tmr",
185*8d92085fSXuyang Dong hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
186*8d92085fSXuyang Dong EIC7700_HSP_MSHC1_REG, 8, 0),
187*8d92085fSXuyang Dong ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC2_TMR, "gate_clk_hsp_mshc2_tmr",
188*8d92085fSXuyang Dong hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
189*8d92085fSXuyang Dong EIC7700_HSP_MSHC2_REG, 8, 0),
190*8d92085fSXuyang Dong };
191*8d92085fSXuyang Dong
192*8d92085fSXuyang Dong static struct eic7700_hsp_clk_gate eic7700_hsp_spec_gate_clks[] = {
193*8d92085fSXuyang Dong EIC7700_HSP_GATE(EIC7700_HSP_CLK_GATE_USB0, "gate_clk_hsp_usb0",
194*8d92085fSXuyang Dong hsp_usb_sata, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
195*8d92085fSXuyang Dong EIC7700_HSP_USB0_REG, 28, EIC7700_HSP_USB0_REF_REG),
196*8d92085fSXuyang Dong EIC7700_HSP_GATE(EIC7700_HSP_CLK_GATE_USB1, "gate_clk_hsp_usb1",
197*8d92085fSXuyang Dong hsp_usb_sata, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
198*8d92085fSXuyang Dong EIC7700_HSP_USB1_REG, 28, EIC7700_HSP_USB1_REF_REG),
199*8d92085fSXuyang Dong };
200*8d92085fSXuyang Dong
201*8d92085fSXuyang Dong static const struct clk_parent_data mux_mmc_3mux1_p[] = {
202*8d92085fSXuyang Dong { .fw_name = "cfg" },
203*8d92085fSXuyang Dong { .hw = &eic7700_hsp_factor_clks[0].hw },
204*8d92085fSXuyang Dong { .hw = &eic7700_hsp_factor_clks[1].hw },
205*8d92085fSXuyang Dong };
206*8d92085fSXuyang Dong
207*8d92085fSXuyang Dong static const struct clk_parent_data mux_mmc_2mux1_p[] = {
208*8d92085fSXuyang Dong { .fw_name = "mmc" },
209*8d92085fSXuyang Dong { .hw = &eic7700_hsp_factor_clks[2].hw },
210*8d92085fSXuyang Dong };
211*8d92085fSXuyang Dong
212*8d92085fSXuyang Dong static u32 mux_mmc_3mux1_tbl[] = { 0x0, 0x1, 0x3 };
213*8d92085fSXuyang Dong
214*8d92085fSXuyang Dong static struct eswin_mux_clock eic7700_hsp_mux_clks[] = {
215*8d92085fSXuyang Dong ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_EMMC_3MUX1, "mux_hsp_emmc_3mux1",
216*8d92085fSXuyang Dong mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
217*8d92085fSXuyang Dong CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC0_REG, 16, 2, 0,
218*8d92085fSXuyang Dong mux_mmc_3mux1_tbl),
219*8d92085fSXuyang Dong ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_SD0_3MUX1, "mux_hsp_sd0_3mux1",
220*8d92085fSXuyang Dong mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
221*8d92085fSXuyang Dong CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC1_REG, 16, 2, 0,
222*8d92085fSXuyang Dong mux_mmc_3mux1_tbl),
223*8d92085fSXuyang Dong ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_SD1_3MUX1, "mux_hsp_sd1_3mux1",
224*8d92085fSXuyang Dong mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
225*8d92085fSXuyang Dong CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC2_REG, 16, 2, 0,
226*8d92085fSXuyang Dong mux_mmc_3mux1_tbl),
227*8d92085fSXuyang Dong ESWIN_MUX(EIC7700_HSP_CLK_MUX_EMMC_CQE_2MUX1, "mux_hsp_emmc_cqe_2mux1",
228*8d92085fSXuyang Dong mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
229*8d92085fSXuyang Dong CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC0_REG, 0, 1, 0),
230*8d92085fSXuyang Dong ESWIN_MUX(EIC7700_HSP_CLK_MUX_SD0_CQE_2MUX1, "mux_hsp_sd0_cqe_2mux1",
231*8d92085fSXuyang Dong mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
232*8d92085fSXuyang Dong CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC1_REG, 0, 1, 0),
233*8d92085fSXuyang Dong ESWIN_MUX(EIC7700_HSP_CLK_MUX_SD1_CQE_2MUX1, "mux_hsp_sd1_cqe_2mux1",
234*8d92085fSXuyang Dong mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
235*8d92085fSXuyang Dong CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC2_REG, 0, 1, 0),
236*8d92085fSXuyang Dong };
237*8d92085fSXuyang Dong
238*8d92085fSXuyang Dong static struct eswin_clk_info eic7700_hsp_clks[] = {
239*8d92085fSXuyang Dong ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_EMMC, "gate_clk_hsp_emmc",
240*8d92085fSXuyang Dong EIC7700_HSP_CLK_MUX_EMMC_3MUX1,
241*8d92085fSXuyang Dong CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
242*8d92085fSXuyang Dong EIC7700_HSP_MSHC0_REG, 24, 0),
243*8d92085fSXuyang Dong ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_SD0, "gate_clk_hsp_sd0",
244*8d92085fSXuyang Dong EIC7700_HSP_CLK_MUX_SD0_3MUX1,
245*8d92085fSXuyang Dong CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
246*8d92085fSXuyang Dong EIC7700_HSP_MSHC1_REG, 24, 0),
247*8d92085fSXuyang Dong ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_SD1, "gate_clk_hsp_sd1",
248*8d92085fSXuyang Dong EIC7700_HSP_CLK_MUX_SD1_3MUX1,
249*8d92085fSXuyang Dong CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
250*8d92085fSXuyang Dong EIC7700_HSP_MSHC2_REG, 24, 0),
251*8d92085fSXuyang Dong };
252*8d92085fSXuyang Dong
eic7700_hsp_clk_probe(struct platform_device * pdev)253*8d92085fSXuyang Dong static int eic7700_hsp_clk_probe(struct platform_device *pdev)
254*8d92085fSXuyang Dong {
255*8d92085fSXuyang Dong struct device *dev = &pdev->dev;
256*8d92085fSXuyang Dong struct auxiliary_device *adev;
257*8d92085fSXuyang Dong struct eswin_clock_data *data;
258*8d92085fSXuyang Dong struct regmap *regmap;
259*8d92085fSXuyang Dong struct clk_hw *hw;
260*8d92085fSXuyang Dong int i, ret;
261*8d92085fSXuyang Dong
262*8d92085fSXuyang Dong data = eswin_clk_init(pdev, EIC7700_HSP_NR_CLKS);
263*8d92085fSXuyang Dong if (IS_ERR(data))
264*8d92085fSXuyang Dong return dev_err_probe(dev, PTR_ERR(data),
265*8d92085fSXuyang Dong "failed to get clk data!\n");
266*8d92085fSXuyang Dong
267*8d92085fSXuyang Dong regmap = devm_regmap_init_mmio(dev, data->base,
268*8d92085fSXuyang Dong &eic7700_hsp_regmap_config);
269*8d92085fSXuyang Dong if (IS_ERR(regmap))
270*8d92085fSXuyang Dong return dev_err_probe(dev, PTR_ERR(regmap),
271*8d92085fSXuyang Dong "failed to get regmap!\n");
272*8d92085fSXuyang Dong
273*8d92085fSXuyang Dong ret = eswin_clk_register_fixed_factor(dev, eic7700_hsp_factor_clks,
274*8d92085fSXuyang Dong ARRAY_SIZE(eic7700_hsp_factor_clks),
275*8d92085fSXuyang Dong data);
276*8d92085fSXuyang Dong if (ret)
277*8d92085fSXuyang Dong return dev_err_probe(dev, ret,
278*8d92085fSXuyang Dong "failed to register fixed factor clock\n");
279*8d92085fSXuyang Dong
280*8d92085fSXuyang Dong ret = eswin_clk_register_gate(dev, eic7700_hsp_gate_clks,
281*8d92085fSXuyang Dong ARRAY_SIZE(eic7700_hsp_gate_clks), data);
282*8d92085fSXuyang Dong if (ret)
283*8d92085fSXuyang Dong return dev_err_probe(dev, ret,
284*8d92085fSXuyang Dong "failed to register gate clock\n");
285*8d92085fSXuyang Dong
286*8d92085fSXuyang Dong ret = eswin_clk_register_mux(dev, eic7700_hsp_mux_clks,
287*8d92085fSXuyang Dong ARRAY_SIZE(eic7700_hsp_mux_clks),
288*8d92085fSXuyang Dong data);
289*8d92085fSXuyang Dong if (ret)
290*8d92085fSXuyang Dong return dev_err_probe(dev, ret,
291*8d92085fSXuyang Dong "failed to register mux clock\n");
292*8d92085fSXuyang Dong
293*8d92085fSXuyang Dong ret = eswin_clk_register_clks(dev, eic7700_hsp_clks,
294*8d92085fSXuyang Dong ARRAY_SIZE(eic7700_hsp_clks), data);
295*8d92085fSXuyang Dong if (ret)
296*8d92085fSXuyang Dong return dev_err_probe(dev, ret,
297*8d92085fSXuyang Dong "failed to register clock\n");
298*8d92085fSXuyang Dong
299*8d92085fSXuyang Dong for (i = 0; i < ARRAY_SIZE(eic7700_hsp_spec_gate_clks); i++) {
300*8d92085fSXuyang Dong struct eic7700_hsp_clk_gate *gate;
301*8d92085fSXuyang Dong
302*8d92085fSXuyang Dong gate = &eic7700_hsp_spec_gate_clks[i];
303*8d92085fSXuyang Dong hw = hsp_clk_register_gate(dev, gate->id, gate->name,
304*8d92085fSXuyang Dong gate->parent_data, gate->flags,
305*8d92085fSXuyang Dong regmap, gate->offset,
306*8d92085fSXuyang Dong gate->ref_offset, gate->bit_idx);
307*8d92085fSXuyang Dong if (IS_ERR(hw))
308*8d92085fSXuyang Dong return dev_err_probe(dev, PTR_ERR(hw),
309*8d92085fSXuyang Dong "failed to register gate clock\n");
310*8d92085fSXuyang Dong
311*8d92085fSXuyang Dong data->clk_data.hws[gate->id] = hw;
312*8d92085fSXuyang Dong }
313*8d92085fSXuyang Dong
314*8d92085fSXuyang Dong ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
315*8d92085fSXuyang Dong &data->clk_data);
316*8d92085fSXuyang Dong if (ret)
317*8d92085fSXuyang Dong return dev_err_probe(dev, ret, "add clk provider failed\n");
318*8d92085fSXuyang Dong
319*8d92085fSXuyang Dong adev = devm_auxiliary_device_create(dev, "hsp-reset", NULL);
320*8d92085fSXuyang Dong if (!adev)
321*8d92085fSXuyang Dong return dev_err_probe(dev, -ENODEV,
322*8d92085fSXuyang Dong "register hsp-reset device failed\n");
323*8d92085fSXuyang Dong
324*8d92085fSXuyang Dong return 0;
325*8d92085fSXuyang Dong }
326*8d92085fSXuyang Dong
327*8d92085fSXuyang Dong static const struct of_device_id eic7700_hsp_clock_dt_ids[] = {
328*8d92085fSXuyang Dong { .compatible = "eswin,eic7700-hspcrg", },
329*8d92085fSXuyang Dong { /* sentinel */ }
330*8d92085fSXuyang Dong };
331*8d92085fSXuyang Dong MODULE_DEVICE_TABLE(of, eic7700_hsp_clock_dt_ids);
332*8d92085fSXuyang Dong
333*8d92085fSXuyang Dong static struct platform_driver eic7700_hsp_clock_driver = {
334*8d92085fSXuyang Dong .probe = eic7700_hsp_clk_probe,
335*8d92085fSXuyang Dong .driver = {
336*8d92085fSXuyang Dong .name = "eic7700-hsp-clock",
337*8d92085fSXuyang Dong .of_match_table = eic7700_hsp_clock_dt_ids,
338*8d92085fSXuyang Dong },
339*8d92085fSXuyang Dong };
340*8d92085fSXuyang Dong
341*8d92085fSXuyang Dong module_platform_driver(eic7700_hsp_clock_driver);
342*8d92085fSXuyang Dong
343*8d92085fSXuyang Dong MODULE_LICENSE("GPL");
344*8d92085fSXuyang Dong MODULE_AUTHOR("Xuyang Dong <dongxuyang@eswincomputing.com>");
345*8d92085fSXuyang Dong MODULE_DESCRIPTION("ESWIN EIC7700 HSP clock controller driver");
346