xref: /linux/drivers/clk/clk-fsl-sai.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
19cd10205SMichael Walle // SPDX-License-Identifier: GPL-2.0
29cd10205SMichael Walle /*
39cd10205SMichael Walle  * Freescale SAI BCLK as a generic clock driver
49cd10205SMichael Walle  *
59cd10205SMichael Walle  * Copyright 2020 Michael Walle <michael@walle.cc>
69cd10205SMichael Walle  */
79cd10205SMichael Walle 
89cd10205SMichael Walle #include <linux/module.h>
99cd10205SMichael Walle #include <linux/platform_device.h>
109cd10205SMichael Walle #include <linux/clk-provider.h>
119cd10205SMichael Walle #include <linux/err.h>
129cd10205SMichael Walle #include <linux/of.h>
139cd10205SMichael Walle #include <linux/of_address.h>
149cd10205SMichael Walle #include <linux/slab.h>
159cd10205SMichael Walle 
169cd10205SMichael Walle #define I2S_CSR		0x00
179cd10205SMichael Walle #define I2S_CR2		0x08
189cd10205SMichael Walle #define CSR_BCE_BIT	28
199cd10205SMichael Walle #define CR2_BCD		BIT(24)
209cd10205SMichael Walle #define CR2_DIV_SHIFT	0
219cd10205SMichael Walle #define CR2_DIV_WIDTH	8
229cd10205SMichael Walle 
239cd10205SMichael Walle struct fsl_sai_clk {
249cd10205SMichael Walle 	struct clk_divider div;
259cd10205SMichael Walle 	struct clk_gate gate;
269cd10205SMichael Walle 	spinlock_t lock;
279cd10205SMichael Walle };
289cd10205SMichael Walle 
fsl_sai_clk_probe(struct platform_device * pdev)299cd10205SMichael Walle static int fsl_sai_clk_probe(struct platform_device *pdev)
309cd10205SMichael Walle {
319cd10205SMichael Walle 	struct device *dev = &pdev->dev;
329cd10205SMichael Walle 	struct fsl_sai_clk *sai_clk;
339cd10205SMichael Walle 	struct clk_parent_data pdata = { .index = 0 };
349cd10205SMichael Walle 	void __iomem *base;
359cd10205SMichael Walle 	struct clk_hw *hw;
369cd10205SMichael Walle 
379cd10205SMichael Walle 	sai_clk = devm_kzalloc(dev, sizeof(*sai_clk), GFP_KERNEL);
389cd10205SMichael Walle 	if (!sai_clk)
399cd10205SMichael Walle 		return -ENOMEM;
409cd10205SMichael Walle 
41*d1aa4546SYangtao Li 	base = devm_platform_ioremap_resource(pdev, 0);
429cd10205SMichael Walle 	if (IS_ERR(base))
439cd10205SMichael Walle 		return PTR_ERR(base);
449cd10205SMichael Walle 
459cd10205SMichael Walle 	spin_lock_init(&sai_clk->lock);
469cd10205SMichael Walle 
479cd10205SMichael Walle 	sai_clk->gate.reg = base + I2S_CSR;
489cd10205SMichael Walle 	sai_clk->gate.bit_idx = CSR_BCE_BIT;
499cd10205SMichael Walle 	sai_clk->gate.lock = &sai_clk->lock;
509cd10205SMichael Walle 
519cd10205SMichael Walle 	sai_clk->div.reg = base + I2S_CR2;
529cd10205SMichael Walle 	sai_clk->div.shift = CR2_DIV_SHIFT;
539cd10205SMichael Walle 	sai_clk->div.width = CR2_DIV_WIDTH;
549cd10205SMichael Walle 	sai_clk->div.lock = &sai_clk->lock;
559cd10205SMichael Walle 
569cd10205SMichael Walle 	/* set clock direction, we are the BCLK master */
579cd10205SMichael Walle 	writel(CR2_BCD, base + I2S_CR2);
589cd10205SMichael Walle 
59fb871515SMichael Walle 	hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
609cd10205SMichael Walle 						  &pdata, 1, NULL, NULL,
619cd10205SMichael Walle 						  &sai_clk->div.hw,
629cd10205SMichael Walle 						  &clk_divider_ops,
639cd10205SMichael Walle 						  &sai_clk->gate.hw,
649cd10205SMichael Walle 						  &clk_gate_ops,
659cd10205SMichael Walle 						  CLK_SET_RATE_GATE);
669cd10205SMichael Walle 	if (IS_ERR(hw))
679cd10205SMichael Walle 		return PTR_ERR(hw);
689cd10205SMichael Walle 
699cd10205SMichael Walle 	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
709cd10205SMichael Walle }
719cd10205SMichael Walle 
729cd10205SMichael Walle static const struct of_device_id of_fsl_sai_clk_ids[] = {
739cd10205SMichael Walle 	{ .compatible = "fsl,vf610-sai-clock" },
749cd10205SMichael Walle 	{ }
759cd10205SMichael Walle };
769cd10205SMichael Walle MODULE_DEVICE_TABLE(of, of_fsl_sai_clk_ids);
779cd10205SMichael Walle 
789cd10205SMichael Walle static struct platform_driver fsl_sai_clk_driver = {
799cd10205SMichael Walle 	.probe = fsl_sai_clk_probe,
809cd10205SMichael Walle 	.driver		= {
819cd10205SMichael Walle 		.name	= "fsl-sai-clk",
829cd10205SMichael Walle 		.of_match_table = of_fsl_sai_clk_ids,
839cd10205SMichael Walle 	},
849cd10205SMichael Walle };
859cd10205SMichael Walle module_platform_driver(fsl_sai_clk_driver);
869cd10205SMichael Walle 
879cd10205SMichael Walle MODULE_DESCRIPTION("Freescale SAI bitclock-as-a-clock driver");
889cd10205SMichael Walle MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
899cd10205SMichael Walle MODULE_ALIAS("platform:fsl-sai-clk");
90