1 /* 2 * ctu.c 3 * 4 * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 #include "rsnd.h" 11 12 #define CTU_NAME_SIZE 16 13 #define CTU_NAME "ctu" 14 15 struct rsnd_ctu { 16 struct rsnd_mod mod; 17 }; 18 19 #define rsnd_ctu_nr(priv) ((priv)->ctu_nr) 20 #define for_each_rsnd_ctu(pos, priv, i) \ 21 for ((i) = 0; \ 22 ((i) < rsnd_ctu_nr(priv)) && \ 23 ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \ 24 i++) 25 26 #define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id) 27 #define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1) 28 #define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0) 29 static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) 30 { 31 rsnd_mod_write(mod, CTU_CTUIR, enable); 32 } 33 34 static int rsnd_ctu_probe_(struct rsnd_mod *mod, 35 struct rsnd_dai_stream *io, 36 struct rsnd_priv *priv) 37 { 38 return rsnd_cmd_attach(io, rsnd_mod_id(mod) / 4); 39 } 40 41 static int rsnd_ctu_init(struct rsnd_mod *mod, 42 struct rsnd_dai_stream *io, 43 struct rsnd_priv *priv) 44 { 45 rsnd_mod_power_on(mod); 46 47 rsnd_ctu_initialize_lock(mod); 48 49 rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io)); 50 51 rsnd_ctu_initialize_unlock(mod); 52 53 return 0; 54 } 55 56 static int rsnd_ctu_quit(struct rsnd_mod *mod, 57 struct rsnd_dai_stream *io, 58 struct rsnd_priv *priv) 59 { 60 rsnd_mod_power_off(mod); 61 62 return 0; 63 } 64 65 static struct rsnd_mod_ops rsnd_ctu_ops = { 66 .name = CTU_NAME, 67 .probe = rsnd_ctu_probe_, 68 .init = rsnd_ctu_init, 69 .quit = rsnd_ctu_quit, 70 }; 71 72 struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id) 73 { 74 if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv))) 75 id = 0; 76 77 return rsnd_mod_get(rsnd_ctu_get(priv, id)); 78 } 79 80 int rsnd_ctu_probe(struct rsnd_priv *priv) 81 { 82 struct device_node *node; 83 struct device_node *np; 84 struct device *dev = rsnd_priv_to_dev(priv); 85 struct rsnd_ctu *ctu; 86 struct clk *clk; 87 char name[CTU_NAME_SIZE]; 88 int i, nr, ret; 89 90 /* This driver doesn't support Gen1 at this point */ 91 if (rsnd_is_gen1(priv)) 92 return 0; 93 94 node = rsnd_ctu_of_node(priv); 95 if (!node) 96 return 0; /* not used is not error */ 97 98 nr = of_get_child_count(node); 99 if (!nr) { 100 ret = -EINVAL; 101 goto rsnd_ctu_probe_done; 102 } 103 104 ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL); 105 if (!ctu) { 106 ret = -ENOMEM; 107 goto rsnd_ctu_probe_done; 108 } 109 110 priv->ctu_nr = nr; 111 priv->ctu = ctu; 112 113 i = 0; 114 ret = 0; 115 for_each_child_of_node(node, np) { 116 ctu = rsnd_ctu_get(priv, i); 117 118 /* 119 * CTU00, CTU01, CTU02, CTU03 => CTU0 120 * CTU10, CTU11, CTU12, CTU13 => CTU1 121 */ 122 snprintf(name, CTU_NAME_SIZE, "%s.%d", 123 CTU_NAME, i / 4); 124 125 clk = devm_clk_get(dev, name); 126 if (IS_ERR(clk)) { 127 ret = PTR_ERR(clk); 128 goto rsnd_ctu_probe_done; 129 } 130 131 ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, 132 clk, RSND_MOD_CTU, i); 133 if (ret) 134 goto rsnd_ctu_probe_done; 135 136 i++; 137 } 138 139 140 rsnd_ctu_probe_done: 141 of_node_put(node); 142 143 return ret; 144 } 145 146 void rsnd_ctu_remove(struct rsnd_priv *priv) 147 { 148 struct rsnd_ctu *ctu; 149 int i; 150 151 for_each_rsnd_ctu(ctu, priv, i) { 152 rsnd_mod_quit(rsnd_mod_get(ctu)); 153 } 154 } 155