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

« back to all changes in this revision

Viewing changes to roms/u-boot/board/egnite/ethernut5/ethernut5_pwrman.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
 * (C) Copyright 2011
 
3
 * egnite GmbH <info@egnite.de>
 
4
 *
 
5
 * SPDX-License-Identifier:     GPL-2.0+
 
6
 */
 
7
 
 
8
/*
 
9
 * Ethernut 5 power management support
 
10
 *
 
11
 * This board may be supplied via USB, IEEE 802.3af PoE or an
 
12
 * auxiliary DC input. An on-board ATmega168 microcontroller,
 
13
 * the so called power management controller or PMC, is used
 
14
 * to select the supply source and to switch on and off certain
 
15
 * energy consuming board components. This allows to reduce the
 
16
 * total stand-by consumption to less than 70mW.
 
17
 *
 
18
 * The main CPU communicates with the PMC via I2C. When
 
19
 * CONFIG_CMD_BSP is defined in the board configuration file,
 
20
 * then the board specific command 'pwrman' becomes available,
 
21
 * which allows to manually deal with the PMC.
 
22
 *
 
23
 * Two distinct registers are provided by the PMC for enabling
 
24
 * and disabling specific features. This avoids the often seen
 
25
 * read-modify-write cycle or shadow register requirement.
 
26
 * Additional registers are available to query the board
 
27
 * status and temperature, the auxiliary voltage and to control
 
28
 * the green user LED that is integrated in the reset switch.
 
29
 *
 
30
 * Note, that the AVR firmware of the PMC is released under BSDL.
 
31
 *
 
32
 * For additional information visit the project home page at
 
33
 * http://www.ethernut.de/
 
34
 */
 
35
#include <common.h>
 
36
#include <asm/arch/at91sam9260.h>
 
37
#include <asm/arch/at91_common.h>
 
38
#include <asm/arch/gpio.h>
 
39
#include <asm/io.h>
 
40
#include <i2c.h>
 
41
 
 
42
#include "ethernut5_pwrman.h"
 
43
 
 
44
/* PMC firmware version */
 
45
static int pwrman_major;
 
46
static int pwrman_minor;
 
47
 
 
48
/*
 
49
 * Enable Ethernut 5 power management.
 
50
 *
 
51
 * This function must be called during board initialization.
 
52
 * While we are using u-boot's I2C subsystem, it may be required
 
53
 * to enable the serial port before calling this function,
 
54
 * in particular when debugging is enabled.
 
55
 *
 
56
 * If board specific commands are not available, we will activate
 
57
 * all board components.
 
58
 */
 
59
void ethernut5_power_init(void)
 
60
{
 
61
        pwrman_minor = i2c_reg_read(PWRMAN_I2C_ADDR, PWRMAN_REG_VERS);
 
62
        pwrman_major = pwrman_minor >> 4;
 
63
        pwrman_minor &= 15;
 
64
 
 
65
#ifndef CONFIG_CMD_BSP
 
66
        /* Do not modify anything, if we do not have a known version. */
 
67
        if (pwrman_major == 2) {
 
68
                /* Without board specific commands we enable all features. */
 
69
                i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_ENA, ~PWRMAN_ETHRST);
 
70
                i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_DIS, PWRMAN_ETHRST);
 
71
        }
 
72
#endif
 
73
}
 
74
 
 
75
/*
 
76
 * Reset Ethernet PHY.
 
77
 *
 
78
 * This function allows the re-configure the PHY after
 
79
 * changing its strap pins.
 
80
 */
 
81
void ethernut5_phy_reset(void)
 
82
{
 
83
        /* Do not modify anything, if we do not have a known version. */
 
84
        if (pwrman_major != 2)
 
85
                return;
 
86
 
 
87
        /*
 
88
         * Make sure that the Ethernet clock is enabled and the PHY reset
 
89
         * is disabled for at least 100 us.
 
90
         */
 
91
        i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_ENA, PWRMAN_ETHCLK);
 
92
        i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_DIS, PWRMAN_ETHRST);
 
93
        udelay(100);
 
94
 
 
95
        /*
 
96
         * LAN8710 strap pins are
 
97
         * PA14 => PHY MODE0
 
98
         * PA15 => PHY MODE1
 
99
         * PA17 => PHY MODE2 => 111b all capable
 
100
         * PA18 => PHY ADDR0 => 0b
 
101
         */
 
102
        at91_set_pio_input(AT91_PIO_PORTA, 14, 1);
 
103
        at91_set_pio_input(AT91_PIO_PORTA, 15, 1);
 
104
        at91_set_pio_input(AT91_PIO_PORTA, 17, 1);
 
105
        at91_set_pio_input(AT91_PIO_PORTA, 18, 0);
 
106
 
 
107
        /* Activate PHY reset for 100 us. */
 
108
        i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_ENA, PWRMAN_ETHRST);
 
109
        udelay(100);
 
110
        i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_DIS, PWRMAN_ETHRST);
 
111
 
 
112
        at91_set_pio_input(AT91_PIO_PORTA, 14, 1);
 
113
}
 
114
 
 
115
/*
 
116
 * Output the firmware version we got during initialization.
 
117
 */
 
118
void ethernut5_print_version(void)
 
119
{
 
120
        printf("%u.%u\n", pwrman_major, pwrman_minor);
 
121
}
 
122
 
 
123
/*
 
124
 * All code below this point is optional and implements
 
125
 * the 'pwrman' command.
 
126
 */
 
127
#ifdef CONFIG_CMD_BSP
 
128
 
 
129
/* Human readable names of PMC features */
 
130
char *pwrman_feat[8] = {
 
131
        "board", "vbin", "vbout", "mmc",
 
132
        "rs232", "ethclk", "ethrst", "wakeup"
 
133
};
 
134
 
 
135
/*
 
136
 * Print all feature names, that have its related flags enabled.
 
137
 */
 
138
static void print_flagged_features(u8 flags)
 
139
{
 
140
        int i;
 
141
 
 
142
        for (i = 0; i < 8; i++) {
 
143
                if (flags & (1 << i))
 
144
                        printf("%s ", pwrman_feat[i]);
 
145
        }
 
146
}
 
147
 
 
148
/*
 
149
 * Return flags of a given list of feature names.
 
150
 *
 
151
 * The function stops at the first unknown list entry and
 
152
 * returns the number of detected names as a function result.
 
153
 */
 
154
static int feature_flags(char * const names[], int num, u8 *flags)
 
155
{
 
156
        int i, j;
 
157
 
 
158
        *flags = 0;
 
159
        for (i = 0; i < num; i++) {
 
160
                for (j = 0; j < 8; j++) {
 
161
                        if (strcmp(pwrman_feat[j], names[i]) == 0) {
 
162
                                *flags |= 1 << j;
 
163
                                break;
 
164
                        }
 
165
                }
 
166
                if (j > 7)
 
167
                        break;
 
168
        }
 
169
        return i;
 
170
}
 
171
 
 
172
void ethernut5_print_power(void)
 
173
{
 
174
        u8 flags;
 
175
        int i;
 
176
 
 
177
        flags = i2c_reg_read(PWRMAN_I2C_ADDR, PWRMAN_REG_ENA);
 
178
        for (i = 0; i < 2; i++) {
 
179
                if (flags) {
 
180
                        print_flagged_features(flags);
 
181
                        printf("%s\n", i ? "off" : "on");
 
182
                }
 
183
                flags = ~flags;
 
184
        }
 
185
}
 
186
 
 
187
void ethernut5_print_celsius(void)
 
188
{
 
189
        int val;
 
190
 
 
191
        /* Read ADC value from LM50 and return Celsius degrees. */
 
192
        val = i2c_reg_read(PWRMAN_I2C_ADDR, PWRMAN_REG_TEMP);
 
193
        val *= 5000;    /* 100mV/degree with 5V reference */
 
194
        val += 128;     /* 8 bit resolution */
 
195
        val /= 256;
 
196
        val -= 450;     /* Celsius offset, still x10 */
 
197
        /* Output full degrees. */
 
198
        printf("%d\n", (val + 5) / 10);
 
199
}
 
200
 
 
201
void ethernut5_print_voltage(void)
 
202
{
 
203
        int val;
 
204
 
 
205
        /* Read ADC value from divider and return voltage. */
 
206
        val = i2c_reg_read(PWRMAN_I2C_ADDR, PWRMAN_REG_VAUX);
 
207
        /* Resistors are 100k and 12.1k */
 
208
        val += 5;
 
209
        val *= 180948;
 
210
        val /= 100000;
 
211
        val++;
 
212
        /* Calculation was done in 0.1V units. */
 
213
        printf("%d\n", (val + 5) / 10);
 
214
}
 
215
 
 
216
/*
 
217
 * Process the board specific 'pwrman' command.
 
218
 */
 
219
int do_pwrman(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
220
{
 
221
        u8 val;
 
222
        int i;
 
223
 
 
224
        if (argc == 1) {
 
225
                ethernut5_print_power();
 
226
        } else if (argc == 2 && strcmp(argv[1], "reset") == 0) {
 
227
                at91_set_pio_output(AT91_PIO_PORTB, 8, 1);
 
228
                udelay(100);
 
229
                at91_set_pio_output(AT91_PIO_PORTB, 8, 0);
 
230
                udelay(100000);
 
231
        } else if (argc == 2 && strcmp(argv[1], "temp") == 0) {
 
232
                ethernut5_print_celsius();
 
233
        } else if (argc == 2 && strcmp(argv[1], "vaux") == 0) {
 
234
                ethernut5_print_voltage();
 
235
        } else if (argc == 2 && strcmp(argv[1], "version") == 0) {
 
236
                ethernut5_print_version();
 
237
        } else if (strcmp(argv[1], "led") == 0) {
 
238
                /* Control the green status LED. Blink frequency unit
 
239
                ** is 0.1s, very roughly. */
 
240
                if (argc == 2) {
 
241
                        /* No more arguments, output current settings. */
 
242
                        val = i2c_reg_read(PWRMAN_I2C_ADDR, PWRMAN_REG_LEDCTL);
 
243
                        printf("led %u %u\n", val >> 4, val & 15);
 
244
                } else {
 
245
                        /* First argument specifies the on-time. */
 
246
                        val = (u8) simple_strtoul(argv[2], NULL, 0);
 
247
                        val <<= 4;
 
248
                        if (argc > 3) {
 
249
                                /* Second argument specifies the off-time. */
 
250
                                val |= (u8) (simple_strtoul(argv[3], NULL, 0)
 
251
                                                & 15);
 
252
                        }
 
253
                        /* Update the LED control register. */
 
254
                        i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_LEDCTL, val);
 
255
                }
 
256
        } else {
 
257
                /* We expect a list of features followed an optional status. */
 
258
                argc--;
 
259
                i = feature_flags(&argv[1], argc, &val);
 
260
                if (argc == i) {
 
261
                        /* We got a list only, print status. */
 
262
                        val &= i2c_reg_read(PWRMAN_I2C_ADDR, PWRMAN_REG_STA);
 
263
                        if (val) {
 
264
                                if (i > 1)
 
265
                                        print_flagged_features(val);
 
266
                                printf("active\n");
 
267
                        } else {
 
268
                                printf("inactive\n");
 
269
                        }
 
270
                } else {
 
271
                        /* More arguments. */
 
272
                        if (i == 0) {
 
273
                                /* No given feature, use despensibles. */
 
274
                                val = PWRMAN_DISPENSIBLE;
 
275
                        }
 
276
                        if (strcmp(argv[i + 1], "on") == 0) {
 
277
                                /* Enable features. */
 
278
                                i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_ENA,
 
279
                                                val);
 
280
                        } else if (strcmp(argv[i + 1], "off") == 0) {
 
281
                                /* Disable features. */
 
282
                                i2c_reg_write(PWRMAN_I2C_ADDR, PWRMAN_REG_DIS,
 
283
                                                val);
 
284
                        } else {
 
285
                                printf("Bad parameter %s\n", argv[i + 1]);
 
286
                                return 1;
 
287
                        }
 
288
                }
 
289
        }
 
290
        return 0;
 
291
}
 
292
 
 
293
U_BOOT_CMD(
 
294
        pwrman, CONFIG_SYS_MAXARGS, 1, do_pwrman,
 
295
        "power management",
 
296
                   "- print settings\n"
 
297
        "pwrman feature ...\n"
 
298
        "       - print status\n"
 
299
        "pwrman [feature ...] on|off\n"
 
300
        "       - enable/disable specified or all dispensible features\n"
 
301
        "pwrman led [on-time [off-time]]\n"
 
302
        "       - print or set led blink timer\n"
 
303
        "pwrman temp\n"
 
304
        "       - print board temperature (Celsius)\n"
 
305
        "pwrman vaux\n"
 
306
        "       - print auxiliary input voltage\n"
 
307
        "pwrman reset\n"
 
308
        "       - reset power management controller\n"
 
309
        "pwrman version\n"
 
310
        "       - print firmware version\n"
 
311
        "\n"
 
312
        "        features, (*)=dispensible:\n"
 
313
        "          board  - 1.8V and 3.3V supply\n"
 
314
        "          vbin   - supply via USB device connector\n"
 
315
        "          vbout  - USB host connector supply(*)\n"
 
316
        "          mmc    - MMC slot supply(*)\n"
 
317
        "          rs232  - RS232 driver\n"
 
318
        "          ethclk - Ethernet PHY clock(*)\n"
 
319
        "          ethrst - Ethernet PHY reset\n"
 
320
        "          wakeup - RTC alarm"
 
321
);
 
322
#endif /* CONFIG_CMD_BSP */