~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/arm/cpu/armv7/omap-common/pipe3-phy.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * TI PIPE3 PHY
 
3
 *
 
4
 * (C) Copyright 2013
 
5
 * Texas Instruments, <www.ti.com>
 
6
 *
 
7
 * SPDX-License-Identifier:     GPL-2.0+
 
8
 */
 
9
 
 
10
#include <common.h>
 
11
#include <sata.h>
 
12
#include <asm/arch/clock.h>
 
13
#include <asm/arch/sys_proto.h>
 
14
#include <asm/io.h>
 
15
#include <asm/errno.h>
 
16
#include "pipe3-phy.h"
 
17
 
 
18
/* PLLCTRL Registers */
 
19
#define PLL_STATUS              0x00000004
 
20
#define PLL_GO                  0x00000008
 
21
#define PLL_CONFIGURATION1      0x0000000C
 
22
#define PLL_CONFIGURATION2      0x00000010
 
23
#define PLL_CONFIGURATION3      0x00000014
 
24
#define PLL_CONFIGURATION4      0x00000020
 
25
 
 
26
#define PLL_REGM_MASK           0x001FFE00
 
27
#define PLL_REGM_SHIFT          9
 
28
#define PLL_REGM_F_MASK         0x0003FFFF
 
29
#define PLL_REGM_F_SHIFT        0
 
30
#define PLL_REGN_MASK           0x000001FE
 
31
#define PLL_REGN_SHIFT          1
 
32
#define PLL_SELFREQDCO_MASK     0x0000000E
 
33
#define PLL_SELFREQDCO_SHIFT    1
 
34
#define PLL_SD_MASK             0x0003FC00
 
35
#define PLL_SD_SHIFT            10
 
36
#define SET_PLL_GO              0x1
 
37
#define PLL_TICOPWDN            BIT(16)
 
38
#define PLL_LDOPWDN             BIT(15)
 
39
#define PLL_LOCK                0x2
 
40
#define PLL_IDLE                0x1
 
41
 
 
42
/* PHY POWER CONTROL Register */
 
43
#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK         0x003FC000
 
44
#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT        0xE
 
45
 
 
46
#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK        0xFFC00000
 
47
#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT       0x16
 
48
 
 
49
#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON       0x3
 
50
#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF      0x0
 
51
 
 
52
 
 
53
#define PLL_IDLE_TIME   100     /* in milliseconds */
 
54
#define PLL_LOCK_TIME   100     /* in milliseconds */
 
55
 
 
56
static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset)
 
57
{
 
58
        return __raw_readl(addr + offset);
 
59
}
 
60
 
 
61
static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset,
 
62
                u32 data)
 
63
{
 
64
        __raw_writel(data, addr + offset);
 
65
}
 
66
 
 
67
static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(struct omap_pipe3
 
68
                                                                        *pipe3)
 
69
{
 
70
        u32 rate;
 
71
        struct pipe3_dpll_map *dpll_map = pipe3->dpll_map;
 
72
 
 
73
        rate = get_sys_clk_freq();
 
74
 
 
75
        for (; dpll_map->rate; dpll_map++) {
 
76
                if (rate == dpll_map->rate)
 
77
                        return &dpll_map->params;
 
78
        }
 
79
 
 
80
        printf("%s: No DPLL configuration for %u Hz SYS CLK\n",
 
81
               __func__, rate);
 
82
        return NULL;
 
83
}
 
84
 
 
85
 
 
86
static int omap_pipe3_wait_lock(struct omap_pipe3 *phy)
 
87
{
 
88
        u32 val;
 
89
        int timeout = PLL_LOCK_TIME;
 
90
 
 
91
        do {
 
92
                mdelay(1);
 
93
                val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
 
94
                if (val & PLL_LOCK)
 
95
                        break;
 
96
        } while (--timeout);
 
97
 
 
98
        if (!(val & PLL_LOCK)) {
 
99
                printf("%s: DPLL failed to lock\n", __func__);
 
100
                return -EBUSY;
 
101
        }
 
102
 
 
103
        return 0;
 
104
}
 
105
 
 
106
static int omap_pipe3_dpll_program(struct omap_pipe3 *phy)
 
107
{
 
108
        u32                     val;
 
109
        struct pipe3_dpll_params *dpll_params;
 
110
 
 
111
        dpll_params = omap_pipe3_get_dpll_params(phy);
 
112
        if (!dpll_params) {
 
113
                printf("%s: Invalid DPLL parameters\n", __func__);
 
114
                return -EINVAL;
 
115
        }
 
116
 
 
117
        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
 
118
        val &= ~PLL_REGN_MASK;
 
119
        val |= dpll_params->n << PLL_REGN_SHIFT;
 
120
        omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
 
121
 
 
122
        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 
123
        val &= ~PLL_SELFREQDCO_MASK;
 
124
        val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
 
125
        omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
 
126
 
 
127
        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
 
128
        val &= ~PLL_REGM_MASK;
 
129
        val |= dpll_params->m << PLL_REGM_SHIFT;
 
130
        omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
 
131
 
 
132
        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
 
133
        val &= ~PLL_REGM_F_MASK;
 
134
        val |= dpll_params->mf << PLL_REGM_F_SHIFT;
 
135
        omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
 
136
 
 
137
        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
 
138
        val &= ~PLL_SD_MASK;
 
139
        val |= dpll_params->sd << PLL_SD_SHIFT;
 
140
        omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
 
141
 
 
142
        omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
 
143
 
 
144
        return omap_pipe3_wait_lock(phy);
 
145
}
 
146
 
 
147
static void omap_control_phy_power(struct omap_pipe3 *phy, int on)
 
148
{
 
149
        u32 val, rate;
 
150
 
 
151
        val = readl(phy->power_reg);
 
152
 
 
153
        rate = get_sys_clk_freq();
 
154
        rate = rate/1000000;
 
155
 
 
156
        if (on) {
 
157
                val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
 
158
                                OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK);
 
159
                val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
 
160
                        OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
 
161
                val |= rate <<
 
162
                        OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
 
163
        } else {
 
164
                val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK;
 
165
                val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
 
166
                        OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
 
167
        }
 
168
 
 
169
        writel(val, phy->power_reg);
 
170
}
 
171
 
 
172
int phy_pipe3_power_on(struct omap_pipe3 *phy)
 
173
{
 
174
        int ret;
 
175
        u32 val;
 
176
 
 
177
        /* Program the DPLL only if not locked */
 
178
        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
 
179
        if (!(val & PLL_LOCK)) {
 
180
                ret = omap_pipe3_dpll_program(phy);
 
181
                if (ret)
 
182
                        return ret;
 
183
        } else {
 
184
                /* else just bring it out of IDLE mode */
 
185
                val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 
186
                if (val & PLL_IDLE) {
 
187
                        val &= ~PLL_IDLE;
 
188
                        omap_pipe3_writel(phy->pll_ctrl_base,
 
189
                                          PLL_CONFIGURATION2, val);
 
190
                        ret = omap_pipe3_wait_lock(phy);
 
191
                        if (ret)
 
192
                                return ret;
 
193
                }
 
194
        }
 
195
 
 
196
        /* Power up the PHY */
 
197
        omap_control_phy_power(phy, 1);
 
198
 
 
199
        return 0;
 
200
}
 
201
 
 
202
int phy_pipe3_power_off(struct omap_pipe3 *phy)
 
203
{
 
204
        u32 val;
 
205
        int timeout = PLL_IDLE_TIME;
 
206
 
 
207
        /* Power down the PHY */
 
208
        omap_control_phy_power(phy, 0);
 
209
 
 
210
        /* Put DPLL in IDLE mode */
 
211
        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 
212
        val |= PLL_IDLE;
 
213
        omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
 
214
 
 
215
        /* wait for LDO and Oscillator to power down */
 
216
        do {
 
217
                mdelay(1);
 
218
                val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
 
219
                if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
 
220
                        break;
 
221
        } while (--timeout);
 
222
 
 
223
        if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
 
224
                printf("%s: Failed to power down DPLL: PLL_STATUS 0x%x\n",
 
225
                       __func__, val);
 
226
                return -EBUSY;
 
227
        }
 
228
 
 
229
        return 0;
 
230
}
 
231