0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/errno.h>
0014 #include <linux/bug.h>
0015 #include <linux/of.h>
0016 #include <linux/of_address.h>
0017
0018 #include "cm2xxx.h"
0019 #include "cm3xxx.h"
0020 #include "cm33xx.h"
0021 #include "cm44xx.h"
0022 #include "clock.h"
0023
0024
0025
0026
0027
0028 static struct cm_ll_data null_cm_ll_data;
0029 static const struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
0030
0031
0032 struct omap_domain_base cm_base;
0033
0034
0035 struct omap_domain_base cm2_base;
0036
0037 #define CM_NO_CLOCKS 0x1
0038 #define CM_SINGLE_INSTANCE 0x2
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
0053 u8 *idlest_reg_id)
0054 {
0055 int ret;
0056 if (!cm_ll_data->split_idlest_reg) {
0057 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
0058 __func__);
0059 return -EINVAL;
0060 }
0061
0062 ret = cm_ll_data->split_idlest_reg(idlest_reg, prcm_inst,
0063 idlest_reg_id);
0064 *prcm_inst -= cm_base.offset;
0065 return ret;
0066 }
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
0082 u8 idlest_shift)
0083 {
0084 if (!cm_ll_data->wait_module_ready) {
0085 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
0086 __func__);
0087 return -EINVAL;
0088 }
0089
0090 return cm_ll_data->wait_module_ready(part, prcm_mod, idlest_reg,
0091 idlest_shift);
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 int omap_cm_wait_module_idle(u8 part, s16 prcm_mod, u16 idlest_reg,
0108 u8 idlest_shift)
0109 {
0110 if (!cm_ll_data->wait_module_idle) {
0111 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
0112 __func__);
0113 return -EINVAL;
0114 }
0115
0116 return cm_ll_data->wait_module_idle(part, prcm_mod, idlest_reg,
0117 idlest_shift);
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 int omap_cm_module_enable(u8 mode, u8 part, u16 inst, u16 clkctrl_offs)
0132 {
0133 if (!cm_ll_data->module_enable) {
0134 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
0135 __func__);
0136 return -EINVAL;
0137 }
0138
0139 cm_ll_data->module_enable(mode, part, inst, clkctrl_offs);
0140 return 0;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
0154 {
0155 if (!cm_ll_data->module_disable) {
0156 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
0157 __func__);
0158 return -EINVAL;
0159 }
0160
0161 cm_ll_data->module_disable(part, inst, clkctrl_offs);
0162 return 0;
0163 }
0164
0165 u32 omap_cm_xlate_clkctrl(u8 part, u16 inst, u16 clkctrl_offs)
0166 {
0167 if (!cm_ll_data->xlate_clkctrl) {
0168 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
0169 __func__);
0170 return 0;
0171 }
0172 return cm_ll_data->xlate_clkctrl(part, inst, clkctrl_offs);
0173 }
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 int cm_register(const struct cm_ll_data *cld)
0187 {
0188 if (!cld)
0189 return -EINVAL;
0190
0191 if (cm_ll_data != &null_cm_ll_data)
0192 return -EEXIST;
0193
0194 cm_ll_data = cld;
0195
0196 return 0;
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 int cm_unregister(const struct cm_ll_data *cld)
0211 {
0212 if (!cld || cm_ll_data != cld)
0213 return -EINVAL;
0214
0215 cm_ll_data = &null_cm_ll_data;
0216
0217 return 0;
0218 }
0219
0220 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
0221 defined(CONFIG_SOC_DRA7XX)
0222 static struct omap_prcm_init_data cm_data __initdata = {
0223 .index = TI_CLKM_CM,
0224 .init = omap4_cm_init,
0225 };
0226
0227 static struct omap_prcm_init_data cm2_data __initdata = {
0228 .index = TI_CLKM_CM2,
0229 .init = omap4_cm_init,
0230 };
0231 #endif
0232
0233 #ifdef CONFIG_ARCH_OMAP2
0234 static struct omap_prcm_init_data omap2_prcm_data __initdata = {
0235 .index = TI_CLKM_CM,
0236 .init = omap2xxx_cm_init,
0237 .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
0238 };
0239 #endif
0240
0241 #ifdef CONFIG_ARCH_OMAP3
0242 static struct omap_prcm_init_data omap3_cm_data __initdata = {
0243 .index = TI_CLKM_CM,
0244 .init = omap3xxx_cm_init,
0245 .flags = CM_SINGLE_INSTANCE,
0246
0247
0248
0249
0250
0251 .offset = -OMAP3430_IVA2_MOD,
0252 };
0253 #endif
0254
0255 #if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_TI81XX)
0256 static struct omap_prcm_init_data am3_prcm_data __initdata = {
0257 .index = TI_CLKM_CM,
0258 .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
0259 .init = am33xx_cm_init,
0260 };
0261 #endif
0262
0263 #ifdef CONFIG_SOC_AM43XX
0264 static struct omap_prcm_init_data am4_prcm_data __initdata = {
0265 .index = TI_CLKM_CM,
0266 .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
0267 .init = omap4_cm_init,
0268 };
0269 #endif
0270
0271 static const struct of_device_id omap_cm_dt_match_table[] __initconst = {
0272 #ifdef CONFIG_ARCH_OMAP2
0273 { .compatible = "ti,omap2-prcm", .data = &omap2_prcm_data },
0274 #endif
0275 #ifdef CONFIG_ARCH_OMAP3
0276 { .compatible = "ti,omap3-cm", .data = &omap3_cm_data },
0277 #endif
0278 #ifdef CONFIG_ARCH_OMAP4
0279 { .compatible = "ti,omap4-cm1", .data = &cm_data },
0280 { .compatible = "ti,omap4-cm2", .data = &cm2_data },
0281 #endif
0282 #ifdef CONFIG_SOC_OMAP5
0283 { .compatible = "ti,omap5-cm-core-aon", .data = &cm_data },
0284 { .compatible = "ti,omap5-cm-core", .data = &cm2_data },
0285 #endif
0286 #ifdef CONFIG_SOC_DRA7XX
0287 { .compatible = "ti,dra7-cm-core-aon", .data = &cm_data },
0288 { .compatible = "ti,dra7-cm-core", .data = &cm2_data },
0289 #endif
0290 #ifdef CONFIG_SOC_AM33XX
0291 { .compatible = "ti,am3-prcm", .data = &am3_prcm_data },
0292 #endif
0293 #ifdef CONFIG_SOC_AM43XX
0294 { .compatible = "ti,am4-prcm", .data = &am4_prcm_data },
0295 #endif
0296 #ifdef CONFIG_SOC_TI81XX
0297 { .compatible = "ti,dm814-prcm", .data = &am3_prcm_data },
0298 { .compatible = "ti,dm816-prcm", .data = &am3_prcm_data },
0299 #endif
0300 { }
0301 };
0302
0303
0304
0305
0306
0307
0308
0309
0310 int __init omap2_cm_base_init(void)
0311 {
0312 struct device_node *np;
0313 const struct of_device_id *match;
0314 struct omap_prcm_init_data *data;
0315 struct resource res;
0316 int ret;
0317 struct omap_domain_base *mem = NULL;
0318
0319 for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
0320 data = (struct omap_prcm_init_data *)match->data;
0321
0322 ret = of_address_to_resource(np, 0, &res);
0323 if (ret) {
0324 of_node_put(np);
0325 return ret;
0326 }
0327
0328 if (data->index == TI_CLKM_CM)
0329 mem = &cm_base;
0330
0331 if (data->index == TI_CLKM_CM2)
0332 mem = &cm2_base;
0333
0334 data->mem = ioremap(res.start, resource_size(&res));
0335
0336 if (mem) {
0337 mem->pa = res.start + data->offset;
0338 mem->va = data->mem + data->offset;
0339 mem->offset = data->offset;
0340 }
0341
0342 data->np = np;
0343
0344 if (data->init && (data->flags & CM_SINGLE_INSTANCE ||
0345 (cm_base.va && cm2_base.va)))
0346 data->init(data);
0347 }
0348
0349 return 0;
0350 }
0351
0352
0353
0354
0355
0356
0357
0358 int __init omap_cm_init(void)
0359 {
0360 struct device_node *np;
0361 const struct of_device_id *match;
0362 const struct omap_prcm_init_data *data;
0363 int ret;
0364
0365 for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
0366 data = match->data;
0367
0368 if (data->flags & CM_NO_CLOCKS)
0369 continue;
0370
0371 ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
0372 if (ret) {
0373 of_node_put(np);
0374 return ret;
0375 }
0376 }
0377
0378 return 0;
0379 }