clk-fsl-sai.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Freescale SAI BCLK as a generic clock driver
  4. *
  5. * Copyright 2020 Michael Walle <michael@walle.cc>
  6. */
  7. #include <linux/module.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/clk-provider.h>
  10. #include <linux/err.h>
  11. #include <linux/of.h>
  12. #include <linux/of_address.h>
  13. #include <linux/slab.h>
  14. #define I2S_CSR 0x00
  15. #define I2S_CR2 0x08
  16. #define CSR_BCE_BIT 28
  17. #define CR2_BCD BIT(24)
  18. #define CR2_DIV_SHIFT 0
  19. #define CR2_DIV_WIDTH 8
  20. struct fsl_sai_clk {
  21. struct clk_divider div;
  22. struct clk_gate gate;
  23. spinlock_t lock;
  24. };
  25. static int fsl_sai_clk_probe(struct platform_device *pdev)
  26. {
  27. struct device *dev = &pdev->dev;
  28. struct fsl_sai_clk *sai_clk;
  29. struct clk_parent_data pdata = { .index = 0 };
  30. void __iomem *base;
  31. struct clk_hw *hw;
  32. sai_clk = devm_kzalloc(dev, sizeof(*sai_clk), GFP_KERNEL);
  33. if (!sai_clk)
  34. return -ENOMEM;
  35. base = devm_platform_ioremap_resource(pdev, 0);
  36. if (IS_ERR(base))
  37. return PTR_ERR(base);
  38. spin_lock_init(&sai_clk->lock);
  39. sai_clk->gate.reg = base + I2S_CSR;
  40. sai_clk->gate.bit_idx = CSR_BCE_BIT;
  41. sai_clk->gate.lock = &sai_clk->lock;
  42. sai_clk->div.reg = base + I2S_CR2;
  43. sai_clk->div.shift = CR2_DIV_SHIFT;
  44. sai_clk->div.width = CR2_DIV_WIDTH;
  45. sai_clk->div.lock = &sai_clk->lock;
  46. /* set clock direction, we are the BCLK master */
  47. writel(CR2_BCD, base + I2S_CR2);
  48. hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
  49. &pdata, 1, NULL, NULL,
  50. &sai_clk->div.hw,
  51. &clk_divider_ops,
  52. &sai_clk->gate.hw,
  53. &clk_gate_ops,
  54. CLK_SET_RATE_GATE);
  55. if (IS_ERR(hw))
  56. return PTR_ERR(hw);
  57. return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
  58. }
  59. static const struct of_device_id of_fsl_sai_clk_ids[] = {
  60. { .compatible = "fsl,vf610-sai-clock" },
  61. { }
  62. };
  63. MODULE_DEVICE_TABLE(of, of_fsl_sai_clk_ids);
  64. static struct platform_driver fsl_sai_clk_driver = {
  65. .probe = fsl_sai_clk_probe,
  66. .driver = {
  67. .name = "fsl-sai-clk",
  68. .of_match_table = of_fsl_sai_clk_ids,
  69. },
  70. };
  71. module_platform_driver(fsl_sai_clk_driver);
  72. MODULE_DESCRIPTION("Freescale SAI bitclock-as-a-clock driver");
  73. MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
  74. MODULE_ALIAS("platform:fsl-sai-clk");