1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
/*
* OMAP LDO control and configuration
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/cpu.h>
#include "control.h"
#include "pm.h"
#define OMAP4_DPLL_MPU_TRIMMED_VAL_2P4 (0x1 << 18)
#define OMAP4_DPLL_MPU_TRIMMED_VAL_3P0 (0x3 << 18)
#define OMAP4_DPLL_MPU_TRIMMED_MASK (BIT(19) | BIT(18))
static bool bgap_trim_sw_overide;
static bool dpll_trim_override;
/**
* omap4_ldo_trim_configure() - Handle device trim variance
*
* Few of the silicon out of the fab come out without trim parameters
* efused in. These need some software support to allow the device to
* function normally. Handle these silicon quirks here.
*/
int omap4_ldo_trim_configure(void)
{
u32 val;
/* if not trimmed, we set force overide, insted of efuse. */
if (bgap_trim_sw_overide) {
/* Fill in recommended values */
val = 0x0f << OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT;
val |= OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK;
val |= 0x1 << OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT;
val |= OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK;
omap_ctrl_writel(val,
OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL);
omap_ctrl_writel(val,
OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL);
omap_ctrl_writel(val,
OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL);
}
/* For all trimmed and untrimmed write value as per recomendation */
val = 0x10 << OMAP4_AVDAC_TRIM_BYTE0_SHIFT;
val |= 0x01 << OMAP4_AVDAC_TRIM_BYTE1_SHIFT;
val |= 0x4d << OMAP4_AVDAC_TRIM_BYTE2_SHIFT;
val |= 0x1C << OMAP4_AVDAC_TRIM_BYTE3_SHIFT;
omap4_ctrl_pad_writel(val,
OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1);
/*
* For all ESx.y trimmed and untrimmed units LPDDR IO and
* Smart IO override efuse.
*/
val = OMAP4_LPDDR2_PTV_P5_MASK | OMAP4_LPDDR2_PTV_N5_MASK;
omap4_ctrl_pad_writel(val, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2);
/* Required for DPLL_MPU to lock at 2.4 GHz */
if (dpll_trim_override)
omap_ctrl_writel(0x29, OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0);
return 0;
}
/**
* omap4460_mpu_dpll_trim_override() - provide a selective s/w trim overide
*/
static __init void omap4460_mpu_dpll_trim_override(void)
{
u32 val;
val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1) &
OMAP4_DPLL_MPU_TRIMMED_MASK;
switch (val) {
case OMAP4_DPLL_MPU_TRIMMED_VAL_3P0:
/* all ok.. */
break;
case OMAP4_DPLL_MPU_TRIMMED_VAL_2P4:
/* Cross check! */
if (omap4_has_mpu_1_5ghz()) {
WARN(1, "%s: OMAP is 1.5GHz capable, trimmed=1.2GHz!\n",
__func__);
}
break;
default:
WARN(1, "%s: UNKNOWN TRIM:0x%08x, using s/w override\n",
__func__, val);
/* fall through and use override */
case 0:
/*
* For PRE_RTP devices: Not trimmed, use s/w override!
* We only support unto 1.2GHz with s/w override,
* so just give a gentle warning if higher opp is attempted
*/
dpll_trim_override = true;
/* Confirm */
if (omap4_has_mpu_1_5ghz()) {
pr_err("%s: OMAP is 1.5GHz capable, s/w trim=1.2GHz!\n",
__func__);
}
break;
}
}
static __init int omap4_ldo_trim_init(void)
{
u32 bgap_trimmed = 0;
/* Applicable only for OMAP4 */
if (!cpu_is_omap44xx())
return 0;
/*
* Some ES2.2 efuse values for BGAP and SLDO trim
* are not programmed. For these units
* 1. we can set overide mode for SLDO trim,
* and program the max multiplication factor, to ensure
* high enough voltage on SLDO output.
* 2. trim VDAC value for TV output as per recomendation
*/
if (omap_rev() >= CHIP_IS_OMAP4430ES2_2)
bgap_trimmed = omap_ctrl_readl(
OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP);
bgap_trimmed &= OMAP4_STD_FUSE_OPP_BGAP_MASK_LSB;
/* if not trimmed, we set force overide, insted of efuse. */
if (!bgap_trimmed)
bgap_trim_sw_overide = true;
/* If not already trimmed, use s/w override */
if (cpu_is_omap446x())
omap4460_mpu_dpll_trim_override();
return omap4_ldo_trim_configure();
}
arch_initcall(omap4_ldo_trim_init);
|