1 // SPDX-License-Identifier: GPL-2.0
3 * Freescale SAI BCLK as a generic clock driver
5 * Copyright 2020 Michael Walle <michael@walle.cc>
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/clk-provider.h>
11 #include <linux/err.h>
13 #include <linux/of_address.h>
14 #include <linux/slab.h>
18 #define CSR_BCE_BIT 28
19 #define CR2_BCD BIT(24)
20 #define CR2_DIV_SHIFT 0
21 #define CR2_DIV_WIDTH 8
24 struct clk_divider div
;
29 static int fsl_sai_clk_probe(struct platform_device
*pdev
)
31 struct device
*dev
= &pdev
->dev
;
32 struct fsl_sai_clk
*sai_clk
;
33 struct clk_parent_data pdata
= { .index
= 0 };
38 sai_clk
= devm_kzalloc(dev
, sizeof(*sai_clk
), GFP_KERNEL
);
42 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
43 base
= devm_ioremap_resource(dev
, res
);
47 spin_lock_init(&sai_clk
->lock
);
49 sai_clk
->gate
.reg
= base
+ I2S_CSR
;
50 sai_clk
->gate
.bit_idx
= CSR_BCE_BIT
;
51 sai_clk
->gate
.lock
= &sai_clk
->lock
;
53 sai_clk
->div
.reg
= base
+ I2S_CR2
;
54 sai_clk
->div
.shift
= CR2_DIV_SHIFT
;
55 sai_clk
->div
.width
= CR2_DIV_WIDTH
;
56 sai_clk
->div
.lock
= &sai_clk
->lock
;
58 /* set clock direction, we are the BCLK master */
59 writel(CR2_BCD
, base
+ I2S_CR2
);
61 hw
= devm_clk_hw_register_composite_pdata(dev
, dev
->of_node
->name
,
62 &pdata
, 1, NULL
, NULL
,
71 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_simple_get
, hw
);
74 static const struct of_device_id of_fsl_sai_clk_ids
[] = {
75 { .compatible
= "fsl,vf610-sai-clock" },
78 MODULE_DEVICE_TABLE(of
, of_fsl_sai_clk_ids
);
80 static struct platform_driver fsl_sai_clk_driver
= {
81 .probe
= fsl_sai_clk_probe
,
83 .name
= "fsl-sai-clk",
84 .of_match_table
= of_fsl_sai_clk_ids
,
87 module_platform_driver(fsl_sai_clk_driver
);
89 MODULE_DESCRIPTION("Freescale SAI bitclock-as-a-clock driver");
90 MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
91 MODULE_LICENSE("GPL");
92 MODULE_ALIAS("platform:fsl-sai-clk");