aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/board/compulab/common
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/board/compulab/common')
-rw-r--r--roms/u-boot/board/compulab/common/Makefile10
-rw-r--r--roms/u-boot/board/compulab/common/common.c61
-rw-r--r--roms/u-boot/board/compulab/common/common.h37
-rw-r--r--roms/u-boot/board/compulab/common/eeprom.c528
-rw-r--r--roms/u-boot/board/compulab/common/eeprom.h32
-rw-r--r--roms/u-boot/board/compulab/common/omap3_display.c452
-rw-r--r--roms/u-boot/board/compulab/common/omap3_smc911x.c93
7 files changed, 1213 insertions, 0 deletions
diff --git a/roms/u-boot/board/compulab/common/Makefile b/roms/u-boot/board/compulab/common/Makefile
new file mode 100644
index 000000000..7ba92f5db
--- /dev/null
+++ b/roms/u-boot/board/compulab/common/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2011 - 2013 CompuLab, Ltd. <www.compulab.co.il>
+#
+# Author: Igor Grinberg <grinberg@compulab.co.il>
+
+obj-y += common.o
+obj-$(CONFIG_SYS_I2C) += eeprom.o
+obj-$(CONFIG_LCD) += omap3_display.o
+obj-$(CONFIG_SMC911X) += omap3_smc911x.o
diff --git a/roms/u-boot/board/compulab/common/common.c b/roms/u-boot/board/compulab/common/common.c
new file mode 100644
index 000000000..528c97df1
--- /dev/null
+++ b/roms/u-boot/board/compulab/common/common.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Igor Grinberg <grinberg@compulab.co.il>
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/bootm.h>
+#include <asm/gpio.h>
+#include <asm/setup.h>
+#include <linux/delay.h>
+
+#include "common.h"
+#include "eeprom.h"
+
+void cl_print_pcb_info(void)
+{
+ u32 board_rev = get_board_rev();
+ u32 rev_major = board_rev / 100;
+ u32 rev_minor = board_rev - (rev_major * 100);
+
+ if ((rev_minor / 10) * 10 == rev_minor)
+ rev_minor = rev_minor / 10;
+
+ printf("PCB: %u.%u\n", rev_major, rev_minor);
+}
+
+#ifdef CONFIG_SERIAL_TAG
+void __weak get_board_serial(struct tag_serialnr *serialnr)
+{
+ /*
+ * This corresponds to what happens when we can communicate with the
+ * eeprom but don't get a valid board serial value.
+ */
+ serialnr->low = 0;
+ serialnr->high = 0;
+};
+#endif
+
+#ifdef CONFIG_CMD_USB
+int cl_usb_hub_init(int gpio, const char *label)
+{
+ if (gpio_request(gpio, label)) {
+ printf("Error: can't obtain GPIO%d for %s", gpio, label);
+ return -1;
+ }
+
+ gpio_direction_output(gpio, 0);
+ udelay(10);
+ gpio_set_value(gpio, 1);
+ udelay(1000);
+ return 0;
+}
+
+void cl_usb_hub_deinit(int gpio)
+{
+ gpio_free(gpio);
+}
+#endif
diff --git a/roms/u-boot/board/compulab/common/common.h b/roms/u-boot/board/compulab/common/common.h
new file mode 100644
index 000000000..17cfbb6f2
--- /dev/null
+++ b/roms/u-boot/board/compulab/common/common.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Igor Grinberg <grinberg@compulab.co.il>
+ */
+
+#ifndef _CL_COMMON_
+#define _CL_COMMON_
+
+#include <linux/errno.h>
+
+void cl_print_pcb_info(void);
+
+#ifdef CONFIG_CMD_USB
+int cl_usb_hub_init(int gpio, const char *label);
+void cl_usb_hub_deinit(int gpio);
+#else /* !CONFIG_CMD_USB */
+static inline int cl_usb_hub_init(int gpio, const char *label)
+{
+ return -ENOSYS;
+}
+static inline void cl_usb_hub_deinit(int gpio) {}
+#endif /* CONFIG_CMD_USB */
+
+#ifdef CONFIG_SMC911X
+int cl_omap3_smc911x_init(int id, int cs, u32 base_addr,
+ int (*reset)(int), int rst_gpio);
+#else /* !CONFIG_SMC911X */
+static inline int cl_omap3_smc911x_init(int id, int cs, u32 base_addr,
+ int (*reset)(int), int rst_gpio)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_SMC911X */
+
+#endif /* _CL_COMMON_ */
diff --git a/roms/u-boot/board/compulab/common/eeprom.c b/roms/u-boot/board/compulab/common/eeprom.c
new file mode 100644
index 000000000..5206cf5c0
--- /dev/null
+++ b/roms/u-boot/board/compulab/common/eeprom.c
@@ -0,0 +1,528 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Nikita Kiryanov <nikita@compulab.co.il>
+ * Igor Grinberg <grinberg@compulab.co.il>
+ */
+
+#include <common.h>
+#include <eeprom.h>
+#include <i2c.h>
+#include <eeprom_layout.h>
+#include <eeprom_field.h>
+#include <asm/setup.h>
+#include <linux/kernel.h>
+#include "eeprom.h"
+
+#ifndef CONFIG_SYS_I2C_EEPROM_ADDR
+# define CONFIG_SYS_I2C_EEPROM_ADDR 0x50
+# define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
+#endif
+
+#ifndef CONFIG_SYS_I2C_EEPROM_BUS
+#define CONFIG_SYS_I2C_EEPROM_BUS 0
+#endif
+
+#define EEPROM_LAYOUT_VER_OFFSET 44
+#define BOARD_SERIAL_OFFSET 20
+#define BOARD_SERIAL_OFFSET_LEGACY 8
+#define BOARD_REV_OFFSET 0
+#define BOARD_REV_OFFSET_LEGACY 6
+#define BOARD_REV_SIZE 2
+#define PRODUCT_NAME_OFFSET 128
+#define PRODUCT_NAME_SIZE 16
+#define MAC_ADDR_OFFSET 4
+#define MAC_ADDR_OFFSET_LEGACY 0
+
+#define LAYOUT_INVALID 0
+#define LAYOUT_LEGACY 0xff
+
+static int cl_eeprom_bus;
+static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */
+
+static int cl_eeprom_read(uint offset, uchar *buf, int len)
+{
+ int res;
+ unsigned int current_i2c_bus = i2c_get_bus_num();
+
+ res = i2c_set_bus_num(cl_eeprom_bus);
+ if (res < 0)
+ return res;
+
+ res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, offset,
+ CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, len);
+
+ i2c_set_bus_num(current_i2c_bus);
+
+ return res;
+}
+
+static int cl_eeprom_setup(uint eeprom_bus)
+{
+ int res;
+
+ /*
+ * We know the setup was already done when the layout is set to a valid
+ * value and we're using the same bus as before.
+ */
+ if (cl_eeprom_layout != LAYOUT_INVALID && eeprom_bus == cl_eeprom_bus)
+ return 0;
+
+ cl_eeprom_bus = eeprom_bus;
+ res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET,
+ (uchar *)&cl_eeprom_layout, 1);
+ if (res) {
+ cl_eeprom_layout = LAYOUT_INVALID;
+ return res;
+ }
+
+ if (cl_eeprom_layout == 0 || cl_eeprom_layout >= 0x20)
+ cl_eeprom_layout = LAYOUT_LEGACY;
+
+ return 0;
+}
+
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+ u32 serial[2];
+ uint offset;
+
+ memset(serialnr, 0, sizeof(*serialnr));
+
+ if (cl_eeprom_setup(CONFIG_SYS_I2C_EEPROM_BUS))
+ return;
+
+ offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
+ BOARD_SERIAL_OFFSET : BOARD_SERIAL_OFFSET_LEGACY;
+
+ if (cl_eeprom_read(offset, (uchar *)serial, 8))
+ return;
+
+ if (serial[0] != 0xffffffff && serial[1] != 0xffffffff) {
+ serialnr->low = serial[0];
+ serialnr->high = serial[1];
+ }
+}
+
+/*
+ * Routine: cl_eeprom_read_mac_addr
+ * Description: read mac address and store it in buf.
+ */
+int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus)
+{
+ uint offset;
+ int err;
+
+ err = cl_eeprom_setup(eeprom_bus);
+ if (err)
+ return err;
+
+ offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
+ MAC_ADDR_OFFSET : MAC_ADDR_OFFSET_LEGACY;
+
+ return cl_eeprom_read(offset, buf, 6);
+}
+
+static u32 board_rev;
+
+/*
+ * Routine: cl_eeprom_get_board_rev
+ * Description: read system revision from eeprom
+ */
+u32 cl_eeprom_get_board_rev(uint eeprom_bus)
+{
+ char str[5]; /* Legacy representation can contain at most 4 digits */
+ uint offset = BOARD_REV_OFFSET_LEGACY;
+
+ if (board_rev)
+ return board_rev;
+
+ if (cl_eeprom_setup(eeprom_bus))
+ return 0;
+
+ if (cl_eeprom_layout != LAYOUT_LEGACY)
+ offset = BOARD_REV_OFFSET;
+
+ if (cl_eeprom_read(offset, (uchar *)&board_rev, BOARD_REV_SIZE))
+ return 0;
+
+ /*
+ * Convert legacy syntactic representation to semantic
+ * representation. i.e. for rev 1.00: 0x100 --> 0x64
+ */
+ if (cl_eeprom_layout == LAYOUT_LEGACY) {
+ sprintf(str, "%x", board_rev);
+ board_rev = simple_strtoul(str, NULL, 10);
+ }
+
+ return board_rev;
+};
+
+/*
+ * Routine: cl_eeprom_get_board_rev
+ * Description: read system revision from eeprom
+ *
+ * @buf: buffer to store the product name
+ * @eeprom_bus: i2c bus num of the eeprom
+ *
+ * @return: 0 on success, < 0 on failure
+ */
+int cl_eeprom_get_product_name(uchar *buf, uint eeprom_bus)
+{
+ int err;
+
+ if (buf == NULL)
+ return -EINVAL;
+
+ err = cl_eeprom_setup(eeprom_bus);
+ if (err)
+ return err;
+
+ err = cl_eeprom_read(PRODUCT_NAME_OFFSET, buf, PRODUCT_NAME_SIZE);
+ if (!err) /* Protect ourselves from invalid data (unterminated str) */
+ buf[PRODUCT_NAME_SIZE - 1] = '\0';
+
+ return err;
+}
+
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+/**
+ * eeprom_field_print_bin_ver() - print a "version field" which contains binary
+ * data
+ *
+ * Treat the field data as simple binary data, and print it formatted as a
+ * version number (2 digits after decimal point).
+ * The field size must be exactly 2 bytes.
+ *
+ * Sample output:
+ * Field Name 123.45
+ *
+ * @field: an initialized field to print
+ */
+void eeprom_field_print_bin_ver(const struct eeprom_field *field)
+{
+ if ((field->buf[0] == 0xff) && (field->buf[1] == 0xff)) {
+ field->buf[0] = 0;
+ field->buf[1] = 0;
+ }
+
+ printf(PRINT_FIELD_SEGMENT, field->name);
+ int major = (field->buf[1] << 8 | field->buf[0]) / 100;
+ int minor = (field->buf[1] << 8 | field->buf[0]) - major * 100;
+ printf("%d.%02d\n", major, minor);
+}
+
+/**
+ * eeprom_field_update_bin_ver() - update a "version field" which contains
+ * binary data
+ *
+ * This function takes a version string in the form of x.y (x and y are both
+ * decimal values, y is limited to two digits), translates it to the binary
+ * form, then writes it to the field. The field size must be exactly 2 bytes.
+ *
+ * This function strictly enforces the data syntax, and will not update the
+ * field if there's any deviation from it. It also protects from overflow.
+ *
+ * @field: an initialized field
+ * @value: a version string
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int eeprom_field_update_bin_ver(struct eeprom_field *field, char *value)
+{
+ char *endptr;
+ char *tok = strtok(value, ".");
+ if (tok == NULL)
+ return -1;
+
+ int num = simple_strtol(tok, &endptr, 0);
+ if (*endptr != '\0')
+ return -1;
+
+ tok = strtok(NULL, "");
+ if (tok == NULL)
+ return -1;
+
+ int remainder = simple_strtol(tok, &endptr, 0);
+ if (*endptr != '\0')
+ return -1;
+
+ num = num * 100 + remainder;
+ if (num >> 16)
+ return -1;
+
+ field->buf[0] = (unsigned char)num;
+ field->buf[1] = num >> 8;
+
+ return 0;
+}
+
+char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+/**
+ * eeprom_field_print_date() - print a field which contains date data
+ *
+ * Treat the field data as simple binary data, and print it formatted as a date.
+ * Sample output:
+ * Field Name 07/Feb/2014
+ * Field Name 56/BAD/9999
+ *
+ * @field: an initialized field to print
+ */
+void eeprom_field_print_date(const struct eeprom_field *field)
+{
+ printf(PRINT_FIELD_SEGMENT, field->name);
+ printf("%02d/", field->buf[0]);
+ if (field->buf[1] >= 1 && field->buf[1] <= 12)
+ printf("%s", months[field->buf[1] - 1]);
+ else
+ printf("BAD");
+
+ printf("/%d\n", field->buf[3] << 8 | field->buf[2]);
+}
+
+static int validate_date(unsigned char day, unsigned char month,
+ unsigned int year)
+{
+ int days_in_february;
+
+ switch (month) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ case 7:
+ case 9:
+ case 11:
+ if (day > 31)
+ return -1;
+ break;
+ case 3:
+ case 5:
+ case 8:
+ case 10:
+ if (day > 30)
+ return -1;
+ break;
+ case 1:
+ days_in_february = 28;
+ if (year % 4 == 0) {
+ if (year % 100 != 0)
+ days_in_february = 29;
+ else if (year % 400 == 0)
+ days_in_february = 29;
+ }
+
+ if (day > days_in_february)
+ return -1;
+
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * eeprom_field_update_date() - update a date field which contains binary data
+ *
+ * This function takes a date string in the form of x/Mon/y (x and y are both
+ * decimal values), translates it to the binary representation, then writes it
+ * to the field.
+ *
+ * This function strictly enforces the data syntax, and will not update the
+ * field if there's any deviation from it. It also protects from overflow in the
+ * year value, and checks the validity of the date.
+ *
+ * @field: an initialized field
+ * @value: a date string
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int eeprom_field_update_date(struct eeprom_field *field, char *value)
+{
+ char *endptr;
+ char *tok1 = strtok(value, "/");
+ char *tok2 = strtok(NULL, "/");
+ char *tok3 = strtok(NULL, "/");
+
+ if (tok1 == NULL || tok2 == NULL || tok3 == NULL) {
+ printf("%s: syntax error\n", field->name);
+ return -1;
+ }
+
+ unsigned char day = (unsigned char)simple_strtol(tok1, &endptr, 0);
+ if (*endptr != '\0' || day == 0) {
+ printf("%s: invalid day\n", field->name);
+ return -1;
+ }
+
+ unsigned char month;
+ for (month = 1; month <= 12; month++)
+ if (!strcmp(tok2, months[month - 1]))
+ break;
+
+ unsigned int year = simple_strtol(tok3, &endptr, 0);
+ if (*endptr != '\0') {
+ printf("%s: invalid year\n", field->name);
+ return -1;
+ }
+
+ if (validate_date(day, month - 1, year)) {
+ printf("%s: invalid date\n", field->name);
+ return -1;
+ }
+
+ if (year >> 16) {
+ printf("%s: year overflow\n", field->name);
+ return -1;
+ }
+
+ field->buf[0] = day;
+ field->buf[1] = month;
+ field->buf[2] = (unsigned char)year;
+ field->buf[3] = (unsigned char)(year >> 8);
+
+ return 0;
+}
+
+#define LAYOUT_VERSION_LEGACY 1
+#define LAYOUT_VERSION_VER1 2
+#define LAYOUT_VERSION_VER2 3
+#define LAYOUT_VERSION_VER3 4
+
+extern struct eeprom_field layout_unknown[1];
+
+#define DEFINE_PRINT_UPDATE(x) eeprom_field_print_##x, eeprom_field_update_##x
+
+#ifdef CONFIG_CM_T3X
+struct eeprom_field layout_legacy[5] = {
+ { "MAC address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "Board Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin) },
+ { "Serial Number", 8, NULL, DEFINE_PRINT_UPDATE(bin) },
+ { "Board Configuration", 64, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { RESERVED_FIELDS, 176, NULL, eeprom_field_print_reserved,
+ eeprom_field_update_ascii },
+};
+#else
+#define layout_legacy layout_unknown
+#endif
+
+#if defined(CONFIG_CM_T3X)
+struct eeprom_field layout_v1[12] = {
+ { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
+ { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
+ { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) },
+ { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) },
+ { RESERVED_FIELDS, 96, NULL, DEFINE_PRINT_UPDATE(reserved) },
+ { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved,
+ eeprom_field_update_ascii },
+};
+#else
+#define layout_v1 layout_unknown
+#endif
+
+struct eeprom_field layout_v2[15] = {
+ { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
+ { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
+ { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) },
+ { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) },
+ { "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) },
+ { RESERVED_FIELDS, 83, NULL, DEFINE_PRINT_UPDATE(reserved) },
+ { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved,
+ eeprom_field_update_ascii },
+};
+
+struct eeprom_field layout_v3[16] = {
+ { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
+ { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) },
+ { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) },
+ { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) },
+ { "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) },
+ { "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) },
+ { "CompuLab EEPROM ID", 3, NULL, DEFINE_PRINT_UPDATE(bin) },
+ { RESERVED_FIELDS, 80, NULL, DEFINE_PRINT_UPDATE(reserved) },
+ { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) },
+ { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved,
+ eeprom_field_update_ascii },
+};
+
+void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version)
+{
+ switch (layout->layout_version) {
+ case LAYOUT_VERSION_LEGACY:
+ layout->fields = layout_legacy;
+ layout->num_of_fields = ARRAY_SIZE(layout_legacy);
+ break;
+ case LAYOUT_VERSION_VER1:
+ layout->fields = layout_v1;
+ layout->num_of_fields = ARRAY_SIZE(layout_v1);
+ break;
+ case LAYOUT_VERSION_VER2:
+ layout->fields = layout_v2;
+ layout->num_of_fields = ARRAY_SIZE(layout_v2);
+ break;
+ case LAYOUT_VERSION_VER3:
+ layout->fields = layout_v3;
+ layout->num_of_fields = ARRAY_SIZE(layout_v3);
+ break;
+ default:
+ __eeprom_layout_assign(layout, layout_version);
+ }
+}
+
+int eeprom_parse_layout_version(char *str)
+{
+ if (!strcmp(str, "legacy"))
+ return LAYOUT_VERSION_LEGACY;
+ else if (!strcmp(str, "v1"))
+ return LAYOUT_VERSION_VER1;
+ else if (!strcmp(str, "v2"))
+ return LAYOUT_VERSION_VER2;
+ else if (!strcmp(str, "v3"))
+ return LAYOUT_VERSION_VER3;
+ else
+ return LAYOUT_VERSION_UNRECOGNIZED;
+}
+
+int eeprom_layout_detect(unsigned char *data)
+{
+ switch (data[EEPROM_LAYOUT_VER_OFFSET]) {
+ case 0xff:
+ case 0:
+ return LAYOUT_VERSION_VER1;
+ case 2:
+ return LAYOUT_VERSION_VER2;
+ case 3:
+ return LAYOUT_VERSION_VER3;
+ }
+
+ if (data[EEPROM_LAYOUT_VER_OFFSET] >= 0x20)
+ return LAYOUT_VERSION_LEGACY;
+
+ return LAYOUT_VERSION_UNRECOGNIZED;
+}
+#endif
diff --git a/roms/u-boot/board/compulab/common/eeprom.h b/roms/u-boot/board/compulab/common/eeprom.h
new file mode 100644
index 000000000..a9c0203b8
--- /dev/null
+++ b/roms/u-boot/board/compulab/common/eeprom.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2011 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Nikita Kiryanov <nikita@compulab.co.il>
+ * Igor Grinberg <grinberg@compulab.co.il>
+ */
+
+#ifndef _EEPROM_
+#define _EEPROM_
+#include <errno.h>
+
+#ifdef CONFIG_SYS_I2C
+int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus);
+u32 cl_eeprom_get_board_rev(uint eeprom_bus);
+int cl_eeprom_get_product_name(uchar *buf, uint eeprom_bus);
+#else
+static inline int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus)
+{
+ return 1;
+}
+static inline u32 cl_eeprom_get_board_rev(uint eeprom_bus)
+{
+ return 0;
+}
+static inline int cl_eeprom_get_product_name(uchar *buf, uint eeprom_bus)
+{
+ return -ENOSYS;
+}
+#endif
+
+#endif
diff --git a/roms/u-boot/board/compulab/common/omap3_display.c b/roms/u-boot/board/compulab/common/omap3_display.c
new file mode 100644
index 000000000..cb9ebae7f
--- /dev/null
+++ b/roms/u-boot/board/compulab/common/omap3_display.c
@@ -0,0 +1,452 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012 - 2013 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Nikita Kiryanov <nikita@compulab.co.il>
+ *
+ * Parsing code based on linux/drivers/video/pxafb.c
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <env.h>
+#include <stdio_dev.h>
+#include <asm/arch/dss.h>
+#include <lcd.h>
+#include <scf0403_lcd.h>
+#include <asm/arch-omap3/dss.h>
+
+enum display_type {
+ NONE,
+ DVI,
+ DVI_CUSTOM,
+ DATA_IMAGE, /* #define CONFIG_SCF0403_LCD to use */
+};
+
+#define CMAP_ADDR 0x80100000
+
+/*
+ * The frame buffer is allocated before we have the chance to parse user input.
+ * To make sure enough memory is allocated for all resolutions, we define
+ * vl_{col | row} to the maximal resolution supported by OMAP3.
+ */
+vidinfo_t panel_info = {
+ .vl_col = 1400,
+ .vl_row = 1050,
+ .vl_bpix = LCD_BPP,
+ .cmap = (ushort *)CMAP_ADDR,
+};
+
+static struct panel_config panel_cfg;
+static enum display_type lcd_def;
+
+/*
+ * A note on DVI presets;
+ * U-Boot can convert 8 bit BMP data to 16 bit BMP data, and OMAP DSS can
+ * convert 16 bit data into 24 bit data. Thus, GFXFORMAT_RGB16 allows us to
+ * support two BMP types with one setting.
+ */
+static const struct panel_config preset_dvi_640X480 = {
+ .lcd_size = PANEL_LCD_SIZE(640, 480),
+ .timing_h = DSS_HBP(48) | DSS_HFP(16) | DSS_HSW(96),
+ .timing_v = DSS_VBP(33) | DSS_VFP(10) | DSS_VSW(2),
+ .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC,
+ .divisor = 12 | (1 << 16),
+ .data_lines = LCD_INTERFACE_24_BIT,
+ .panel_type = ACTIVE_DISPLAY,
+ .load_mode = 2,
+ .gfx_format = GFXFORMAT_RGB16,
+};
+
+static const struct panel_config preset_dvi_800X600 = {
+ .lcd_size = PANEL_LCD_SIZE(800, 600),
+ .timing_h = DSS_HBP(88) | DSS_HFP(40) | DSS_HSW(128),
+ .timing_v = DSS_VBP(23) | DSS_VFP(1) | DSS_VSW(4),
+ .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC,
+ .divisor = 8 | (1 << 16),
+ .data_lines = LCD_INTERFACE_24_BIT,
+ .panel_type = ACTIVE_DISPLAY,
+ .load_mode = 2,
+ .gfx_format = GFXFORMAT_RGB16,
+};
+
+static const struct panel_config preset_dvi_1024X768 = {
+ .lcd_size = PANEL_LCD_SIZE(1024, 768),
+ .timing_h = DSS_HBP(160) | DSS_HFP(24) | DSS_HSW(136),
+ .timing_v = DSS_VBP(29) | DSS_VFP(3) | DSS_VSW(6),
+ .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC,
+ .divisor = 5 | (1 << 16),
+ .data_lines = LCD_INTERFACE_24_BIT,
+ .panel_type = ACTIVE_DISPLAY,
+ .load_mode = 2,
+ .gfx_format = GFXFORMAT_RGB16,
+};
+
+static const struct panel_config preset_dvi_1152X864 = {
+ .lcd_size = PANEL_LCD_SIZE(1152, 864),
+ .timing_h = DSS_HBP(256) | DSS_HFP(64) | DSS_HSW(128),
+ .timing_v = DSS_VBP(32) | DSS_VFP(1) | DSS_VSW(3),
+ .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC,
+ .divisor = 4 | (1 << 16),
+ .data_lines = LCD_INTERFACE_24_BIT,
+ .panel_type = ACTIVE_DISPLAY,
+ .load_mode = 2,
+ .gfx_format = GFXFORMAT_RGB16,
+};
+
+static const struct panel_config preset_dvi_1280X960 = {
+ .lcd_size = PANEL_LCD_SIZE(1280, 960),
+ .timing_h = DSS_HBP(312) | DSS_HFP(96) | DSS_HSW(112),
+ .timing_v = DSS_VBP(36) | DSS_VFP(1) | DSS_VSW(3),
+ .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC,
+ .divisor = 3 | (1 << 16),
+ .data_lines = LCD_INTERFACE_24_BIT,
+ .panel_type = ACTIVE_DISPLAY,
+ .load_mode = 2,
+ .gfx_format = GFXFORMAT_RGB16,
+};
+
+static const struct panel_config preset_dvi_1280X1024 = {
+ .lcd_size = PANEL_LCD_SIZE(1280, 1024),
+ .timing_h = DSS_HBP(248) | DSS_HFP(48) | DSS_HSW(112),
+ .timing_v = DSS_VBP(38) | DSS_VFP(1) | DSS_VSW(3),
+ .pol_freq = DSS_IHS | DSS_IVS | DSS_IPC,
+ .divisor = 3 | (1 << 16),
+ .data_lines = LCD_INTERFACE_24_BIT,
+ .panel_type = ACTIVE_DISPLAY,
+ .load_mode = 2,
+ .gfx_format = GFXFORMAT_RGB16,
+};
+
+static const struct panel_config preset_dataimage_480X800 = {
+ .lcd_size = PANEL_LCD_SIZE(480, 800),
+ .timing_h = DSS_HBP(2) | DSS_HFP(2) | DSS_HSW(2),
+ .timing_v = DSS_VBP(17) | DSS_VFP(20) | DSS_VSW(3),
+ .pol_freq = DSS_IVS | DSS_IHS | DSS_IPC | DSS_ONOFF,
+ .divisor = 10 | (1 << 10),
+ .data_lines = LCD_INTERFACE_18_BIT,
+ .panel_type = ACTIVE_DISPLAY,
+ .load_mode = 2,
+ .gfx_format = GFXFORMAT_RGB16,
+};
+
+/*
+ * set_resolution_params()
+ *
+ * Due to usage of multiple display related APIs resolution data is located in
+ * more than one place. This function updates them all.
+ */
+static void set_resolution_params(int x, int y)
+{
+ panel_cfg.lcd_size = PANEL_LCD_SIZE(x, y);
+ panel_info.vl_col = x;
+ panel_info.vl_row = y;
+ lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
+}
+
+static void set_preset(const struct panel_config preset, int x_res, int y_res)
+{
+ panel_cfg = preset;
+ set_resolution_params(x_res, y_res);
+}
+
+static enum display_type set_dvi_preset(const struct panel_config preset,
+ int x_res, int y_res)
+{
+ set_preset(preset, x_res, y_res);
+ return DVI;
+}
+
+static enum display_type set_dataimage_preset(const struct panel_config preset,
+ int x_res, int y_res)
+{
+ set_preset(preset, x_res, y_res);
+ return DATA_IMAGE;
+}
+
+/*
+ * parse_mode() - parse the mode parameter of custom lcd settings
+ *
+ * @mode: <res_x>x<res_y>
+ *
+ * Returns -1 on error, 0 on success.
+ */
+static int parse_mode(const char *mode)
+{
+ unsigned int modelen = strlen(mode);
+ int res_specified = 0;
+ unsigned int xres = 0, yres = 0;
+ int yres_specified = 0;
+ int i;
+
+ for (i = modelen - 1; i >= 0; i--) {
+ switch (mode[i]) {
+ case 'x':
+ if (!yres_specified) {
+ yres = simple_strtoul(&mode[i + 1], NULL, 0);
+ yres_specified = 1;
+ } else {
+ goto done_parsing;
+ }
+
+ break;
+ case '0' ... '9':
+ break;
+ default:
+ goto done_parsing;
+ }
+ }
+
+ if (i < 0 && yres_specified) {
+ xres = simple_strtoul(mode, NULL, 0);
+ res_specified = 1;
+ }
+
+done_parsing:
+ if (res_specified) {
+ set_resolution_params(xres, yres);
+ } else {
+ printf("LCD: invalid mode: %s\n", mode);
+ return -1;
+ }
+
+ return 0;
+}
+
+#define PIXEL_CLK_NUMERATOR (26 * 432 / 39)
+/*
+ * parse_pixclock() - Parse the pixclock parameter of custom lcd settings
+ *
+ * @pixclock: the desired pixel clock
+ *
+ * Returns -1 on error, 0 on success.
+ *
+ * Handling the pixel_clock:
+ *
+ * Pixel clock is defined in the OMAP35x TRM as follows:
+ * pixel_clock =
+ * (SYS_CLK * 2 * PRCM.CM_CLKSEL2_PLL[18:8]) /
+ * (DSS.DISPC_DIVISOR[23:16] * DSS.DISPC_DIVISOR[6:0] *
+ * PRCM.CM_CLKSEL_DSS[4:0] * (PRCM.CM_CLKSEL2_PLL[6:0] + 1))
+ *
+ * In practice, this means that in order to set the
+ * divisor for the desired pixel clock one needs to
+ * solve the following equation:
+ *
+ * 26 * 432 / (39 * <pixel_clock>) = DSS.DISPC_DIVISOR[6:0]
+ *
+ * NOTE: the explicit equation above is reduced. Do not
+ * try to infer anything from these numbers.
+ */
+static int parse_pixclock(char *pixclock)
+{
+ int divisor, pixclock_val;
+ char *pixclk_start = pixclock;
+
+ pixclock_val = simple_strtoul(pixclock, &pixclock, 10);
+ divisor = DIV_ROUND_UP(PIXEL_CLK_NUMERATOR, pixclock_val);
+ /* 0 and 1 are illegal values for PCD */
+ if (divisor <= 1)
+ divisor = 2;
+
+ panel_cfg.divisor = divisor | (1 << 16);
+ if (pixclock[0] != '\0') {
+ printf("LCD: invalid value for pixclock:%s\n", pixclk_start);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * parse_setting() - parse a single setting of custom lcd parameters
+ *
+ * @setting: The custom lcd setting <name>:<value>
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+static int parse_setting(char *setting)
+{
+ int num_val;
+ char *setting_start = setting;
+
+ if (!strncmp(setting, "mode:", 5)) {
+ return parse_mode(setting + 5);
+ } else if (!strncmp(setting, "pixclock:", 9)) {
+ return parse_pixclock(setting + 9);
+ } else if (!strncmp(setting, "left:", 5)) {
+ num_val = simple_strtoul(setting + 5, &setting, 0);
+ panel_cfg.timing_h |= DSS_HBP(num_val);
+ } else if (!strncmp(setting, "right:", 6)) {
+ num_val = simple_strtoul(setting + 6, &setting, 0);
+ panel_cfg.timing_h |= DSS_HFP(num_val);
+ } else if (!strncmp(setting, "upper:", 6)) {
+ num_val = simple_strtoul(setting + 6, &setting, 0);
+ panel_cfg.timing_v |= DSS_VBP(num_val);
+ } else if (!strncmp(setting, "lower:", 6)) {
+ num_val = simple_strtoul(setting + 6, &setting, 0);
+ panel_cfg.timing_v |= DSS_VFP(num_val);
+ } else if (!strncmp(setting, "hsynclen:", 9)) {
+ num_val = simple_strtoul(setting + 9, &setting, 0);
+ panel_cfg.timing_h |= DSS_HSW(num_val);
+ } else if (!strncmp(setting, "vsynclen:", 9)) {
+ num_val = simple_strtoul(setting + 9, &setting, 0);
+ panel_cfg.timing_v |= DSS_VSW(num_val);
+ } else if (!strncmp(setting, "hsync:", 6)) {
+ if (simple_strtoul(setting + 6, &setting, 0) == 0)
+ panel_cfg.pol_freq |= DSS_IHS;
+ else
+ panel_cfg.pol_freq &= ~DSS_IHS;
+ } else if (!strncmp(setting, "vsync:", 6)) {
+ if (simple_strtoul(setting + 6, &setting, 0) == 0)
+ panel_cfg.pol_freq |= DSS_IVS;
+ else
+ panel_cfg.pol_freq &= ~DSS_IVS;
+ } else if (!strncmp(setting, "outputen:", 9)) {
+ if (simple_strtoul(setting + 9, &setting, 0) == 0)
+ panel_cfg.pol_freq |= DSS_IEO;
+ else
+ panel_cfg.pol_freq &= ~DSS_IEO;
+ } else if (!strncmp(setting, "pixclockpol:", 12)) {
+ if (simple_strtoul(setting + 12, &setting, 0) == 0)
+ panel_cfg.pol_freq |= DSS_IPC;
+ else
+ panel_cfg.pol_freq &= ~DSS_IPC;
+ } else if (!strncmp(setting, "active", 6)) {
+ panel_cfg.panel_type = ACTIVE_DISPLAY;
+ return 0; /* Avoid sanity check below */
+ } else if (!strncmp(setting, "passive", 7)) {
+ panel_cfg.panel_type = PASSIVE_DISPLAY;
+ return 0; /* Avoid sanity check below */
+ } else if (!strncmp(setting, "display:", 8)) {
+ if (!strncmp(setting + 8, "dvi", 3)) {
+ lcd_def = DVI_CUSTOM;
+ return 0; /* Avoid sanity check below */
+ }
+ } else {
+ printf("LCD: unknown option %s\n", setting_start);
+ return -1;
+ }
+
+ if (setting[0] != '\0') {
+ printf("LCD: invalid value for %s\n", setting_start);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * env_parse_customlcd() - parse custom lcd params from an environment variable.
+ *
+ * @custom_lcd_params: The environment variable containing the lcd params.
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+static int parse_customlcd(char *custom_lcd_params)
+{
+ char params_cpy[160];
+ char *setting;
+
+ strncpy(params_cpy, custom_lcd_params, 160);
+ setting = strtok(params_cpy, ",");
+ while (setting) {
+ if (parse_setting(setting) < 0)
+ return -1;
+
+ setting = strtok(NULL, ",");
+ }
+
+ /* Currently we don't support changing this via custom lcd params */
+ panel_cfg.data_lines = LCD_INTERFACE_24_BIT;
+ panel_cfg.gfx_format = GFXFORMAT_RGB16; /* See dvi predefines note */
+
+ return 0;
+}
+
+/*
+ * env_parse_displaytype() - parse display type.
+ *
+ * Parses the environment variable "displaytype", which contains the
+ * name of the display type or preset, in which case it applies its
+ * configurations.
+ *
+ * Returns the type of display that was specified.
+ */
+static enum display_type env_parse_displaytype(char *displaytype)
+{
+ if (!strncmp(displaytype, "dvi640x480", 10))
+ return set_dvi_preset(preset_dvi_640X480, 640, 480);
+ else if (!strncmp(displaytype, "dvi800x600", 10))
+ return set_dvi_preset(preset_dvi_800X600, 800, 600);
+ else if (!strncmp(displaytype, "dvi1024x768", 11))
+ return set_dvi_preset(preset_dvi_1024X768, 1024, 768);
+ else if (!strncmp(displaytype, "dvi1152x864", 11))
+ return set_dvi_preset(preset_dvi_1152X864, 1152, 864);
+ else if (!strncmp(displaytype, "dvi1280x960", 11))
+ return set_dvi_preset(preset_dvi_1280X960, 1280, 960);
+ else if (!strncmp(displaytype, "dvi1280x1024", 12))
+ return set_dvi_preset(preset_dvi_1280X1024, 1280, 1024);
+ else if (!strncmp(displaytype, "dataimage480x800", 16))
+ return set_dataimage_preset(preset_dataimage_480X800, 480, 800);
+
+ return NONE;
+}
+
+void lcd_ctrl_init(void *lcdbase)
+{
+ struct prcm *prcm = (struct prcm *)PRCM_BASE;
+ char *custom_lcd;
+ char *displaytype = env_get("displaytype");
+
+ if (displaytype == NULL)
+ return;
+
+ lcd_def = env_parse_displaytype(displaytype);
+ /* If we did not recognize the preset, check if it's an env variable */
+ if (lcd_def == NONE) {
+ custom_lcd = env_get(displaytype);
+ if (custom_lcd == NULL || parse_customlcd(custom_lcd) < 0)
+ return;
+ }
+
+ panel_cfg.frame_buffer = lcdbase;
+ omap3_dss_panel_config(&panel_cfg);
+ /*
+ * Pixel clock is defined with many divisions and only few
+ * multiplications of the system clock. Since DSS FCLK divisor is set
+ * to 16 by default, we need to set it to a smaller value, like 3
+ * (chosen via trial and error).
+ */
+ clrsetbits_le32(&prcm->clksel_dss, 0xF, 3);
+}
+
+#ifdef CONFIG_SCF0403_LCD
+static void scf0403_enable(void)
+{
+ gpio_direction_output(58, 1);
+ scf0403_init(157);
+}
+#else
+static inline void scf0403_enable(void) {}
+#endif
+
+void lcd_enable(void)
+{
+ switch (lcd_def) {
+ case NONE:
+ return;
+ case DVI:
+ case DVI_CUSTOM:
+ gpio_direction_output(54, 0); /* Turn on DVI */
+ break;
+ case DATA_IMAGE:
+ scf0403_enable();
+ break;
+ }
+
+ omap3_dss_enable();
+}
+
+void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) {}
diff --git a/roms/u-boot/board/compulab/common/omap3_smc911x.c b/roms/u-boot/board/compulab/common/omap3_smc911x.c
new file mode 100644
index 000000000..f0d365272
--- /dev/null
+++ b/roms/u-boot/board/compulab/common/omap3_smc911x.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Igor Grinberg <grinberg@compulab.co.il>
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/mem.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+
+#include "common.h"
+
+static u32 cl_omap3_smc911x_gpmc_net_config[GPMC_MAX_REG] = {
+ NET_GPMC_CONFIG1,
+ NET_GPMC_CONFIG2,
+ NET_GPMC_CONFIG3,
+ NET_GPMC_CONFIG4,
+ NET_GPMC_CONFIG5,
+ NET_GPMC_CONFIG6,
+ 0
+};
+
+static void cl_omap3_smc911x_setup_net_chip_gmpc(int cs, u32 base_addr)
+{
+ struct ctrl *ctrl_base = (struct ctrl *)OMAP34XX_CTRL_BASE;
+
+ enable_gpmc_cs_config(cl_omap3_smc911x_gpmc_net_config,
+ &gpmc_cfg->cs[cs], base_addr, GPMC_SIZE_16M);
+
+ /* Enable off mode for NWE in PADCONF_GPMC_NWE register */
+ writew(readw(&ctrl_base->gpmc_nwe) | 0x0E00, &ctrl_base->gpmc_nwe);
+
+ /* Enable off mode for NOE in PADCONF_GPMC_NADV_ALE register */
+ writew(readw(&ctrl_base->gpmc_noe) | 0x0E00, &ctrl_base->gpmc_noe);
+
+ /* Enable off mode for ALE in PADCONF_GPMC_NADV_ALE register */
+ writew(readw(&ctrl_base->gpmc_nadv_ale) | 0x0E00,
+ &ctrl_base->gpmc_nadv_ale);
+}
+
+#ifdef CONFIG_OMAP_GPIO
+static int cl_omap3_smc911x_reset_net_chip(int gpio)
+{
+ int err;
+
+ if (!gpio_is_valid(gpio))
+ return -EINVAL;
+
+ err = gpio_request(gpio, "eth rst");
+ if (err)
+ return err;
+
+ /* Set gpio as output and send a pulse */
+ gpio_direction_output(gpio, 1);
+ udelay(1);
+ gpio_set_value(gpio, 0);
+ mdelay(40);
+ gpio_set_value(gpio, 1);
+ mdelay(1);
+
+ return 0;
+}
+#else /* !CONFIG_OMAP_GPIO */
+static inline int cl_omap3_smc911x_reset_net_chip(int gpio) { return 0; }
+#endif /* CONFIG_OMAP_GPIO */
+
+int cl_omap3_smc911x_init(int id, int cs, u32 base_addr,
+ int (*reset)(int), int rst_gpio)
+{
+ int ret;
+
+ cl_omap3_smc911x_setup_net_chip_gmpc(cs, base_addr);
+
+ if (reset)
+ reset(rst_gpio);
+ else
+ cl_omap3_smc911x_reset_net_chip(rst_gpio);
+
+ ret = smc911x_initialize(id, base_addr);
+ if (ret > 0)
+ return ret;
+
+ printf("Failed initializing SMC911x! ");
+ return 0;
+}