1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 Microchip Technology Inc,
4 * Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
9 #include <linux/clk-provider.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/regmap.h>
13 #include <linux/slab.h>
15 #include <soc/at91/atmel-sfr.h>
21 struct regmap
*regmap
;
25 #define to_clk_i2s_mux(hw) container_of(hw, struct clk_i2s_mux, hw)
27 static u8
clk_i2s_mux_get_parent(struct clk_hw
*hw
)
29 struct clk_i2s_mux
*mux
= to_clk_i2s_mux(hw
);
32 regmap_read(mux
->regmap
, AT91_SFR_I2SCLKSEL
, &val
);
34 return (val
& BIT(mux
->bus_id
)) >> mux
->bus_id
;
37 static int clk_i2s_mux_set_parent(struct clk_hw
*hw
, u8 index
)
39 struct clk_i2s_mux
*mux
= to_clk_i2s_mux(hw
);
41 return regmap_update_bits(mux
->regmap
, AT91_SFR_I2SCLKSEL
,
42 BIT(mux
->bus_id
), index
<< mux
->bus_id
);
45 static const struct clk_ops clk_i2s_mux_ops
= {
46 .get_parent
= clk_i2s_mux_get_parent
,
47 .set_parent
= clk_i2s_mux_set_parent
,
48 .determine_rate
= __clk_mux_determine_rate
,
51 static struct clk_hw
* __init
52 at91_clk_i2s_mux_register(struct regmap
*regmap
, const char *name
,
53 const char * const *parent_names
,
54 unsigned int num_parents
, u8 bus_id
)
56 struct clk_init_data init
= {};
57 struct clk_i2s_mux
*i2s_ck
;
60 i2s_ck
= kzalloc(sizeof(*i2s_ck
), GFP_KERNEL
);
62 return ERR_PTR(-ENOMEM
);
65 init
.ops
= &clk_i2s_mux_ops
;
66 init
.parent_names
= parent_names
;
67 init
.num_parents
= num_parents
;
69 i2s_ck
->hw
.init
= &init
;
70 i2s_ck
->bus_id
= bus_id
;
71 i2s_ck
->regmap
= regmap
;
73 ret
= clk_hw_register(NULL
, &i2s_ck
->hw
);
82 static void __init
of_sama5d2_clk_i2s_mux_setup(struct device_node
*np
)
84 struct regmap
*regmap_sfr
;
86 const char *parent_names
[2];
87 struct device_node
*i2s_mux_np
;
91 regmap_sfr
= syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
92 if (IS_ERR(regmap_sfr
))
95 for_each_child_of_node(np
, i2s_mux_np
) {
96 if (of_property_read_u8(i2s_mux_np
, "reg", &bus_id
))
99 if (bus_id
> I2S_BUS_NR
)
102 ret
= of_clk_parent_fill(i2s_mux_np
, parent_names
, 2);
106 hw
= at91_clk_i2s_mux_register(regmap_sfr
, i2s_mux_np
->name
,
107 parent_names
, 2, bus_id
);
111 of_clk_add_hw_provider(i2s_mux_np
, of_clk_hw_simple_get
, hw
);
115 CLK_OF_DECLARE(sama5d2_clk_i2s_mux
, "atmel,sama5d2-clk-i2s-mux",
116 of_sama5d2_clk_i2s_mux_setup
);