xref: /linux/drivers/clk/clk-fsl-sai.c (revision fb8715157b6a16cf93a14109ebc8a6440a182a82)
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 
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 	struct resource *res;
379cd10205SMichael Walle 
389cd10205SMichael Walle 	sai_clk = devm_kzalloc(dev, sizeof(*sai_clk), GFP_KERNEL);
399cd10205SMichael Walle 	if (!sai_clk)
409cd10205SMichael Walle 		return -ENOMEM;
419cd10205SMichael Walle 
429cd10205SMichael Walle 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
439cd10205SMichael Walle 	base = devm_ioremap_resource(dev, res);
449cd10205SMichael Walle 	if (IS_ERR(base))
459cd10205SMichael Walle 		return PTR_ERR(base);
469cd10205SMichael Walle 
479cd10205SMichael Walle 	spin_lock_init(&sai_clk->lock);
489cd10205SMichael Walle 
499cd10205SMichael Walle 	sai_clk->gate.reg = base + I2S_CSR;
509cd10205SMichael Walle 	sai_clk->gate.bit_idx = CSR_BCE_BIT;
519cd10205SMichael Walle 	sai_clk->gate.lock = &sai_clk->lock;
529cd10205SMichael Walle 
539cd10205SMichael Walle 	sai_clk->div.reg = base + I2S_CR2;
549cd10205SMichael Walle 	sai_clk->div.shift = CR2_DIV_SHIFT;
559cd10205SMichael Walle 	sai_clk->div.width = CR2_DIV_WIDTH;
569cd10205SMichael Walle 	sai_clk->div.lock = &sai_clk->lock;
579cd10205SMichael Walle 
589cd10205SMichael Walle 	/* set clock direction, we are the BCLK master */
599cd10205SMichael Walle 	writel(CR2_BCD, base + I2S_CR2);
609cd10205SMichael Walle 
61*fb871515SMichael Walle 	hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
629cd10205SMichael Walle 						  &pdata, 1, NULL, NULL,
639cd10205SMichael Walle 						  &sai_clk->div.hw,
649cd10205SMichael Walle 						  &clk_divider_ops,
659cd10205SMichael Walle 						  &sai_clk->gate.hw,
669cd10205SMichael Walle 						  &clk_gate_ops,
679cd10205SMichael Walle 						  CLK_SET_RATE_GATE);
689cd10205SMichael Walle 	if (IS_ERR(hw))
699cd10205SMichael Walle 		return PTR_ERR(hw);
709cd10205SMichael Walle 
719cd10205SMichael Walle 	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
729cd10205SMichael Walle }
739cd10205SMichael Walle 
749cd10205SMichael Walle static const struct of_device_id of_fsl_sai_clk_ids[] = {
759cd10205SMichael Walle 	{ .compatible = "fsl,vf610-sai-clock" },
769cd10205SMichael Walle 	{ }
779cd10205SMichael Walle };
789cd10205SMichael Walle MODULE_DEVICE_TABLE(of, of_fsl_sai_clk_ids);
799cd10205SMichael Walle 
809cd10205SMichael Walle static struct platform_driver fsl_sai_clk_driver = {
819cd10205SMichael Walle 	.probe = fsl_sai_clk_probe,
829cd10205SMichael Walle 	.driver		= {
839cd10205SMichael Walle 		.name	= "fsl-sai-clk",
849cd10205SMichael Walle 		.of_match_table = of_fsl_sai_clk_ids,
859cd10205SMichael Walle 	},
869cd10205SMichael Walle };
879cd10205SMichael Walle module_platform_driver(fsl_sai_clk_driver);
889cd10205SMichael Walle 
899cd10205SMichael Walle MODULE_DESCRIPTION("Freescale SAI bitclock-as-a-clock driver");
909cd10205SMichael Walle MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
919cd10205SMichael Walle MODULE_LICENSE("GPL");
929cd10205SMichael Walle MODULE_ALIAS("platform:fsl-sai-clk");
93