gxbb-aoclk.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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/mfd/syscon.h>
  60. #include <linux/regmap.h>
  61. #include <linux/init.h>
  62. #include <linux/delay.h>
  63. #include <dt-bindings/clock/gxbb-aoclkc.h>
  64. #include <dt-bindings/reset/gxbb-aoclkc.h>
  65. #include "clk-regmap.h"
  66. #include "gxbb-aoclk.h"
  67. struct gxbb_aoclk_reset_controller {
  68. struct reset_controller_dev reset;
  69. unsigned int *data;
  70. struct regmap *regmap;
  71. };
  72. static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev,
  73. unsigned long id)
  74. {
  75. struct gxbb_aoclk_reset_controller *reset =
  76. container_of(rcdev, struct gxbb_aoclk_reset_controller, reset);
  77. return regmap_write(reset->regmap, AO_RTI_GEN_CNTL_REG0,
  78. BIT(reset->data[id]));
  79. }
  80. static const struct reset_control_ops gxbb_aoclk_reset_ops = {
  81. .reset = gxbb_aoclk_do_reset,
  82. };
  83. #define GXBB_AO_GATE(_name, _bit) \
  84. static struct clk_regmap _name##_ao = { \
  85. .data = &(struct clk_regmap_gate_data) { \
  86. .offset = AO_RTI_GEN_CNTL_REG0, \
  87. .bit_idx = (_bit), \
  88. }, \
  89. .hw.init = &(struct clk_init_data) { \
  90. .name = #_name "_ao", \
  91. .ops = &clk_regmap_gate_ops, \
  92. .parent_names = (const char *[]){ "clk81" }, \
  93. .num_parents = 1, \
  94. .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
  95. }, \
  96. }
  97. GXBB_AO_GATE(remote, 0);
  98. GXBB_AO_GATE(i2c_master, 1);
  99. GXBB_AO_GATE(i2c_slave, 2);
  100. GXBB_AO_GATE(uart1, 3);
  101. GXBB_AO_GATE(uart2, 5);
  102. GXBB_AO_GATE(ir_blaster, 6);
  103. static struct aoclk_cec_32k cec_32k_ao = {
  104. .hw.init = &(struct clk_init_data) {
  105. .name = "cec_32k_ao",
  106. .ops = &meson_aoclk_cec_32k_ops,
  107. .parent_names = (const char *[]){ "xtal" },
  108. .num_parents = 1,
  109. .flags = CLK_IGNORE_UNUSED,
  110. },
  111. };
  112. static unsigned int gxbb_aoclk_reset[] = {
  113. [RESET_AO_REMOTE] = 16,
  114. [RESET_AO_I2C_MASTER] = 18,
  115. [RESET_AO_I2C_SLAVE] = 19,
  116. [RESET_AO_UART1] = 17,
  117. [RESET_AO_UART2] = 22,
  118. [RESET_AO_IR_BLASTER] = 23,
  119. };
  120. static struct clk_regmap *gxbb_aoclk_gate[] = {
  121. [CLKID_AO_REMOTE] = &remote_ao,
  122. [CLKID_AO_I2C_MASTER] = &i2c_master_ao,
  123. [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
  124. [CLKID_AO_UART1] = &uart1_ao,
  125. [CLKID_AO_UART2] = &uart2_ao,
  126. [CLKID_AO_IR_BLASTER] = &ir_blaster_ao,
  127. };
  128. static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
  129. .hws = {
  130. [CLKID_AO_REMOTE] = &remote_ao.hw,
  131. [CLKID_AO_I2C_MASTER] = &i2c_master_ao.hw,
  132. [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao.hw,
  133. [CLKID_AO_UART1] = &uart1_ao.hw,
  134. [CLKID_AO_UART2] = &uart2_ao.hw,
  135. [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
  136. [CLKID_AO_CEC_32K] = &cec_32k_ao.hw,
  137. },
  138. .num = 7,
  139. };
  140. static int gxbb_aoclkc_probe(struct platform_device *pdev)
  141. {
  142. struct gxbb_aoclk_reset_controller *rstc;
  143. struct device *dev = &pdev->dev;
  144. struct regmap *regmap;
  145. int ret, clkid;
  146. rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL);
  147. if (!rstc)
  148. return -ENOMEM;
  149. regmap = syscon_node_to_regmap(of_get_parent(dev->of_node));
  150. if (IS_ERR(regmap)) {
  151. dev_err(dev, "failed to get regmap\n");
  152. return -ENODEV;
  153. }
  154. /* Reset Controller */
  155. rstc->regmap = regmap;
  156. rstc->data = gxbb_aoclk_reset;
  157. rstc->reset.ops = &gxbb_aoclk_reset_ops;
  158. rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset);
  159. rstc->reset.of_node = dev->of_node;
  160. ret = devm_reset_controller_register(dev, &rstc->reset);
  161. /*
  162. * Populate regmap and register all clks
  163. */
  164. for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) {
  165. gxbb_aoclk_gate[clkid]->map = regmap;
  166. ret = devm_clk_hw_register(dev,
  167. gxbb_aoclk_onecell_data.hws[clkid]);
  168. if (ret)
  169. return ret;
  170. }
  171. /* Specific clocks */
  172. cec_32k_ao.regmap = regmap;
  173. ret = devm_clk_hw_register(dev, &cec_32k_ao.hw);
  174. if (ret)
  175. return ret;
  176. return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
  177. &gxbb_aoclk_onecell_data);
  178. }
  179. static const struct of_device_id gxbb_aoclkc_match_table[] = {
  180. { .compatible = "amlogic,meson-gx-aoclkc" },
  181. { }
  182. };
  183. static struct platform_driver gxbb_aoclkc_driver = {
  184. .probe = gxbb_aoclkc_probe,
  185. .driver = {
  186. .name = "gxbb-aoclkc",
  187. .of_match_table = gxbb_aoclkc_match_table,
  188. },
  189. };
  190. builtin_platform_driver(gxbb_aoclkc_driver);