Loading...
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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | /*
* Copyright (C) 2015 Samsung Electronics
* Przemyslaw Marczak <p.marczak@samsung.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <adc.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <power/pmic.h>
#include <power/regulator.h>
#include <power/s2mps11.h>
#include <samsung/exynos5-dt-types.h>
#include <samsung/misc.h>
DECLARE_GLOBAL_DATA_PTR;
static const struct udevice_id board_ids[] = {
{ .compatible = "samsung,odroidxu3", .data = EXYNOS5_BOARD_ODROID_XU3 },
{ .compatible = "samsung,exynos5", .data = EXYNOS5_BOARD_GENERIC },
{ },
};
/**
* Odroix XU3/4 board revisions:
* Rev ADCmax Board
* 0.1 0 XU3 0.1
* 0.2 410 XU3 0.2 | XU3L - no DISPLAYPORT (probe I2C0:0x40 / INA231)
* 0.3 1408 XU4 0.1
* Use +10 % for ADC value tolerance.
*/
struct odroid_rev_info odroid_info[] = {
{ EXYNOS5_BOARD_ODROID_XU3_REV01, 1, 10, "xu3" },
{ EXYNOS5_BOARD_ODROID_XU3_REV02, 2, 410, "xu3" },
{ EXYNOS5_BOARD_ODROID_XU4_REV01, 1, 1408, "xu4" },
{ EXYNOS5_BOARD_ODROID_UNKNOWN, 0, 4095, "unknown" },
};
static unsigned int odroid_get_rev(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
if (odroid_info[i].board_type == gd->board_type)
return odroid_info[i].board_rev;
}
return 0;
}
static int odroid_get_board_type(void)
{
unsigned int adcval;
int ret, i;
ret = adc_channel_single_shot("adc", CONFIG_ODROID_REV_AIN, &adcval);
if (ret)
goto rev_default;
for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
/* ADC tolerance: +20 % */
if (adcval < odroid_info[i].adc_val)
return odroid_info[i].board_type;
}
rev_default:
return EXYNOS5_BOARD_ODROID_XU3;
}
/**
* odroid_get_type_str - returns pointer to one of the board type string.
* Board types: "xu3", "xu3-lite", "xu4". However the "xu3lite" can be
* detected only when the i2c controller is ready to use. Fortunately,
* XU3 and XU3L are compatible, and the information about board lite
* revision is needed before booting the linux, to set proper environment
* variable: $fdtfile.
*/
static const char *odroid_get_type_str(void)
{
const char *type_xu3l = "xu3-lite";
struct udevice *dev, *chip;
int i, ret;
if (gd->board_type != EXYNOS5_BOARD_ODROID_XU3_REV02)
goto exit;
ret = pmic_get("s2mps11", &dev);
if (ret)
goto exit;
/* Enable LDO26: 3.0V */
ret = pmic_reg_write(dev, S2MPS11_REG_L26CTRL,
S2MPS11_LDO26_ENABLE);
if (ret)
goto exit;
/* Check XU3Lite by probe INA231 I2C0:0x40 */
ret = uclass_get_device(UCLASS_I2C, 0, &dev);
if (ret)
goto exit;
ret = dm_i2c_probe(dev, 0x40, 0x0, &chip);
if (ret)
return type_xu3l;
exit:
for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
if (odroid_info[i].board_type == gd->board_type)
return odroid_info[i].name;
}
return NULL;
}
bool board_is_odroidxu3(void)
{
if (gd->board_type >= EXYNOS5_BOARD_ODROID_XU3 &&
gd->board_type <= EXYNOS5_BOARD_ODROID_XU3_REV02)
return true;
return false;
}
bool board_is_odroidxu4(void)
{
if (gd->board_type == EXYNOS5_BOARD_ODROID_XU4_REV01)
return true;
return false;
}
bool board_is_generic(void)
{
if (gd->board_type == EXYNOS5_BOARD_GENERIC)
return true;
return false;
}
/**
* get_board_rev() - return detected board revision.
*
* @return: return board revision number for XU3 or 0 for generic
*/
u32 get_board_rev(void)
{
if (board_is_generic())
return 0;
return odroid_get_rev();
}
/**
* get_board_type() - returns board type string.
*
* @return: return board type string for XU3 or empty string for generic
*/
const char *get_board_type(void)
{
const char *generic = "";
if (board_is_generic())
return generic;
return odroid_get_type_str();
}
/**
* set_board_type() - set board type in gd->board_type.
* As default type set EXYNOS5_BOARD_GENERIC, if detect Odroid,
* then set its proper type.
*/
void set_board_type(void)
{
const struct udevice_id *of_match = board_ids;
int ret;
gd->board_type = EXYNOS5_BOARD_GENERIC;
while (of_match->compatible) {
ret = fdt_node_check_compatible(gd->fdt_blob, 0,
of_match->compatible);
if (ret)
of_match++;
gd->board_type = of_match->data;
break;
}
/* If Odroid, then check its revision */
if (board_is_odroidxu3())
gd->board_type = odroid_get_board_type();
}
|