92f3bd25f460b01eebf8024bcc7e0def8d161a82
[oweals/u-boot.git] / board / phytec / phycore_rk3288 / phycore-rk3288.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2017 PHYTEC Messtechnik GmbH
4  * Author: Wadim Egorov <w.egorov@phytec.de>
5  */
6
7 #include <asm/io.h>
8 #include <common.h>
9 #include <dm.h>
10 #include <environment.h>
11 #include <fdtdec.h>
12 #include <i2c.h>
13 #include <i2c_eeprom.h>
14 #include <netdev.h>
15 #include "som.h"
16 #include <power/regulator.h>
17 #include <power/rk8xx_pmic.h>
18
19 static int valid_rk3288_som(struct rk3288_som *som)
20 {
21         unsigned char *p = (unsigned char *)som;
22         unsigned char *e = p + sizeof(struct rk3288_som) - 1;
23         int hw = 0;
24
25         while (p < e) {
26                 hw += hweight8(*p);
27                 p++;
28         }
29
30         return hw == som->bs;
31 }
32
33 int rk3288_board_late_init(void)
34 {
35         int ret;
36         struct udevice *dev;
37         struct rk3288_som opt;
38         int off;
39
40         /* Get the identificatioin page of M24C32-D EEPROM */
41         off = fdt_path_offset(gd->fdt_blob, "eeprom0");
42         if (off < 0) {
43                 printf("%s: No eeprom0 path offset\n", __func__);
44                 return off;
45         }
46
47         ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev);
48         if (ret) {
49                 printf("%s: Could not find EEPROM\n", __func__);
50                 return ret;
51         }
52
53         ret = i2c_set_chip_offset_len(dev, 2);
54         if (ret)
55                 return ret;
56
57         ret = i2c_eeprom_read(dev, 0, (uint8_t *)&opt,
58                                 sizeof(struct rk3288_som));
59         if (ret) {
60                 printf("%s: Could not read EEPROM\n", __func__);
61                 return ret;
62         }
63
64         if (opt.api_version != 0 || !valid_rk3288_som(&opt)) {
65                 printf("Invalid data or wrong EEPROM layout version.\n");
66                 /* Proceed anyway, since there is no fallback option */
67         }
68
69         if (is_valid_ethaddr(opt.mac))
70                 eth_env_set_enetaddr("ethaddr", opt.mac);
71
72         return 0;
73 }
74
75 #ifdef CONFIG_SPL_BUILD
76 #if !defined(CONFIG_SPL_OF_PLATDATA)
77 static int phycore_init(void)
78 {
79         struct udevice *pmic;
80         int ret;
81
82         ret = uclass_first_device_err(UCLASS_PMIC, &pmic);
83         if (ret)
84                 return ret;
85
86 #if defined(CONFIG_SPL_POWER_SUPPORT)
87         /* Increase USB input current to 2A */
88         ret = rk818_spl_configure_usb_input_current(pmic, 2000);
89         if (ret)
90                 return ret;
91
92         /* Close charger when USB lower then 3.26V */
93         ret = rk818_spl_configure_usb_chrg_shutdown(pmic, 3260000);
94         if (ret)
95                 return ret;
96 #endif
97
98         return 0;
99 }
100 #endif
101
102 void spl_board_init(void)
103 {
104 #if !defined(CONFIG_SPL_OF_PLATDATA)
105         int ret;
106
107         if (of_machine_is_compatible("phytec,rk3288-phycore-som")) {
108                 ret = phycore_init();
109                 if (ret) {
110                         debug("Failed to set up phycore power settings: %d\n",
111                               ret);
112                         return;
113                 }
114         }
115 #endif
116 }
117 #endif