setenv_hex("fdtsize", fdt_totalsize(fdt));
}
-static int karo_load_part(const char *part, void *addr, size_t len)
-{
- int ret;
- struct mtd_device *dev;
- struct part_info *part_info;
- u8 part_num;
- size_t actual;
-
- debug("Initializing mtd_parts\n");
- ret = mtdparts_init();
- if (ret)
- return ret;
-
- debug("Trying to find NAND partition '%s'\n", part);
- ret = find_dev_and_part(part, &dev, &part_num, &part_info);
- if (ret) {
- printf("Failed to find flash partition '%s': %d\n",
- part, ret);
-
- return ret;
- }
- debug("Found partition '%s': offset=%08x size=%08x\n",
- part, part_info->offset, part_info->size);
- if (part_info->size < len) {
- printf("Warning: partition '%s' smaller than requested size: %u; truncating data to %u byte\n",
- part, len, part_info->size);
- len = part_info->size;
- }
- debug("Reading NAND partition '%s' to %p\n", part, addr);
- ret = nand_read_skip_bad(&nand_info[0], part_info->offset, &len,
- &actual, len, addr);
- if (ret) {
- printf("Failed to load partition '%s' to %p\n", part, addr);
- return ret;
- }
- if (actual < len)
- printf("Read only %u of %u bytes due to bad blocks\n",
- actual, len);
-
- debug("Read %u byte from partition '%s' @ offset %08x\n",
- len, part, part_info->offset);
- return 0;
-}
-
static void *karo_fdt_load_dtb(void)
{
int ret;
{
int offs = fdt_node_offset_by_compatible(blob, -1, name);
- if (offs < 0) {
- debug("node '%s' not found: %s\n", name, fdt_strerror(offs));
- return;
+ while (offs >= 0) {
+ debug("Disabling node '%s'\n", name);
+ fdt_set_node_status(blob, offs, FDT_STATUS_DISABLED, 0);
+ offs = fdt_node_offset_by_compatible(blob, offs, name);
}
-
- debug("Disabling node '%s'\n", name);
- fdt_set_node_status(blob, offs, FDT_STATUS_DISABLED, 0);
}
void karo_fdt_fixup_touchpanel(void *blob, const char *panels[],
karo_set_fdtsize(blob);
}
+static int karo_fdt_disable_node_phandle(void *blob, const char *parent,
+ const char *name)
+{
+ const uint32_t *ph;
+ int off;
+
+ off = fdt_path_offset(blob, parent);
+ if (off < 0) {
+ printf("Failed to find node '%s'\n", parent);
+ return off;
+ }
+
+ ph = fdt_getprop(blob, off, name, NULL);
+ if (ph == NULL) {
+ debug("Failed to find '%s' phandle in node '%s'\n", name,
+ fdt_get_name(blob, off, NULL));
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*ph));
+ if (off <= 0) {
+ printf("Failed to find '%s' node via phandle %04x\n",
+ name, fdt32_to_cpu(*ph));
+ return -FDT_ERR_NOTFOUND;
+ }
+ return fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
+}
+
void karo_fdt_fixup_usb_otg(void *blob, const char *node, const char *phy)
{
const char *otg_mode = getenv("otg_mode");
int off;
int ret;
- const uint32_t *ph;
int disable_otg = 0;
int disable_phy_pins = 1;
} else if (otg_mode && strcmp(otg_mode, "otg") == 0) {
debug("Setting dr_mode to 'host'\n");
ret = fdt_setprop_string(blob, off, "dr_mode", "otg");
+ disable_phy_pins = 0;
} else {
if (otg_mode && strcmp(otg_mode, "none") != 0)
printf("Invalid 'otg_mode' setting '%s'; disabling usbotg port\n",
if ((!disable_phy_pins && !disable_otg) || ret)
goto out;
+ ret = karo_fdt_disable_node_phandle(blob, node, "vbus-supply");
+ if (ret)
+ goto out;
+
if (disable_otg) {
+ debug("Disabling usbphy\n");
ret = fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
if (ret)
goto out;
- }
- ph = fdt_getprop(blob, off, phy, NULL);
- if (ph == NULL) {
- printf("Failed to find '%s' phandle in node '%s'\n", phy,
- fdt_get_name(blob, off, NULL));
- goto out;
+ ret = karo_fdt_disable_node_phandle(blob, node, phy);
+ } else if (disable_phy_pins) {
+ debug("Removing 'vbus-supply' from usbotg node\n");
+ fdt_delprop(blob, off, "vbus-supply");
}
- off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*ph));
- if (off <= 0) {
- printf("Failed to find '%s' node via phandle %04x\n",
- phy, fdt32_to_cpu(*ph));
- goto out;
- }
-
- if (disable_otg) {
- debug("Disabling usbphy\n");
- ret = fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0);
- }
out:
if (ret)
printf("Failed to update usbotg: %s\n", fdt_strerror(ret));
karo_set_fdtsize(blob);
}
-static int karo_fdt_flexcan_enabled(void *blob)
+static inline int karo_fdt_flexcan_enabled(void *blob)
{
- const char *can_ifs[] = {
+ static const char *can_ifs[] = {
"can0",
"can1",
};
return 0;
}
-static void karo_fdt_set_lcd_pins(void *blob, const char *name)
+static inline void karo_fdt_set_lcd_pins(void *blob, const char *name)
{
int off = fdt_path_offset(blob, name);
u32 ph;
void karo_fdt_fixup_flexcan(void *blob, int xcvr_present)
{
+ int ret;
const char *xcvr_status = "disabled";
+ const char *otg_mode = getenv("otg_mode");
if (xcvr_present) {
if (karo_fdt_flexcan_enabled(blob)) {
- karo_fdt_set_lcd_pins(blob, "lcdif_23bit_pins_a");
- xcvr_status = "okay";
- } else {
+ if (!is_lvds()) {
+ debug("Changing LCD to use 23bits only\n");
+ karo_fdt_set_lcd_pins(blob, "lcdif_23bit_pins_a");
+ xcvr_status = NULL;
+ }
+ } else if (!is_lvds()) {
+ debug("Changing LCD to use 24bits\n");
karo_fdt_set_lcd_pins(blob, "lcdif_24bit_pins_a");
}
} else {
- const char *otg_mode = getenv("otg_mode");
+ int off = fdt_path_offset(blob, "can0");
+
+ if (off >= 0)
+ fdt_delprop(blob, off, "xceiver-supply");
+ off = fdt_path_offset(blob, "can1");
+ if (off >= 0)
+ fdt_delprop(blob, off, "xceiver-supply");
+ if (!is_lvds())
+ karo_fdt_set_lcd_pins(blob, "lcdif_24bit_pins_a");
+ }
- if (otg_mode && (strcmp(otg_mode, "host") == 0))
- karo_fdt_enable_node(blob, "can1", 0);
+ if (otg_mode && strcmp(otg_mode, "host") == 0)
+ karo_fdt_enable_node(blob, "can1", 0);
- karo_fdt_set_lcd_pins(blob, "lcdif_24bit_pins_a");
+ if (xcvr_status) {
+ debug("Disabling CAN XCVR\n");
+ ret = fdt_find_and_setprop(blob, "reg_can_xcvr", "status",
+ xcvr_status, strlen(xcvr_status) + 1, 1);
+ if (ret)
+ printf("Failed to disable CAN transceiver switch: %s\n",
+ fdt_strerror(ret));
}
- fdt_find_and_setprop(blob, "reg_can_xcvr", "status",
- xcvr_status, strlen(xcvr_status) + 1, 1);
}
void karo_fdt_del_prop(void *blob, const char *compat, phys_addr_t offs,
return ret;
}
-static int karo_fdt_set_display_alias(void *blob, const char *path,
- const char *name)
-{
- int ret;
- int off;
- size_t size = strlen(path) + strlen(name) + 2;
- char *display;
-
- display = malloc(size);
- if (display == NULL) {
- printf("%s: Failed to allocate buffer\n", __func__);
- return -ENOMEM;
- }
- sprintf(display, "%s/%s", path, name);
- if (strlen(display) != size - 1)
- hang();
- off = fdt_path_offset(blob, "/aliases");
- if (off == FDT_ERR_BADMAGIC)
- return -EINVAL;
- ret = fdt_resize(blob);
- if (ret < 0) {
- printf("%s: Failed to resize FDT: %s\n",
- __func__, fdt_strerror(ret));
- }
- if (off < 0) {
- off = fdt_add_subnode(blob, 0, "aliases");
- if (off < 0) {
- printf("%s: Failed to create 'aliases' node: %s\n",
- __func__, fdt_strerror(off));
- return off;
- }
- }
- ret = fdt_setprop_string(blob, off, "display", display);
- debug("setprop_string(display='%s') returned %d (%s)\n", display, ret,
- ret < 0 ? fdt_strerror(ret) : "OK");
- return ret;
-}
-
-const char *karo_fdt_set_display(const char *video_mode, const char *lcd_path,
- const char *lvds_path)
-{
- const char *vmode = NULL;
- int ret;
- void *blob = working_fdt;
-
- if (video_mode == NULL || strlen(video_mode) == 0)
- return NULL;
-
- vmode = strchr(video_mode, ':');
-
- if (lvds_path == NULL)
- return vmode ? vmode + 1 : video_mode;
-
- if (lvds_path != NULL && vmode != NULL) {
- if (strncmp(video_mode, "LVDS:", 5) == 0 ||
- strncmp(video_mode, "LVDS0:", 6) == 0) {
- ret = karo_fdt_set_display_alias(blob, lvds_path,
- "lvds-channel@0");
- } else if (strncmp(video_mode, "LVDS1:", 6) == 0) {
- ret = karo_fdt_set_display_alias(blob, lvds_path,
- "lvds-channel@1");
- } else {
- debug("%s: Syntax error in video_mode\n", __func__);
- return vmode + 1;
- }
- video_mode = vmode + 1;
- } else {
- int off;
-
- ret = karo_fdt_set_display_alias(blob, lcd_path,
- "display@di0");
-
- off = fdt_path_offset(blob, "lvds0");
- if (off >= 0) {
- ret = fdt_set_node_status(blob, off,
- FDT_STATUS_DISABLED, 0);
- }
- off = fdt_path_offset(blob, "lvds1");
- if (off >= 0) {
- ret = fdt_set_node_status(blob, off,
- FDT_STATUS_DISABLED, 0);
- }
- }
- if (ret) {
- printf("%s: failed to set 'display' alias: %s\n",
- __func__, fdt_strerror(ret));
- }
- return video_mode;
-}
-
int karo_fdt_update_fb_mode(void *blob, const char *name)
{
int off = fdt_path_offset(blob, "display");
return fdt_update_native_fb_mode(blob, off);
return off;
}
+
+#ifdef CONFIG_SYS_LVDS_IF
+int karo_fdt_get_lcd_bus_width(const void *blob, int default_width)
+{
+ int off = fdt_path_offset(blob, "display");
+
+ if (off >= 0) {
+ const uint32_t *prop;
+
+ prop = fdt_getprop(blob, off, "fsl,data-width", NULL);
+ if (prop)
+ return fdt32_to_cpu(*prop);
+ }
+ return default_width;
+}
+
+int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping)
+{
+ int off = fdt_path_offset(blob, "display");
+
+ if (off >= 0) {
+ const char *prop;
+
+ prop = fdt_getprop(blob, off, "fsl,data-mapping", NULL);
+ if (prop)
+ return strcmp(prop, "jeida") == 0;
+ }
+ return default_mapping;
+}
+
+u8 karo_fdt_get_lvds_channels(const void *blob)
+{
+ static const char *lvds_chans[] = {
+ "lvds0",
+ "lvds1",
+ };
+ u8 lvds_chan_mask = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(lvds_chans); i++) {
+ const char *status;
+ int off = fdt_path_offset(blob, lvds_chans[i]);
+
+ if (off < 0)
+ continue;
+
+ status = fdt_getprop(blob, off, "status", NULL);
+ if (status && strcmp(status, "okay") == 0) {
+ debug("%s is enabled\n", lvds_chans[i]);
+ lvds_chan_mask |= 1 << i;
+ }
+ }
+ return lvds_chan_mask;
+}
+#endif
+
+int karo_fdt_get_backlight_polarity(const void *blob)
+{
+#ifdef CONFIG_SYS_LVDS_IF
+ const char *backlight_node = "/backlight0";
+#else
+ const char *backlight_node = "/backlight";
+#endif
+ int off = fdt_path_offset(blob, "backlight"); /* first try alias */
+ const struct fdt_property *prop;
+ int len;
+
+ if (off < 0) {
+ /*
+ * if no 'backlight' alias exists try finding '/backlight0'
+ * or '/backlight' depending on LVDS or not
+ */
+ off = fdt_path_offset(blob, backlight_node);
+ if (off < 0) {
+ printf("/backlight node not found in DT\n");
+ return off;
+ }
+ }
+
+ prop = fdt_get_property(blob, off, "pwms", &len);
+ if (!prop)
+ printf("'pwms' property not found\n");
+ else
+ debug("'pwms' property has len %d\n", len);
+
+ len /= sizeof(u32);
+ if (prop && len > 3) {
+ const u32 *data = (const u32 *)prop->data;
+ return fdt32_to_cpu(data[3]) == 0;
+ }
+ return 0;
+}