gxbb-aoclk.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * This file is provided under a dual BSD/GPLv2 license. When using or
  3. * redistributing this file, you may do so under either license.
  4. *
  5. * GPL LICENSE SUMMARY
  6. *
  7. * Copyright (c) 2016 BayLibre, SAS.
  8. * Author: Neil Armstrong <narmstrong@baylibre.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of version 2 of the GNU General Public License as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  21. * The full GNU General Public License is included in this distribution
  22. * in the file called COPYING.
  23. *
  24. * BSD LICENSE
  25. *
  26. * Copyright (c) 2016 BayLibre, SAS.
  27. * Author: Neil Armstrong <narmstrong@baylibre.com>
  28. *
  29. * Redistribution and use in source and binary forms, with or without
  30. * modification, are permitted provided that the following conditions
  31. * are met:
  32. *
  33. * * Redistributions of source code must retain the above copyright
  34. * notice, this list of conditions and the following disclaimer.
  35. * * Redistributions in binary form must reproduce the above copyright
  36. * notice, this list of conditions and the following disclaimer in
  37. * the documentation and/or other materials provided with the
  38. * distribution.
  39. * * Neither the name of Intel Corporation nor the names of its
  40. * contributors may be used to endorse or promote products derived
  41. * from this software without specific prior written permission.
  42. *
  43. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  44. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  45. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  46. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  47. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  48. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  49. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  50. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  51. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  52. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  53. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  54. */
  55. #include <linux/clk-provider.h>
  56. #include <linux/of_address.h>
  57. #include <linux/platform_device.h>
  58. #include <linux/reset-controller.h>
  59. #include <linux/init.h>
  60. #include <dt-bindings/clock/gxbb-aoclkc.h>
  61. #include <dt-bindings/reset/gxbb-aoclkc.h>
  62. static DEFINE_SPINLOCK(gxbb_aoclk_lock);
  63. struct gxbb_aoclk_reset_controller {
  64. struct reset_controller_dev reset;
  65. unsigned int *data;
  66. void __iomem *base;
  67. };
  68. static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev,
  69. unsigned long id)
  70. {
  71. struct gxbb_aoclk_reset_controller *reset =
  72. container_of(rcdev, struct gxbb_aoclk_reset_controller, reset);
  73. writel(BIT(reset->data[id]), reset->base);
  74. return 0;
  75. }
  76. static const struct reset_control_ops gxbb_aoclk_reset_ops = {
  77. .reset = gxbb_aoclk_do_reset,
  78. };
  79. #define GXBB_AO_GATE(_name, _bit) \
  80. static struct clk_gate _name##_ao = { \
  81. .reg = (void __iomem *)0, \
  82. .bit_idx = (_bit), \
  83. .lock = &gxbb_aoclk_lock, \
  84. .hw.init = &(struct clk_init_data) { \
  85. .name = #_name "_ao", \
  86. .ops = &clk_gate_ops, \
  87. .parent_names = (const char *[]){ "clk81" }, \
  88. .num_parents = 1, \
  89. .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
  90. }, \
  91. }
  92. GXBB_AO_GATE(remote, 0);
  93. GXBB_AO_GATE(i2c_master, 1);
  94. GXBB_AO_GATE(i2c_slave, 2);
  95. GXBB_AO_GATE(uart1, 3);
  96. GXBB_AO_GATE(uart2, 5);
  97. GXBB_AO_GATE(ir_blaster, 6);
  98. static unsigned int gxbb_aoclk_reset[] = {
  99. [RESET_AO_REMOTE] = 16,
  100. [RESET_AO_I2C_MASTER] = 18,
  101. [RESET_AO_I2C_SLAVE] = 19,
  102. [RESET_AO_UART1] = 17,
  103. [RESET_AO_UART2] = 22,
  104. [RESET_AO_IR_BLASTER] = 23,
  105. };
  106. static struct clk_gate *gxbb_aoclk_gate[] = {
  107. [CLKID_AO_REMOTE] = &remote_ao,
  108. [CLKID_AO_I2C_MASTER] = &i2c_master_ao,
  109. [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
  110. [CLKID_AO_UART1] = &uart1_ao,
  111. [CLKID_AO_UART2] = &uart2_ao,
  112. [CLKID_AO_IR_BLASTER] = &ir_blaster_ao,
  113. };
  114. static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
  115. .hws = {
  116. [CLKID_AO_REMOTE] = &remote_ao.hw,
  117. [CLKID_AO_I2C_MASTER] = &i2c_master_ao.hw,
  118. [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao.hw,
  119. [CLKID_AO_UART1] = &uart1_ao.hw,
  120. [CLKID_AO_UART2] = &uart2_ao.hw,
  121. [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
  122. },
  123. .num = ARRAY_SIZE(gxbb_aoclk_gate),
  124. };
  125. static int gxbb_aoclkc_probe(struct platform_device *pdev)
  126. {
  127. struct resource *res;
  128. void __iomem *base;
  129. int ret, clkid;
  130. struct device *dev = &pdev->dev;
  131. struct gxbb_aoclk_reset_controller *rstc;
  132. rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL);
  133. if (!rstc)
  134. return -ENOMEM;
  135. /* Generic clocks */
  136. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  137. base = devm_ioremap_resource(dev, res);
  138. if (IS_ERR(base))
  139. return PTR_ERR(base);
  140. /* Reset Controller */
  141. rstc->base = base;
  142. rstc->data = gxbb_aoclk_reset;
  143. rstc->reset.ops = &gxbb_aoclk_reset_ops;
  144. rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset);
  145. rstc->reset.of_node = dev->of_node;
  146. ret = devm_reset_controller_register(dev, &rstc->reset);
  147. /*
  148. * Populate base address and register all clks
  149. */
  150. for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) {
  151. gxbb_aoclk_gate[clkid]->reg = base;
  152. ret = devm_clk_hw_register(dev,
  153. gxbb_aoclk_onecell_data.hws[clkid]);
  154. if (ret)
  155. return ret;
  156. }
  157. return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
  158. &gxbb_aoclk_onecell_data);
  159. }
  160. static const struct of_device_id gxbb_aoclkc_match_table[] = {
  161. { .compatible = "amlogic,gxbb-aoclkc" },
  162. { }
  163. };
  164. static struct platform_driver gxbb_aoclkc_driver = {
  165. .probe = gxbb_aoclkc_probe,
  166. .driver = {
  167. .name = "gxbb-aoclkc",
  168. .of_match_table = gxbb_aoclkc_match_table,
  169. },
  170. };
  171. builtin_platform_driver(gxbb_aoclkc_driver);