1 // SPDX-License-Identifier: GPL-2.0-only
3 * OMAP3/OMAP4 smartreflex device file
5 * Author: Thara Gopinath <thara@ti.com>
7 * Based originally on code from smartreflex.c
8 * Copyright (C) 2010 Texas Instruments, Inc.
9 * Thara Gopinath <thara@ti.com>
11 * Copyright (C) 2008 Nokia Corporation
14 * Copyright (C) 2007 Texas Instruments, Inc.
15 * Lesly A M <x0080970@ti.com>
17 #include <linux/power/smartreflex.h>
19 #include <linux/err.h>
20 #include <linux/slab.h>
24 #include "omap_device.h"
29 /* Read EFUSE values from control registers for OMAP3430 */
30 static void __init
sr_set_nvalues(struct omap_volt_data
*volt_data
,
31 struct omap_sr_data
*sr_data
)
33 struct omap_sr_nvalue_table
*nvalue_table
;
36 sr_data
->nvalue_count
= 0;
37 sr_data
->nvalue_table
= NULL
;
39 while (volt_data
[count
].volt_nominal
)
42 nvalue_table
= kcalloc(count
, sizeof(*nvalue_table
), GFP_KERNEL
);
46 for (i
= 0, j
= 0; i
< count
; i
++) {
50 * In OMAP4 the efuse registers are 24 bit aligned.
51 * A readl_relaxed will fail for non-32 bit aligned address
52 * and hence the 8-bit read and shift.
54 if (cpu_is_omap44xx()) {
55 u16 offset
= volt_data
[i
].sr_efuse_offs
;
57 v
= omap_ctrl_readb(offset
) |
58 omap_ctrl_readb(offset
+ 1) << 8 |
59 omap_ctrl_readb(offset
+ 2) << 16;
61 v
= omap_ctrl_readl(volt_data
[i
].sr_efuse_offs
);
65 * Many OMAP SoCs don't have the eFuse values set.
66 * For example, pretty much all OMAP3xxx before
69 * XXX There needs to be some way for board files or
70 * userspace to add these in.
75 nvalue_table
[j
].nvalue
= v
;
76 nvalue_table
[j
].efuse_offs
= volt_data
[i
].sr_efuse_offs
;
77 nvalue_table
[j
].errminlimit
= volt_data
[i
].sr_errminlimit
;
78 nvalue_table
[j
].volt_nominal
= volt_data
[i
].volt_nominal
;
83 sr_data
->nvalue_table
= nvalue_table
;
84 sr_data
->nvalue_count
= j
;
87 extern struct omap_sr_data omap_sr_pdata
[];
89 static int __init
sr_init_by_name(const char *name
, const char *voltdm
)
91 struct omap_sr_data
*sr_data
= NULL
;
92 struct omap_volt_data
*volt_data
;
95 if (!strncmp(name
, "smartreflex_mpu_iva", 20) ||
96 !strncmp(name
, "smartreflex_mpu", 16))
97 sr_data
= &omap_sr_pdata
[OMAP_SR_MPU
];
98 else if (!strncmp(name
, "smartreflex_core", 17))
99 sr_data
= &omap_sr_pdata
[OMAP_SR_CORE
];
100 else if (!strncmp(name
, "smartreflex_iva", 16))
101 sr_data
= &omap_sr_pdata
[OMAP_SR_IVA
];
104 pr_err("%s: Unknown instance %s\n", __func__
, name
);
108 sr_data
->name
= name
;
109 if (cpu_is_omap343x())
110 sr_data
->ip_type
= 1;
112 sr_data
->ip_type
= 2;
113 sr_data
->senn_mod
= 0x1;
114 sr_data
->senp_mod
= 0x1;
116 if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
117 sr_data
->err_weight
= OMAP3430_SR_ERRWEIGHT
;
118 sr_data
->err_maxlimit
= OMAP3430_SR_ERRMAXLIMIT
;
119 sr_data
->accum_data
= OMAP3430_SR_ACCUMDATA
;
120 if (!(strcmp(sr_data
->name
, "smartreflex_mpu"))) {
121 sr_data
->senn_avgweight
= OMAP3430_SR1_SENNAVGWEIGHT
;
122 sr_data
->senp_avgweight
= OMAP3430_SR1_SENPAVGWEIGHT
;
124 sr_data
->senn_avgweight
= OMAP3430_SR2_SENNAVGWEIGHT
;
125 sr_data
->senp_avgweight
= OMAP3430_SR2_SENPAVGWEIGHT
;
129 sr_data
->voltdm
= voltdm_lookup(voltdm
);
130 if (!sr_data
->voltdm
) {
131 pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
136 omap_voltage_get_volttable(sr_data
->voltdm
, &volt_data
);
138 pr_err("%s: No Voltage table registered for VDD%d\n",
143 sr_set_nvalues(volt_data
, sr_data
);
151 #ifdef CONFIG_OMAP_HWMOD
152 static int __init
sr_dev_init(struct omap_hwmod
*oh
, void *user
)
154 struct omap_smartreflex_dev_attr
*sr_dev_attr
;
156 sr_dev_attr
= (struct omap_smartreflex_dev_attr
*)oh
->dev_attr
;
157 if (!sr_dev_attr
|| !sr_dev_attr
->sensor_voltdm_name
) {
158 pr_err("%s: No voltage domain specified for %s. Cannot initialize\n",
163 return sr_init_by_name(oh
->name
, sr_dev_attr
->sensor_voltdm_name
);
166 static int __init
sr_dev_init(struct omap_hwmod
*oh
, void *user
)
172 static const char * const omap4_sr_instances
[] = {
178 static const char * const dra7_sr_instances
[] = {
183 int __init
omap_devinit_smartreflex(void)
185 const char * const *sr_inst
= NULL
;
188 if (soc_is_omap44xx()) {
189 sr_inst
= omap4_sr_instances
;
190 nr_sr
= ARRAY_SIZE(omap4_sr_instances
);
192 } else if (soc_is_dra7xx()) {
193 sr_inst
= dra7_sr_instances
;
194 nr_sr
= ARRAY_SIZE(dra7_sr_instances
);
198 const char *name
, *voltdm
;
200 for (i
= 0; i
< nr_sr
; i
++) {
201 name
= kasprintf(GFP_KERNEL
, "smartreflex_%s", sr_inst
[i
]);
203 sr_init_by_name(name
, voltdm
);
209 return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init
, NULL
);