[U-Boot] [PATCH 1/5] edid: add function to convert edid to fb_videomode

There may be some custom boards in the field which have an seperate eeprom chip to store edid informations in it. To make use of those edid information in the board code this patch add a function to convert edid to fb_videomode.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- common/edid.c | 29 +++++++++++++++++++++++++++++ include/edid.h | 3 +++ 2 files changed, 32 insertions(+)
diff --git a/common/edid.c b/common/edid.c index e66108f..8841c25 100644 --- a/common/edid.c +++ b/common/edid.c @@ -12,6 +12,7 @@
#include <common.h> #include <edid.h> +#include <linux/fb.h> #include <linux/ctype.h> #include <linux/string.h>
@@ -288,3 +289,31 @@ void edid_print_info(struct edid1_info *edid_info) if (!have_timing) printf("\tNone\n"); } + +void edid_to_fb_videomode(struct edid1_info *edid, struct fb_videomode *mode) +{ + struct edid_monitor_descriptor *monitor = &edid->monitor_details.descriptor[0]; + unsigned char *bytes = (unsigned char *)monitor; + struct edid_detailed_timing *timing = (struct edid_detailed_timing *)monitor; + + uint32_t pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing); + uint32_t h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing); + uint32_t h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing); + uint32_t h_sync_offset = EDID_DETAILED_TIMING_HSYNC_OFFSET(*timing); + uint32_t h_sync_width = EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*timing); + uint32_t v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing); + uint32_t v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing); + uint32_t v_sync_offset = EDID_DETAILED_TIMING_VSYNC_OFFSET(*timing); + uint32_t v_sync_width = EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*timing); + + mode->name = "EDID"; + mode->pixclock = pixclock; + mode->yres = v_active; + mode->xres = h_active; + mode->left_margin = h_blanking - h_sync_offset - h_sync_width; + mode->right_margin = h_sync_offset; + mode->upper_margin = v_blanking - v_sync_offset - v_sync_width; + mode->lower_margin = v_sync_offset; + mode->hsync_len = h_sync_width; + mode->vsync_len = v_sync_width; +} diff --git a/include/edid.h b/include/edid.h index 480a773..4423062 100644 --- a/include/edid.h +++ b/include/edid.h @@ -233,6 +233,9 @@ struct edid1_info { */ void edid_print_info(struct edid1_info *edid_info);
+struct fb_videomode; +void edid_to_fb_videomode(struct edid1_info *edid, struct fb_videomode *mode); + /** * Check the EDID info. *

Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg index bb6c60b..b9e107a 100644 --- a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg +++ b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg @@ -144,7 +144,7 @@ DATA 4 0x021b0404 0x00011006
/* set the default clock gate to save power */ DATA 4 0x020c4068 0x00C03F3F -DATA 4 0x020c406c 0x0030FC03 +DATA 4 0x020c406c 0x0030FC33 DATA 4 0x020c4070 0x0FFFC000 DATA 4 0x020c4074 0x3FF00000 DATA 4 0x020c4078 0x00FFF300

Hi Christian,
On 08/01/2014 08:24, Christian Gmeiner wrote:
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg index bb6c60b..b9e107a 100644 --- a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg +++ b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg @@ -144,7 +144,7 @@ DATA 4 0x021b0404 0x00011006
/* set the default clock gate to save power */ DATA 4 0x020c4068 0x00C03F3F -DATA 4 0x020c406c 0x0030FC03 +DATA 4 0x020c406c 0x0030FC33 DATA 4 0x020c4070 0x0FFFC000 DATA 4 0x020c4074 0x3FF00000 DATA 4 0x020c4078 0x00FFF300
I do not think a good idea to enable the clock here. We have to set only the clocks that are required for U-Boot, letting the other ones off to save power. This is a common file, and then all boards using it will have the ecspi-3 clock turned on, even if they do not require it.
Better is to set the clock inside the board file only for the boards (yours !) that need it, for example in board_early_init()
Best regards, Stefano Babic

Hi Stefano,
On 08/01/2014 08:24, Christian Gmeiner wrote:
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg index bb6c60b..b9e107a 100644 --- a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg +++ b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg @@ -144,7 +144,7 @@ DATA 4 0x021b0404 0x00011006
/* set the default clock gate to save power */ DATA 4 0x020c4068 0x00C03F3F -DATA 4 0x020c406c 0x0030FC03 +DATA 4 0x020c406c 0x0030FC33 DATA 4 0x020c4070 0x0FFFC000 DATA 4 0x020c4074 0x3FF00000 DATA 4 0x020c4078 0x00FFF300
I do not think a good idea to enable the clock here. We have to set only the clocks that are required for U-Boot, letting the other ones off to save power. This is a common file, and then all boards using it will have the ecspi-3 clock turned on, even if they do not require it.
Better is to set the clock inside the board file only for the boards (yours !) that need it, for example in board_early_init()
Sounds like a good plan... will rework this part for the next version.
thanks -- Christian Gmeiner, MSc

Hi Stefano,
On 08/01/2014 08:24, Christian Gmeiner wrote:
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg index bb6c60b..b9e107a 100644 --- a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg +++ b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg @@ -144,7 +144,7 @@ DATA 4 0x021b0404 0x00011006
/* set the default clock gate to save power */ DATA 4 0x020c4068 0x00C03F3F -DATA 4 0x020c406c 0x0030FC03 +DATA 4 0x020c406c 0x0030FC33 DATA 4 0x020c4070 0x0FFFC000 DATA 4 0x020c4074 0x3FF00000 DATA 4 0x020c4078 0x00FFF300
I do not think a good idea to enable the clock here. We have to set only the clocks that are required for U-Boot, letting the other ones off to save power. This is a common file, and then all boards using it will have the ecspi-3 clock turned on, even if they do not require it.
Better is to set the clock inside the board file only for the boards (yours !) that need it, for example in board_early_init()
Sounds like a good plan... will rework this part for the next version.
I thought more deeply about it and think that in the long term all ecspi clocks should get disabled and enabled as needed in the boards.
greets, -- Christian Gmeiner, MSc

Hi Christian,
On 09/01/2014 08:07, Christian Gmeiner wrote:
Hi Stefano,
On 08/01/2014 08:24, Christian Gmeiner wrote:
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg index bb6c60b..b9e107a 100644 --- a/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg +++ b/board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg @@ -144,7 +144,7 @@ DATA 4 0x021b0404 0x00011006
/* set the default clock gate to save power */ DATA 4 0x020c4068 0x00C03F3F -DATA 4 0x020c406c 0x0030FC03 +DATA 4 0x020c406c 0x0030FC33 DATA 4 0x020c4070 0x0FFFC000 DATA 4 0x020c4074 0x3FF00000 DATA 4 0x020c4078 0x00FFF300
I do not think a good idea to enable the clock here. We have to set only the clocks that are required for U-Boot, letting the other ones off to save power. This is a common file, and then all boards using it will have the ecspi-3 clock turned on, even if they do not require it.
Better is to set the clock inside the board file only for the boards (yours !) that need it, for example in board_early_init()
Sounds like a good plan... will rework this part for the next version.
I thought more deeply about it and think that in the long term all ecspi clocks should get disabled and enabled as needed in the boards.
Agree - a general U-Boot rule is to enable only what is really needed by U-Boot itself. Since a lot of time, the kernel does not make any assumption about what a bootcounter has done and configures the whole hardware itself (pinmux, clocks, ...).
In the long term we plan to move i.MX6 to use SPL, letting maybe only a few registers inside the imx image file and putting the setup inside SPL code. This will allow us in future to have a single image for all processor's variations (solo, dual,quad).
Best regards, Stefano Babic

This new function is used to set all display-timings properties based on fb_videomode.
display-timings { timing0 { clock-frequency = <25000000>; hactive = <640>; vactive = <480>; hback-porch = <48>; hfront-porch = <16>; vback-porch = <31>; vfront-porch = <12>; hsync-len = <96>; vsync-len = <2>; }; };
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- common/fdt_support.c | 23 +++++++++++++++++++++++ include/fdt_support.h | 3 +++ 2 files changed, 26 insertions(+)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 4e32b02..cf81a4b 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -11,6 +11,7 @@ #include <stdio_dev.h> #include <linux/ctype.h> #include <linux/types.h> +#include <linux/fb.h> #include <asm/global_data.h> #include <libfdt.h> #include <fdt_support.h> @@ -1342,6 +1343,28 @@ err_size: #endif
/* + * fdt_add_display_timings: add display-timings properties + * + * @fdt: ptr to device tree + * @noff: node to update + * @mode: ptr to b_videomode + */ +void fdt_add_display_timings(void *fdt, int noff, struct fb_videomode *mode) +{ + if (noff != -FDT_ERR_NOTFOUND) { + fdt_setprop_u32(fdt, noff, "clock-frequency", mode->pixclock); + fdt_setprop_u32(fdt, noff, "hactive", mode->xres); + fdt_setprop_u32(fdt, noff, "vactive", mode->yres); + fdt_setprop_u32(fdt, noff, "hback-porch", mode->left_margin); + fdt_setprop_u32(fdt, noff, "hfront-porch", mode->right_margin); + fdt_setprop_u32(fdt, noff, "vback-porch", mode->upper_margin); + fdt_setprop_u32(fdt, noff, "vfront-porch", mode->lower_margin); + fdt_setprop_u32(fdt, noff, "hsync-len", mode->hsync_len); + fdt_setprop_u32(fdt, noff, "vsync-len", mode->vsync_len); + } +} + +/* * Verify the physical address of device tree node for a given alias * * This function locates the device tree node of a given alias, and then diff --git a/include/fdt_support.h b/include/fdt_support.h index 9871e2f..1c54880 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -82,6 +82,9 @@ int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle); unsigned int fdt_create_phandle(void *fdt, int nodeoffset); int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
+struct fb_videomode; +void fdt_add_display_timings(void *blob, int noff, struct fb_videomode *mode); + int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr); u64 fdt_get_base_address(void *fdt, int node);

Hi Christian,
On 08/01/2014 08:24, Christian Gmeiner wrote:
This new function is used to set all display-timings properties based on fb_videomode.
display-timings { timing0 { clock-frequency = <25000000>; hactive = <640>; vactive = <480>; hback-porch = <48>; hfront-porch = <16>; vback-porch = <31>; vfront-porch = <12>; hsync-len = <96>; vsync-len = <2>; }; };
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
common/fdt_support.c | 23 +++++++++++++++++++++++ include/fdt_support.h | 3 +++ 2 files changed, 26 insertions(+)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 4e32b02..cf81a4b 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -11,6 +11,7 @@ #include <stdio_dev.h> #include <linux/ctype.h> #include <linux/types.h> +#include <linux/fb.h> #include <asm/global_data.h> #include <libfdt.h> #include <fdt_support.h> @@ -1342,6 +1343,28 @@ err_size: #endif
/*
- fdt_add_display_timings: add display-timings properties
- @fdt: ptr to device tree
- @noff: node to update
- @mode: ptr to b_videomode
- */
+void fdt_add_display_timings(void *fdt, int noff, struct fb_videomode *mode) +{
- if (noff != -FDT_ERR_NOTFOUND) {
fdt_setprop_u32(fdt, noff, "clock-frequency", mode->pixclock);
fdt_setprop_u32(fdt, noff, "hactive", mode->xres);
fdt_setprop_u32(fdt, noff, "vactive", mode->yres);
fdt_setprop_u32(fdt, noff, "hback-porch", mode->left_margin);
fdt_setprop_u32(fdt, noff, "hfront-porch", mode->right_margin);
fdt_setprop_u32(fdt, noff, "vback-porch", mode->upper_margin);
fdt_setprop_u32(fdt, noff, "vfront-porch", mode->lower_margin);
fdt_setprop_u32(fdt, noff, "hsync-len", mode->hsync_len);
fdt_setprop_u32(fdt, noff, "vsync-len", mode->vsync_len);
- }
+}
+/*
- Verify the physical address of device tree node for a given alias
- This function locates the device tree node of a given alias, and then
diff --git a/include/fdt_support.h b/include/fdt_support.h index 9871e2f..1c54880 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -82,6 +82,9 @@ int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle); unsigned int fdt_create_phandle(void *fdt, int nodeoffset); int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
+struct fb_videomode; +void fdt_add_display_timings(void *blob, int noff, struct fb_videomode *mode);
int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr); u64 fdt_get_base_address(void *fdt, int node);
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
Anatolji, what do you think as best solution we have to follow for display setting ?
Best regards, Stefano Babic

Hi Stefano, 2014/1/8 Stefano Babic sbabic@denx.de:
Hi Christian,
On 08/01/2014 08:24, Christian Gmeiner wrote:
This new function is used to set all display-timings properties based on fb_videomode.
display-timings { timing0 { clock-frequency = <25000000>; hactive = <640>; vactive = <480>; hback-porch = <48>; hfront-porch = <16>; vback-porch = <31>; vfront-porch = <12>; hsync-len = <96>; vsync-len = <2>; }; };
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
common/fdt_support.c | 23 +++++++++++++++++++++++ include/fdt_support.h | 3 +++ 2 files changed, 26 insertions(+)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 4e32b02..cf81a4b 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -11,6 +11,7 @@ #include <stdio_dev.h> #include <linux/ctype.h> #include <linux/types.h> +#include <linux/fb.h> #include <asm/global_data.h> #include <libfdt.h> #include <fdt_support.h> @@ -1342,6 +1343,28 @@ err_size: #endif
/*
- fdt_add_display_timings: add display-timings properties
- @fdt: ptr to device tree
- @noff: node to update
- @mode: ptr to b_videomode
- */
+void fdt_add_display_timings(void *fdt, int noff, struct fb_videomode *mode) +{
if (noff != -FDT_ERR_NOTFOUND) {
fdt_setprop_u32(fdt, noff, "clock-frequency", mode->pixclock);
fdt_setprop_u32(fdt, noff, "hactive", mode->xres);
fdt_setprop_u32(fdt, noff, "vactive", mode->yres);
fdt_setprop_u32(fdt, noff, "hback-porch", mode->left_margin);
fdt_setprop_u32(fdt, noff, "hfront-porch", mode->right_margin);
fdt_setprop_u32(fdt, noff, "vback-porch", mode->upper_margin);
fdt_setprop_u32(fdt, noff, "vfront-porch", mode->lower_margin);
fdt_setprop_u32(fdt, noff, "hsync-len", mode->hsync_len);
fdt_setprop_u32(fdt, noff, "vsync-len", mode->vsync_len);
}
+}
+/*
- Verify the physical address of device tree node for a given alias
- This function locates the device tree node of a given alias, and then
diff --git a/include/fdt_support.h b/include/fdt_support.h index 9871e2f..1c54880 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -82,6 +82,9 @@ int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle); unsigned int fdt_create_phandle(void *fdt, int nodeoffset); int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
+struct fb_videomode; +void fdt_add_display_timings(void *blob, int noff, struct fb_videomode *mode);
int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr); u64 fdt_get_base_address(void *fdt, int node);
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
The problem for me here is that DT only does not work in my case. As it is possible to attach different panels/displays via lvds (different timings and resolutions) we have put an at24 on our print, which contains the suitable EDID data.
So I need to readout the at24 every boot and need to manipulate the loaded (emmc) DT.
Anatolji, what do you think as best solution we have to follow for display setting ?
thanks -- Christian Gmeiner, MSc

Hi Christian,
On 09/01/2014 08:12, Christian Gmeiner wrote:
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
The problem for me here is that DT only does not work in my case. As it is possible to attach different panels/displays via lvds (different timings and resolutions) we have put an at24 on our print, which contains the suitable EDID data.
So I need to readout the at24 every boot and need to manipulate the loaded (emmc) DT.
Understood, thanks for clarification. Agree that we need functions for EDID manipulation. My only concern remains if we need a temporary conversion to videomode as in this patch, or we go towards a edid-to-fdt() function.
Regards, Stefano Babic

Hi Stefano,
On 01/09/2014 03:44 AM, Stefano Babic wrote:
Hi Christian,
On 09/01/2014 08:12, Christian Gmeiner wrote:
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
The problem for me here is that DT only does not work in my case. As it is possible to attach different panels/displays via lvds (different timings and resolutions) we have put an at24 on our print, which contains the suitable EDID data.
So I need to readout the at24 every boot and need to manipulate the loaded (emmc) DT.
Understood, thanks for clarification. Agree that we need functions for EDID manipulation. My only concern remains if we need a temporary conversion to videomode as in this patch, or we go towards a edid-to-fdt() function.
I'd really like to keep Christian's patch and use it to remove the hard-coded resolutions as shown in SabreSD and Nitrogen6X boards:
http://git.denx.de/?p=u-boot.git;a=blob;f=board/freescale/mx6sabresd/mx6sabr... http://git.denx.de/?p=u-boot.git;a=blob;f=board/boundary/nitrogen6x/nitrogen...
Regards,
Eric

Hi Eric,
On 09/01/2014 15:52, Eric Nelson wrote:
Hi Stefano,
On 01/09/2014 03:44 AM, Stefano Babic wrote:
Hi Christian,
On 09/01/2014 08:12, Christian Gmeiner wrote:
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
The problem for me here is that DT only does not work in my case. As it is possible to attach different panels/displays via lvds (different timings and resolutions) we have put an at24 on our print, which contains the suitable EDID data.
So I need to readout the at24 every boot and need to manipulate the loaded (emmc) DT.
Understood, thanks for clarification. Agree that we need functions for EDID manipulation. My only concern remains if we need a temporary conversion to videomode as in this patch, or we go towards a edid-to-fdt() function.
I'd really like to keep Christian's patch and use it to remove the hard-coded resolutions as shown in SabreSD and Nitrogen6X boards:
http://git.denx.de/?p=u-boot.git;a=blob;f=board/freescale/mx6sabresd/mx6sabresd.c;h=9dbe605cf4a5a8ba16c674f14b894ccb59bece9f;hb=HEAD#l266 http://git.denx.de/?p=u-boot.git;a=blob;f=board/boundary/nitrogen6x/nitrogen6x.c;h=53cb8dffd0d534629a4de5c7b9798733015adb6e;hb=HEAD#l520
ok - I see also that Christian's patch fills the gap with the display setup in fdt.
Regards, Stefano

On 01/09/2014 07:52 AM, Eric Nelson wrote:
Hi Stefano,
On 01/09/2014 03:44 AM, Stefano Babic wrote:
Hi Christian,
On 09/01/2014 08:12, Christian Gmeiner wrote:
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
The problem for me here is that DT only does not work in my case. As it is possible to attach different panels/displays via lvds (different timings and resolutions) we have put an at24 on our print, which contains the suitable EDID data.
So I need to readout the at24 every boot and need to manipulate the loaded (emmc) DT.
Understood, thanks for clarification. Agree that we need functions for EDID manipulation. My only concern remains if we need a temporary conversion to videomode as in this patch, or we go towards a edid-to-fdt() function.
In my opinion, without having read the patch or the rest of the thread: Both the DT and the EDID are sources for information about supported video modes. Those two sources (and any others that might appear later like ACPI or hard-coded modes inside U-Boot) should be directly converted to U-Boot's internal mode representation, rather than chaining conversions e.g. EDID -> DT -> internal.

HI Stephen.
2014/1/9 Stephen Warren swarren@wwwdotorg.org:
On 01/09/2014 07:52 AM, Eric Nelson wrote:
Hi Stefano,
On 01/09/2014 03:44 AM, Stefano Babic wrote:
Hi Christian,
On 09/01/2014 08:12, Christian Gmeiner wrote:
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
The problem for me here is that DT only does not work in my case. As it is possible to attach different panels/displays via lvds (different timings and resolutions) we have put an at24 on our print, which contains the suitable EDID data.
So I need to readout the at24 every boot and need to manipulate the loaded (emmc) DT.
Understood, thanks for clarification. Agree that we need functions for EDID manipulation. My only concern remains if we need a temporary conversion to videomode as in this patch, or we go towards a edid-to-fdt() function.
In my opinion, without having read the patch or the rest of the thread: Both the DT and the EDID are sources for information about supported video modes. Those two sources (and any others that might appear later like ACPI or hard-coded modes inside U-Boot) should be directly converted to U-Boot's internal mode representation, rather than chaining conversions e.g. EDID -> DT -> internal.
The patch does this: EDID -> internal -> DT
But it depends a little bit on your definition of "internal".
greets -- Christian Gmeiner, MSc

Hi Stefano,
On Wed, 08 Jan 2014 11:53:39 +0100 Stefano Babic sbabic@denx.de wrote: ...
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
Anatolji, what do you think as best solution we have to follow for display setting ?
many drivers use struct fb_videomode internally and this display-timings binding already exists in linux, so I think a function for converting from fb_videomode to DT is useful. However we should probably extend this current implementation of the function, e.g. rename it to fdt_update_display_timings() and pass more arguments: node compatible and the name of the parent node containing the display-timings node. The code for searching the display-timings node is also needed for other boards, so if it is in the function itself, it will simplify the usage.
This function could look for display-timings node and create it if it doesn't exist. Or update the existing node with new info.
Thanks,
Anatolij

2014/1/12 Anatolij Gustschin agust@denx.de:
Hi Stefano,
On Wed, 08 Jan 2014 11:53:39 +0100 Stefano Babic sbabic@denx.de wrote: ...
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
Anatolji, what do you think as best solution we have to follow for display setting ?
many drivers use struct fb_videomode internally and this display-timings binding already exists in linux, so I think a function for converting from fb_videomode to DT is useful. However we should probably extend this current implementation of the function, e.g. rename it to fdt_update_display_timings() and pass more arguments: node compatible and the name of the parent node containing the display-timings node. The code for searching the display-timings node is also needed for other boards, so if it is in the function itself, it will simplify the usage.
This function could look for display-timings node and create it if it doesn't exist. Or update the existing node with new info.
Thanks for your comments... will come up with something in the next version of the patch series.
thanks -- Christian Gmeiner, MSc

Hi all
2014/1/14 Christian Gmeiner christian.gmeiner@gmail.com:
2014/1/12 Anatolij Gustschin agust@denx.de:
Hi Stefano,
On Wed, 08 Jan 2014 11:53:39 +0100 Stefano Babic sbabic@denx.de wrote: ...
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
Anatolji, what do you think as best solution we have to follow for display setting ?
many drivers use struct fb_videomode internally and this display-timings binding already exists in linux, so I think a function for converting from fb_videomode to DT is useful. However we should probably extend this current implementation of the function, e.g. rename it to fdt_update_display_timings() and pass more arguments: node compatible and the name of the parent node containing the display-timings node. The code for searching the display-timings node is also needed for other boards, so if it is in the function itself, it will simplify the usage.
This function could look for display-timings node and create it if it doesn't exist. Or update the existing node with new info.
Thanks for your comments... will come up with something in the next version of the patch series.
I have some time to work on this patch.
Anatolij are you happy witht the following functions?
int fdt_find_display_timings(void *fdt, const char *compat, const char *parent) { int coff = fdt_node_offset_by_compatible(fdt, -1, compat); int poff = fdt_subnode_offset(fdt, coff, parent); int timings = fdt_subnode_offset(fdt, poff, "display-timings");
return timings; }
int fdt_update_display_timings(void *fdt, const char *compat, const char *parent, struct fb_videomode *mode) { int timings = fdt_find_display_timings(fdt, compat, parent);
/* check if display-timings subnode does exist */ if (timings == -FDT_ERR_NOTFOUND) { return timings; }
/* set all needed properties */ if (timings != -FDT_ERR_NOTFOUND) { fdt_setprop_u32(fdt, noff, "clock-frequency", mode->pixclock); fdt_setprop_u32(fdt, noff, "hactive", mode->xres); fdt_setprop_u32(fdt, noff, "vactive", mode->yres); fdt_setprop_u32(fdt, noff, "hback-porch", mode->left_margin); fdt_setprop_u32(fdt, noff, "hfront-porch", mode->right_margin); fdt_setprop_u32(fdt, noff, "vback-porch", mode->upper_margin); fdt_setprop_u32(fdt, noff, "vfront-porch", mode->lower_margin); fdt_setprop_u32(fdt, noff, "hsync-len", mode->hsync_len); fdt_setprop_u32(fdt, noff, "vsync-len", mode->vsync_len); }
return 0; }
This would allow us to update an existing display-timings node via
fdt_update_display_timings(blob, "fsl,imx6q-ldb", "lvds-channel", mode);
Note: not even compile tested :)
thanks -- Christian Gmeiner, MSc

2014-01-16 12:44 GMT+01:00 Christian Gmeiner christian.gmeiner@gmail.com:
Hi all
2014/1/14 Christian Gmeiner christian.gmeiner@gmail.com:
2014/1/12 Anatolij Gustschin agust@denx.de:
Hi Stefano,
On Wed, 08 Jan 2014 11:53:39 +0100 Stefano Babic sbabic@denx.de wrote: ...
Agree that we have to sync u-boot and kernel, and this can be a way in the short term.
I am asking if this is in the long term the best way to do it. You are converting EDID values to fb_videomode *mode, and then again to the device node as required by DT. We have already had some talks about moving U-Boot configuration to DT, that is U-Boot can be also configured by a DT file (see for example support for Nvidia processors, they already support DT in U-Boot).
Anatolji, what do you think as best solution we have to follow for display setting ?
many drivers use struct fb_videomode internally and this display-timings binding already exists in linux, so I think a function for converting from fb_videomode to DT is useful. However we should probably extend this current implementation of the function, e.g. rename it to fdt_update_display_timings() and pass more arguments: node compatible and the name of the parent node containing the display-timings node. The code for searching the display-timings node is also needed for other boards, so if it is in the function itself, it will simplify the usage.
This function could look for display-timings node and create it if it doesn't exist. Or update the existing node with new info.
Thanks for your comments... will come up with something in the next version of the patch series.
I have some time to work on this patch.
Anatolij are you happy witht the following functions?
int fdt_find_display_timings(void *fdt, const char *compat, const char *parent) { int coff = fdt_node_offset_by_compatible(fdt, -1, compat); int poff = fdt_subnode_offset(fdt, coff, parent); int timings = fdt_subnode_offset(fdt, poff, "display-timings");
return timings;
}
int fdt_update_display_timings(void *fdt, const char *compat, const char *parent, struct fb_videomode *mode) { int timings = fdt_find_display_timings(fdt, compat, parent);
/* check if display-timings subnode does exist */ if (timings == -FDT_ERR_NOTFOUND) { return timings; } /* set all needed properties */ if (timings != -FDT_ERR_NOTFOUND) { fdt_setprop_u32(fdt, noff, "clock-frequency", mode->pixclock); fdt_setprop_u32(fdt, noff, "hactive", mode->xres); fdt_setprop_u32(fdt, noff, "vactive", mode->yres); fdt_setprop_u32(fdt, noff, "hback-porch", mode->left_margin); fdt_setprop_u32(fdt, noff, "hfront-porch", mode->right_margin); fdt_setprop_u32(fdt, noff, "vback-porch", mode->upper_margin); fdt_setprop_u32(fdt, noff, "vfront-porch", mode->lower_margin); fdt_setprop_u32(fdt, noff, "hsync-len", mode->hsync_len); fdt_setprop_u32(fdt, noff, "vsync-len", mode->vsync_len); } return 0;
}
This would allow us to update an existing display-timings node via
fdt_update_display_timings(blob, "fsl,imx6q-ldb", "lvds-channel", mode);
Note: not even compile tested :)
I got no feedback over some months - bad. But okay I really want to get all the bits of our imx6 based board upstream as soon as possible. So has something changed in that area?
In the end I want to read EDID stored in an eeprom and put it into the device tree (patching or creating new node).
greets -- Christian Gmeiner, MSc

This patch add support for one device of the Bachmann OT1200 series - the mr variant.
My first attemp was to use one u-boot binary for all OT1200 devices, but as I need to load a device-specific devicetree I decided to go this way.
Following components are used: + ethernet + usb + i2c + display connected via ldb (init and usage in linux only) + emmc
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- board/bachmann/ot1200/Makefile | 9 ++ board/bachmann/ot1200/ot1200.c | 246 ++++++++++++++++++++++++++++++++++++++++ boards.cfg | 1 + include/configs/ot1200.h | 241 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 497 insertions(+) create mode 100644 board/bachmann/ot1200/Makefile create mode 100644 board/bachmann/ot1200/ot1200.c create mode 100644 include/configs/ot1200.h
diff --git a/board/bachmann/ot1200/Makefile b/board/bachmann/ot1200/Makefile new file mode 100644 index 0000000..1bd42e8 --- /dev/null +++ b/board/bachmann/ot1200/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2012-2013, Guennadi Liakhovetski lg@denx.de +# (C) Copyright 2012-2013 Freescale Semiconductor, Inc. +# Copyright (C) 2013, Boundary Devices info@boundarydevices.com +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := ot1200.o diff --git a/board/bachmann/ot1200/ot1200.c b/board/bachmann/ot1200/ot1200.c new file mode 100644 index 0000000..6a884c2 --- /dev/null +++ b/board/bachmann/ot1200/ot1200.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2013, Bachmann electronic GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/iomux.h> +#include <asm/arch/mx6-pins.h> +#include <asm/imx-common/iomux-v3.h> +#include <asm/imx-common/mxc_i2c.h> +#include <mmc.h> +#include <fsl_esdhc.h> +#include <netdev.h> +#include <i2c.h> +#include <pca953x.h> +#include <edid.h> +#include <linux/fb.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ + PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \ + PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ + PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + +#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) + +#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ + PAD_CTL_ODE | PAD_CTL_SRE_FAST) + +#define OUTPUT_40OHM (PAD_CTL_SPEED_MED|PAD_CTL_DSE_40ohm) + +int dram_init(void) +{ + gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE); + + return 0; +} + +static iomux_v3_cfg_t const uart1_pads[] = { + MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL), + MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL), +}; + +static void setup_iomux_uart(void) +{ + imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads)); +} + +static iomux_v3_cfg_t const enet_pads[] = { + MX6_PAD_KEY_ROW1__ENET_COL | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_KEY_COL3__ENET_CRS | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_GPIO_16__ENET_ETHERNET_REF_OUT | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_GPIO_18__ENET_RX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_RXD0__ENET_RDATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_RXD1__ENET_RDATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_KEY_COL2__ENET_RDATA_2 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_KEY_COL0__ENET_RDATA_3 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_CRS_DV__ENET_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_TXD0__ENET_TDATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_TXD1__ENET_TDATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_KEY_ROW2__ENET_TDATA_2 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_KEY_ROW0__ENET_TDATA_3 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_TX_EN__ENET_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), +}; + +static void setup_iomux_enet(void) +{ + imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads)); +} + +int board_early_init_f(void) +{ + setup_iomux_uart(); + setup_iomux_enet(); + return 0; +} + +static iomux_v3_cfg_t const ecspi1_pads[] = { + MX6_PAD_DISP0_DAT3__ECSPI3_SS0 | MUX_PAD_CTRL(SPI_PAD_CTRL), + MX6_PAD_DISP0_DAT4__ECSPI3_SS1 | MUX_PAD_CTRL(SPI_PAD_CTRL), + MX6_PAD_DISP0_DAT2__ECSPI3_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL), + MX6_PAD_DISP0_DAT1__ECSPI3_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL), + MX6_PAD_DISP0_DAT0__ECSPI3_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL), +}; + +void setup_spi(void) +{ + imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads)); +} + +static iomux_v3_cfg_t const usdhc3_pads[] = { + MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + MX6_PAD_SD3_RST__USDHC3_RST | MUX_PAD_CTRL(USDHC_PAD_CTRL), +}; + +int board_mmc_getcd(struct mmc *mmc) +{ + return 1; +} + +struct fsl_esdhc_cfg usdhc_cfg[] = { + {USDHC3_BASE_ADDR}, +}; + +int board_mmc_init(bd_t *bis) +{ + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); + usdhc_cfg[0].max_bus_width = 8; + + imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads)); + + return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); +} + +#define PC MUX_PAD_CTRL(I2C_PAD_CTRL) + +/* I2C2 - EDID */ +static struct i2c_pads_info i2c_pad_info1 = { + .scl = { + .i2c_mode = MX6_PAD_EIM_EB2__I2C2_SCL | PC, + .gpio_mode = MX6_PAD_EIM_EB2__GPIO_2_30 | PC, + .gp = IMX_GPIO_NR(2, 30) + }, + .sda = { + .i2c_mode = MX6_PAD_EIM_D16__I2C2_SDA | PC, + .gpio_mode = MX6_PAD_EIM_D16__GPIO_3_16 | PC, + .gp = IMX_GPIO_NR(3, 16) + } +}; + +/* I2C3 - IO expander */ +static struct i2c_pads_info i2c_pad_info2 = { + .scl = { + .i2c_mode = MX6_PAD_EIM_D17__I2C3_SCL | PC, + .gpio_mode = MX6_PAD_EIM_D17__GPIO_3_17 | PC, + .gp = IMX_GPIO_NR(3, 17) + }, + .sda = { + .i2c_mode = MX6_PAD_EIM_D18__I2C3_SDA | PC, + .gpio_mode = MX6_PAD_EIM_D18__GPIO_3_18 | PC, + .gp = IMX_GPIO_NR(3, 18) + } +}; + +static iomux_v3_cfg_t const pwm_pad[] = { + MX6_PAD_SD1_CMD__PWM4_PWMO | MUX_PAD_CTRL(OUTPUT_40OHM), +}; + +static void leds_on(void) +{ + i2c_set_bus_num(2); + pca953x_set_dir(0x20, 0xffff, PCA953X_DIR_OUT); + pca953x_set_val(0x20, 0xffff, 0x0); +} + +static void backlight_off(void) +{ + unsigned gpio = IMX_GPIO_NR(2, 0); + //gpio_direction_input(gpio); + gpio_direction_output(gpio, 0); + //gpio_set_value(gpio, 0); +} + +#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) +void ft_board_setup(void *blob, bd_t *bd) +{ + struct edid1_info edid; + struct fb_videomode mode; + + i2c_set_bus_num(1); + if (i2c_read(0x52, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) { + puts("Error reading EDID content.\n"); + return; + } + + if (edid_check_info(&edid)) { + puts("Content isn't valid EDID.\n"); + return; + } + + edid_to_fb_videomode(&edid, &mode); + + /* find display-timings node */ + int noff = fdt_node_offset_by_compatible(blob, -1, "fsl,imx6q-ldb"); + int channel = fdt_subnode_offset(blob, noff, "lvds-channel"); // lvds-channel@0 + int timings = fdt_subnode_offset(blob, channel, "display-timings"); + + /* clean-up all the mess */ + fdt_del_node(blob, timings); + fdt_add_subnode(blob, channel, "display-timings"); + timings = fdt_subnode_offset(blob, channel, "display-timings"); + int final = fdt_add_subnode(blob, timings, "timing"); + + /* fill with useful values */ + fdt_add_display_timings(blob, final, &mode); + + return; +} +#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */ + +int board_init(void) +{ + gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; + + backlight_off(); + + setup_spi(); + + setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); + setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2); + + leds_on(); + + return 0; +} + +int checkboard(void) +{ + puts("Board: "CONFIG_SYS_BOARD" "CONFIG_SYS_VARIANT"\n"); + return 0; +} diff --git a/boards.cfg b/boards.cfg index c602a16..d5175f5 100644 --- a/boards.cfg +++ b/boards.cfg @@ -295,6 +295,7 @@ Active arm armv7 mx6 - udoo udoo_qua Active arm armv7 mx6 - wandboard wandboard_dl wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024 Fabio Estevam fabio.estevam@freescale.com Active arm armv7 mx6 - wandboard wandboard_quad wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q2g.cfg,MX6Q,DDR_MB=2048 Fabio Estevam fabio.estevam@freescale.com Active arm armv7 mx6 - wandboard wandboard_solo wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s.cfg,MX6S,DDR_MB=512 Fabio Estevam fabio.estevam@freescale.com +Active arm armv7 mx6 bachmann ot1200 ot1200_mr ot1200:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg,SYS_VARIANT="mr",MX6Q Active arm armv7 mx6 boundary nitrogen6x mx6qsabrelite nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q.cfg,MX6Q,DDR_MB=1024,SABRELITE Eric Nelson eric.nelson@boundarydevices.com Active arm armv7 mx6 boundary nitrogen6x nitrogen6dl nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024 Eric Nelson eric.nelson@boundarydevices.com Active arm armv7 mx6 boundary nitrogen6x nitrogen6dl2g nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl2g.cfg,MX6DL,DDR_MB=2048 Eric Nelson eric.nelson@boundarydevices.com diff --git a/include/configs/ot1200.h b/include/configs/ot1200.h new file mode 100644 index 0000000..1c1e5fc --- /dev/null +++ b/include/configs/ot1200.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2013, Bachmann electronic GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_MX6 +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO + +#include <asm/arch/imx-regs.h> +#include <asm/imx-common/gpio.h> + +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_INITRD_TAG +#define CONFIG_REVISION_TAG + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (10 * 1024 * 1024) + +#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_MXC_GPIO + +#define CONFIG_CMD_FUSE +#ifdef CONFIG_CMD_FUSE +#define CONFIG_MXC_OCOTP +#endif + +/* UART Configs */ +#define CONFIG_MXC_UART +#define CONFIG_MXC_UART_BASE UART1_BASE + +/* SF Configs */ +#define CONFIG_CMD_SF +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_STMICRO +#define CONFIG_MXC_SPI +#define CONFIG_SF_DEFAULT_BUS 2 +#define CONFIG_SF_DEFAULT_CS (0|(IMX_GPIO_NR(1, 3)<<8)) +#define CONFIG_SF_DEFAULT_SPEED 25000000 +#define CONFIG_SF_DEFAULT_MODE (SPI_MODE_0) + +/* IO expander */ +#define CONFIG_PCA953X +#define CONFIG_SYS_I2C_PCA953X_ADDR 0x20 +#define CONFIG_SYS_I2C_PCA953X_WIDTH { {0x20, 16} } +#define CONFIG_CMD_PCA953X +#define CONFIG_CMD_PCA953X_INFO + +/* I2C Configs */ +#define CONFIG_CMD_I2C +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_SPEED 100000 + +/* OF Configs */ +#define CONFIG_I2C_EDID +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_BOARD_SETUP + +/* OCOTP Configs */ +#define CONFIG_CMD_IMXOTP +#ifdef CONFIG_CMD_IMXOTP +#define CONFIG_IMX_OTP +#define IMX_OTP_BASE OCOTP_BASE_ADDR +#define IMX_OTP_ADDR_MAX 0x7F +#define IMX_OTP_DATA_ERROR_VAL 0xBADABADA +#define IMX_OTPWRITE_ENABLED +#endif + +/* MMC Configs */ +#define CONFIG_FSL_ESDHC +#define CONFIG_FSL_USDHC +#define CONFIG_SYS_FSL_ESDHC_ADDR 0 +#define CONFIG_SYS_FSL_USDHC_NUM 2 + +#define CONFIG_MMC +#define CONFIG_CMD_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_BOUNCE_BUFFER + +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#define CONFIG_CMD_NET +#define CONFIG_FEC_MXC +#define CONFIG_MII +#define IMX_FEC_BASE ENET_BASE_ADDR +#define CONFIG_FEC_XCV_TYPE MII100 +#define CONFIG_ETHPRIME "FEC" +#define CONFIG_FEC_MXC_PHYADDR 0x5 +#define CONFIG_PHYLIB + +/* Miscellaneous commands */ +#define CONFIG_CMD_BMODE +#define CONFIG_CMD_SETEXPR + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 115200 + +/* Command definition */ +#include <config_cmd_default.h> + +#undef CONFIG_CMD_IMLS + +#define CONFIG_BOOTDELAY 1 + +#define CONFIG_PREBOOT "" + +#define CONFIG_LOADADDR 0x12000000 +#define CONFIG_SYS_TEXT_BASE 0x17800000 + +/* Miscellaneous configurable options */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT "U-Boot > " +#define CONFIG_SYS_CBSIZE 1024 + +/* Print Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + +#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +#define CONFIG_CMDLINE_EDITING + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR +#define PHYS_SDRAM_SIZE (1u * 1024 * 1024 * 1024) /* TODO: needed? */ + +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM +#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR +#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE + +#define CONFIG_SYS_INIT_SP_OFFSET \ + (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE) +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET) + +/* FLASH and environment organization */ +#define CONFIG_SYS_NO_FLASH + +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_SIZE (8 * 1024) /* 8 kb */ +#define CONFIG_ENV_OFFSET (768 * 1024) +#define CONFIG_ENV_SECT_SIZE (8 * 1024) +#define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS +#define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS +#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE +#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED + +#define CONFIG_OF_LIBFDT +#define CONFIG_CMD_BOOTZ + +#ifndef CONFIG_SYS_DCACHE_OFF +#define CONFIG_CMD_CACHE +#endif + +#define CONFIG_CMD_BOOTZ +#define CONFIG_SUPPORT_RAW_INITRD + +/* FS Configs */ +#define CONFIG_CMD_EXT3 +#define CONFIG_CMD_EXT4 +#define CONFIG_DOS_PARTITION +#define CONFIG_CMD_FS_GENERIC + +/* needed for run-in etc. */ +#define CONFIG_BOOTP_SERVERIP +#define CONFIG_BOOTP_BOOTFILE + +/* + * Memory layout for where various images get loaded by boot scripts + */ +#define MEM_LAYOUT_ENV_SETTINGS \ + "scriptaddr=0x14000000\0" \ + "kernel_addr_r=0x10000000\0" \ + "fdt_addr_r=0x11000000\0" \ + "ramdisk_addr_r=0x12A00000\0" \ + "fdt_high=0xffffffff\0" \ + "initrd_high=0xffffffff\0" + +#ifdef CONFIG_CMD_MMC +#define BOOTCMDS_MMC \ + "mmc_boot=" \ + "setenv devtype mmc; " \ + "if mmc dev ${devnum}; then " \ + "run scan_boot; " \ + "fi\0" \ + "bootcmd_mmc0=setenv devnum 0; run mmc_boot;\0" +#define BOOT_TARGETS_MMC "mmc0" +#endif + +#define BOOTCMDS_COMMON \ + "rootpart=2\0" \ + \ + "script_boot=" \ + "if load ${devtype} ${devnum}:${rootpart} " \ + "${scriptaddr} ${prefix}${script}; then " \ + "echo ${script} found! Executing ...;" \ + "source ${scriptaddr};" \ + "fi;\0" \ + \ + "scan_boot=" \ + "echo Scanning ${devtype} ${devnum}...; " \ + "for prefix in ${boot_prefixes}; do " \ + "for script in ${boot_scripts}; do " \ + "run script_boot; " \ + "done; " \ + "done;\0" \ + \ + "boot_targets=" \ + BOOT_TARGETS_MMC " " \ + "\0" \ + \ + "boot_prefixes=/boot/ \0" \ + \ + "boot_scripts=boot.scr\0" \ + \ + BOOTCMDS_MMC \ + +#define CONFIG_BOOTCOMMAND \ + "for target in ${boot_targets}; do run bootcmd_${target}; done" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "soc=imx6d\0" \ + "board="CONFIG_SYS_BOARD"\0" \ + "boardver="CONFIG_SYS_VARIANT"\0" \ + MEM_LAYOUT_ENV_SETTINGS \ + BOOTCMDS_COMMON + +#endif /* __CONFIG_H */

Hi Christian,
On 08/01/2014 08:24, Christian Gmeiner wrote:
This patch add support for one device of the Bachmann OT1200 series - the mr variant.
Nobody knows (at least, me !) what mr variant means.
My first attemp was to use one u-boot binary for all OT1200
^----attempt
devices, but as I need to load a device-specific devicetree I decided to go this way.
but a specific devicetree for kernel means only a different U-Boot variable in the environment ? Sure that we are not able to manage this ?
Following components are used:
- ethernet
- usb
- i2c
- display connected via ldb (init and usage in linux only)
- emmc
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
board/bachmann/ot1200/Makefile | 9 ++ board/bachmann/ot1200/ot1200.c | 246 ++++++++++++++++++++++++++++++++++++++++ boards.cfg | 1 + include/configs/ot1200.h | 241 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 497 insertions(+) create mode 100644 board/bachmann/ot1200/Makefile create mode 100644 board/bachmann/ot1200/ot1200.c create mode 100644 include/configs/ot1200.h
diff --git a/board/bachmann/ot1200/Makefile b/board/bachmann/ot1200/Makefile new file mode 100644 index 0000000..1bd42e8 --- /dev/null +++ b/board/bachmann/ot1200/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2012-2013, Guennadi Liakhovetski lg@denx.de +# (C) Copyright 2012-2013 Freescale Semiconductor, Inc. +# Copyright (C) 2013, Boundary Devices info@boundarydevices.com +# +# SPDX-License-Identifier: GPL-2.0+ +#
+obj-y := ot1200.o diff --git a/board/bachmann/ot1200/ot1200.c b/board/bachmann/ot1200/ot1200.c new file mode 100644 index 0000000..6a884c2 --- /dev/null +++ b/board/bachmann/ot1200/ot1200.c @@ -0,0 +1,246 @@ +/*
- Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
- Copyright (C) 2013, Bachmann electronic GmbH
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/iomux.h> +#include <asm/arch/mx6-pins.h> +#include <asm/imx-common/iomux-v3.h> +#include <asm/imx-common/mxc_i2c.h> +#include <mmc.h> +#include <fsl_esdhc.h> +#include <netdev.h> +#include <i2c.h> +#include <pca953x.h> +#include <edid.h> +#include <linux/fb.h>
+DECLARE_GLOBAL_DATA_PTR;
+#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
- PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
- PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
- PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
- PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
- PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
- PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
- PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
- PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+#define OUTPUT_40OHM (PAD_CTL_SPEED_MED|PAD_CTL_DSE_40ohm)
+int dram_init(void) +{
- gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
- return 0;
+}
+static iomux_v3_cfg_t const uart1_pads[] = {
- MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
- MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+static void setup_iomux_uart(void) +{
- imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+}
+static iomux_v3_cfg_t const enet_pads[] = {
- MX6_PAD_KEY_ROW1__ENET_COL | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_KEY_COL3__ENET_CRS | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_GPIO_16__ENET_ETHERNET_REF_OUT | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_GPIO_18__ENET_RX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_RXD0__ENET_RDATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_RXD1__ENET_RDATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_KEY_COL2__ENET_RDATA_2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_KEY_COL0__ENET_RDATA_3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_CRS_DV__ENET_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_TXD0__ENET_TDATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_TXD1__ENET_TDATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_KEY_ROW2__ENET_TDATA_2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_KEY_ROW0__ENET_TDATA_3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
- MX6_PAD_ENET_TX_EN__ENET_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
+};
+static void setup_iomux_enet(void) +{
- imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
+}
+int board_early_init_f(void) +{
- setup_iomux_uart();
- setup_iomux_enet();
- return 0;
+}
+static iomux_v3_cfg_t const ecspi1_pads[] = {
- MX6_PAD_DISP0_DAT3__ECSPI3_SS0 | MUX_PAD_CTRL(SPI_PAD_CTRL),
- MX6_PAD_DISP0_DAT4__ECSPI3_SS1 | MUX_PAD_CTRL(SPI_PAD_CTRL),
- MX6_PAD_DISP0_DAT2__ECSPI3_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
- MX6_PAD_DISP0_DAT1__ECSPI3_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
- MX6_PAD_DISP0_DAT0__ECSPI3_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+};
+void setup_spi(void)
maybe static ?
+{
- imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+}
as setup_spi set only the iomux, and you set the whole iomux in board_early_init_f(), why do you need to postpone the setup in boar_init() ?
+static iomux_v3_cfg_t const usdhc3_pads[] = {
- MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
- MX6_PAD_SD3_RST__USDHC3_RST | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+int board_mmc_getcd(struct mmc *mmc) +{
- return 1;
+}
+struct fsl_esdhc_cfg usdhc_cfg[] = {
- {USDHC3_BASE_ADDR},
+};
+int board_mmc_init(bd_t *bis) +{
- usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
- usdhc_cfg[0].max_bus_width = 8;
- imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
- return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+}
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+/* I2C2 - EDID */ +static struct i2c_pads_info i2c_pad_info1 = {
- .scl = {
.i2c_mode = MX6_PAD_EIM_EB2__I2C2_SCL | PC,
.gpio_mode = MX6_PAD_EIM_EB2__GPIO_2_30 | PC,
.gp = IMX_GPIO_NR(2, 30)
- },
- .sda = {
.i2c_mode = MX6_PAD_EIM_D16__I2C2_SDA | PC,
.gpio_mode = MX6_PAD_EIM_D16__GPIO_3_16 | PC,
.gp = IMX_GPIO_NR(3, 16)
- }
+};
+/* I2C3 - IO expander */ +static struct i2c_pads_info i2c_pad_info2 = {
- .scl = {
.i2c_mode = MX6_PAD_EIM_D17__I2C3_SCL | PC,
.gpio_mode = MX6_PAD_EIM_D17__GPIO_3_17 | PC,
.gp = IMX_GPIO_NR(3, 17)
- },
- .sda = {
.i2c_mode = MX6_PAD_EIM_D18__I2C3_SDA | PC,
.gpio_mode = MX6_PAD_EIM_D18__GPIO_3_18 | PC,
.gp = IMX_GPIO_NR(3, 18)
- }
+};
+static iomux_v3_cfg_t const pwm_pad[] = {
- MX6_PAD_SD1_CMD__PWM4_PWMO | MUX_PAD_CTRL(OUTPUT_40OHM),
+};
+static void leds_on(void) +{
- i2c_set_bus_num(2);
- pca953x_set_dir(0x20, 0xffff, PCA953X_DIR_OUT);
- pca953x_set_val(0x20, 0xffff, 0x0);
It would be nice to use a #define for the I2C address. Please also add a couple of useful comments to indicate which leds are turned on.
+}
+static void backlight_off(void) +{
- unsigned gpio = IMX_GPIO_NR(2, 0);
- //gpio_direction_input(gpio);
No dead code
- gpio_direction_output(gpio, 0);
- //gpio_set_value(gpio, 0);
ditto.
+}
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) +void ft_board_setup(void *blob, bd_t *bd) +{
- struct edid1_info edid;
- struct fb_videomode mode;
- i2c_set_bus_num(1);
- if (i2c_read(0x52, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
I would like that all I2 addresses are defined together in a header file.
puts("Error reading EDID content.\n");
return;
- }
- if (edid_check_info(&edid)) {
puts("Content isn't valid EDID.\n");
return;
- }
- edid_to_fb_videomode(&edid, &mode);
- /* find display-timings node */
- int noff = fdt_node_offset_by_compatible(blob, -1, "fsl,imx6q-ldb");
- int channel = fdt_subnode_offset(blob, noff, "lvds-channel"); // lvds-channel@0
- int timings = fdt_subnode_offset(blob, channel, "display-timings");
- /* clean-up all the mess */
- fdt_del_node(blob, timings);
- fdt_add_subnode(blob, channel, "display-timings");
- timings = fdt_subnode_offset(blob, channel, "display-timings");
- int final = fdt_add_subnode(blob, timings, "timing");
- /* fill with useful values */
- fdt_add_display_timings(blob, final, &mode);
- return;
+} +#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
+int board_init(void) +{
- gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
- backlight_off();
- setup_spi();
- setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
- setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
- leds_on();
- return 0;
+}
+int checkboard(void) +{
- puts("Board: "CONFIG_SYS_BOARD" "CONFIG_SYS_VARIANT"\n");
CONFIG_SYS_VARIANT is not yet used. You need to add description in a README file if it is a CONFIG_SYS_ option.
There also CONFIG_SYS_BOARD_NAME, near CONFIG_SYS_BOARD. Having both is misleading, I think we have to clean it up. But boards define CONFIG_SYS_BOARD_NAME, that is a more descriptive name.
- return 0;
+} diff --git a/boards.cfg b/boards.cfg index c602a16..d5175f5 100644 --- a/boards.cfg +++ b/boards.cfg @@ -295,6 +295,7 @@ Active arm armv7 mx6 - udoo udoo_qua Active arm armv7 mx6 - wandboard wandboard_dl wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024 Fabio Estevam fabio.estevam@freescale.com Active arm armv7 mx6 - wandboard wandboard_quad wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q2g.cfg,MX6Q,DDR_MB=2048 Fabio Estevam fabio.estevam@freescale.com Active arm armv7 mx6 - wandboard wandboard_solo wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s.cfg,MX6S,DDR_MB=512 Fabio Estevam fabio.estevam@freescale.com +Active arm armv7 mx6 bachmann ot1200 ot1200_mr ot1200:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg,SYS_VARIANT="mr",MX6Q
Are you using the correct boards.cfg ? Field for Maintainers is missing.
Active arm armv7 mx6 boundary nitrogen6x mx6qsabrelite nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q.cfg,MX6Q,DDR_MB=1024,SABRELITE Eric Nelson eric.nelson@boundarydevices.com Active arm armv7 mx6 boundary nitrogen6x nitrogen6dl nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024 Eric Nelson eric.nelson@boundarydevices.com Active arm armv7 mx6 boundary nitrogen6x nitrogen6dl2g nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl2g.cfg,MX6DL,DDR_MB=2048 Eric Nelson eric.nelson@boundarydevices.com diff --git a/include/configs/ot1200.h b/include/configs/ot1200.h new file mode 100644 index 0000000..1c1e5fc --- /dev/null +++ b/include/configs/ot1200.h @@ -0,0 +1,241 @@ +/*
- Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
- Copyright (C) 2013, Bachmann electronic GmbH
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __CONFIG_H +#define __CONFIG_H
+#define CONFIG_MX6 +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO
+#include <asm/arch/imx-regs.h> +#include <asm/imx-common/gpio.h>
+#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_INITRD_TAG +#define CONFIG_REVISION_TAG
It seems you are booting only new kernels, that is DT based. Do you need TAG ? Then no, please remove it !
+/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (10 * 1024 * 1024)
+#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_MXC_GPIO
+#define CONFIG_CMD_FUSE +#ifdef CONFIG_CMD_FUSE +#define CONFIG_MXC_OCOTP +#endif
+/* UART Configs */ +#define CONFIG_MXC_UART +#define CONFIG_MXC_UART_BASE UART1_BASE
+/* SF Configs */ +#define CONFIG_CMD_SF +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_STMICRO +#define CONFIG_MXC_SPI +#define CONFIG_SF_DEFAULT_BUS 2 +#define CONFIG_SF_DEFAULT_CS (0|(IMX_GPIO_NR(1, 3)<<8)) +#define CONFIG_SF_DEFAULT_SPEED 25000000 +#define CONFIG_SF_DEFAULT_MODE (SPI_MODE_0)
+/* IO expander */ +#define CONFIG_PCA953X +#define CONFIG_SYS_I2C_PCA953X_ADDR 0x20
You have defined the address ! Please use it in code.
+#define CONFIG_SYS_I2C_PCA953X_WIDTH { {0x20, 16} } +#define CONFIG_CMD_PCA953X +#define CONFIG_CMD_PCA953X_INFO
+/* I2C Configs */ +#define CONFIG_CMD_I2C +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_SPEED 100000
+/* OF Configs */ +#define CONFIG_I2C_EDID +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_BOARD_SETUP
+/* OCOTP Configs */ +#define CONFIG_CMD_IMXOTP +#ifdef CONFIG_CMD_IMXOTP +#define CONFIG_IMX_OTP +#define IMX_OTP_BASE OCOTP_BASE_ADDR +#define IMX_OTP_ADDR_MAX 0x7F +#define IMX_OTP_DATA_ERROR_VAL 0xBADABADA +#define IMX_OTPWRITE_ENABLED +#endif
+/* MMC Configs */ +#define CONFIG_FSL_ESDHC +#define CONFIG_FSL_USDHC +#define CONFIG_SYS_FSL_ESDHC_ADDR 0 +#define CONFIG_SYS_FSL_USDHC_NUM 2
+#define CONFIG_MMC +#define CONFIG_CMD_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#define CONFIG_CMD_NET +#define CONFIG_FEC_MXC +#define CONFIG_MII +#define IMX_FEC_BASE ENET_BASE_ADDR +#define CONFIG_FEC_XCV_TYPE MII100 +#define CONFIG_ETHPRIME "FEC" +#define CONFIG_FEC_MXC_PHYADDR 0x5 +#define CONFIG_PHYLIB
+/* Miscellaneous commands */ +#define CONFIG_CMD_BMODE +#define CONFIG_CMD_SETEXPR
+/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 115200
+/* Command definition */ +#include <config_cmd_default.h>
+#undef CONFIG_CMD_IMLS
+#define CONFIG_BOOTDELAY 1
+#define CONFIG_PREBOOT ""
+#define CONFIG_LOADADDR 0x12000000 +#define CONFIG_SYS_TEXT_BASE 0x17800000
+/* Miscellaneous configurable options */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT "U-Boot > "
You do not need to define CONFIG_SYS_PROMPT, there is a default. Please remove it.
+#define CONFIG_SYS_CBSIZE 1024
+/* Print Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
+#define CONFIG_CMDLINE_EDITING
+/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR +#define PHYS_SDRAM_SIZE (1u * 1024 * 1024 * 1024) /* TODO: needed? */
+#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM +#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR +#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE
+#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+/* FLASH and environment organization */ +#define CONFIG_SYS_NO_FLASH
+#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_SIZE (8 * 1024) /* 8 kb */ +#define CONFIG_ENV_OFFSET (768 * 1024) +#define CONFIG_ENV_SECT_SIZE (8 * 1024) +#define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS +#define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS +#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE +#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
+#define CONFIG_OF_LIBFDT +#define CONFIG_CMD_BOOTZ
+#ifndef CONFIG_SYS_DCACHE_OFF +#define CONFIG_CMD_CACHE +#endif
+#define CONFIG_CMD_BOOTZ +#define CONFIG_SUPPORT_RAW_INITRD
+/* FS Configs */ +#define CONFIG_CMD_EXT3 +#define CONFIG_CMD_EXT4 +#define CONFIG_DOS_PARTITION +#define CONFIG_CMD_FS_GENERIC
+/* needed for run-in etc. */ +#define CONFIG_BOOTP_SERVERIP +#define CONFIG_BOOTP_BOOTFILE
+/*
- Memory layout for where various images get loaded by boot scripts
- */
+#define MEM_LAYOUT_ENV_SETTINGS \
- "scriptaddr=0x14000000\0" \
- "kernel_addr_r=0x10000000\0" \
- "fdt_addr_r=0x11000000\0" \
- "ramdisk_addr_r=0x12A00000\0" \
- "fdt_high=0xffffffff\0" \
- "initrd_high=0xffffffff\0"
We had problems setting fdt_high. Please check commit 6584a1b52624d60249c3d5115b176315dbac3939. Dropping and or unsetting fdt_high leads to issues if CONFIG_HIGHMEM in kernel is not set. Please take a look at the previous thread on this topic.
+#ifdef CONFIG_CMD_MMC +#define BOOTCMDS_MMC \
- "mmc_boot=" \
"setenv devtype mmc; " \
"if mmc dev ${devnum}; then " \
"run scan_boot; " \
"fi\0" \
- "bootcmd_mmc0=setenv devnum 0; run mmc_boot;\0"
+#define BOOT_TARGETS_MMC "mmc0" +#endif
+#define BOOTCMDS_COMMON \
- "rootpart=2\0" \
- \
- "script_boot=" \
"if load ${devtype} ${devnum}:${rootpart} " \
"${scriptaddr} ${prefix}${script}; then " \
"echo ${script} found! Executing ...;" \
"source ${scriptaddr};" \
"fi;\0" \
- \
- "scan_boot=" \
"echo Scanning ${devtype} ${devnum}...; " \
"for prefix in ${boot_prefixes}; do " \
"for script in ${boot_scripts}; do " \
"run script_boot; " \
"done; " \
"done;\0" \
- \
- "boot_targets=" \
BOOT_TARGETS_MMC " " \
"\0" \
- \
- "boot_prefixes=/boot/ \0" \
- \
- "boot_scripts=boot.scr\0" \
- \
- BOOTCMDS_MMC \
+#define CONFIG_BOOTCOMMAND \
- "for target in ${boot_targets}; do run bootcmd_${target}; done"
+#define CONFIG_EXTRA_ENV_SETTINGS \
"soc=imx6d\0" \
"board="CONFIG_SYS_BOARD"\0" \
"boardver="CONFIG_SYS_VARIANT"\0" \
MEM_LAYOUT_ENV_SETTINGS \
BOOTCMDS_COMMON
+#endif /* __CONFIG_H */
Best regards, Stefano Babic

HI Stefano,
2014/1/8 Stefano Babic sbabic@denx.de:
Hi Christian,
On 08/01/2014 08:24, Christian Gmeiner wrote:
This patch add support for one device of the Bachmann OT1200 series - the mr variant.
Nobody knows (at least, me !) what mr variant means.
its just a project name.
My first attemp was to use one u-boot binary for all OT1200
^----attempt
ups
devices, but as I need to load a device-specific devicetree I decided to go this way.
but a specific devicetree for kernel means only a different U-Boot variable in the environment ? Sure that we are not able to manage this ?
That is correct... in the beginnings we did not stored the env in the SPI flash but only used the default one. But that looks like a very good idea. So I can get rid of CONFIG_SYS_VARIANT and have really only one u-boot image for all two devices :)
Following components are used:
- ethernet
- usb
- i2c
- display connected via ldb (init and usage in linux only)
- emmc
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
board/bachmann/ot1200/Makefile | 9 ++ board/bachmann/ot1200/ot1200.c | 246 ++++++++++++++++++++++++++++++++++++++++ boards.cfg | 1 + include/configs/ot1200.h | 241 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 497 insertions(+) create mode 100644 board/bachmann/ot1200/Makefile create mode 100644 board/bachmann/ot1200/ot1200.c create mode 100644 include/configs/ot1200.h
diff --git a/board/bachmann/ot1200/Makefile b/board/bachmann/ot1200/Makefile new file mode 100644 index 0000000..1bd42e8 --- /dev/null +++ b/board/bachmann/ot1200/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2012-2013, Guennadi Liakhovetski lg@denx.de +# (C) Copyright 2012-2013 Freescale Semiconductor, Inc. +# Copyright (C) 2013, Boundary Devices info@boundarydevices.com +# +# SPDX-License-Identifier: GPL-2.0+ +#
+obj-y := ot1200.o diff --git a/board/bachmann/ot1200/ot1200.c b/board/bachmann/ot1200/ot1200.c new file mode 100644 index 0000000..6a884c2 --- /dev/null +++ b/board/bachmann/ot1200/ot1200.c @@ -0,0 +1,246 @@ +/*
- Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
- Copyright (C) 2013, Bachmann electronic GmbH
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/iomux.h> +#include <asm/arch/mx6-pins.h> +#include <asm/imx-common/iomux-v3.h> +#include <asm/imx-common/mxc_i2c.h> +#include <mmc.h> +#include <fsl_esdhc.h> +#include <netdev.h> +#include <i2c.h> +#include <pca953x.h> +#include <edid.h> +#include <linux/fb.h>
+DECLARE_GLOBAL_DATA_PTR;
+#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+#define OUTPUT_40OHM (PAD_CTL_SPEED_MED|PAD_CTL_DSE_40ohm)
+int dram_init(void) +{
gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
return 0;
+}
+static iomux_v3_cfg_t const uart1_pads[] = {
MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+static void setup_iomux_uart(void) +{
imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+}
+static iomux_v3_cfg_t const enet_pads[] = {
MX6_PAD_KEY_ROW1__ENET_COL | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_COL3__ENET_CRS | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_GPIO_16__ENET_ETHERNET_REF_OUT | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_GPIO_18__ENET_RX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_RXD0__ENET_RDATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_RXD1__ENET_RDATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_COL2__ENET_RDATA_2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_COL0__ENET_RDATA_3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_CRS_DV__ENET_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_TXD0__ENET_TDATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_TXD1__ENET_TDATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_ROW2__ENET_TDATA_2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_KEY_ROW0__ENET_TDATA_3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
MX6_PAD_ENET_TX_EN__ENET_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
+};
+static void setup_iomux_enet(void) +{
imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
+}
+int board_early_init_f(void) +{
setup_iomux_uart();
setup_iomux_enet();
return 0;
+}
+static iomux_v3_cfg_t const ecspi1_pads[] = {
MX6_PAD_DISP0_DAT3__ECSPI3_SS0 | MUX_PAD_CTRL(SPI_PAD_CTRL),
MX6_PAD_DISP0_DAT4__ECSPI3_SS1 | MUX_PAD_CTRL(SPI_PAD_CTRL),
MX6_PAD_DISP0_DAT2__ECSPI3_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
MX6_PAD_DISP0_DAT1__ECSPI3_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
MX6_PAD_DISP0_DAT0__ECSPI3_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+};
+void setup_spi(void)
maybe static ?
good idea
+{
imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+}
as setup_spi set only the iomux, and you set the whole iomux in board_early_init_f(), why do you need to postpone the setup in boar_init() ?
don't know... will fix it.
+static iomux_v3_cfg_t const usdhc3_pads[] = {
MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_RST__USDHC3_RST | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+int board_mmc_getcd(struct mmc *mmc) +{
return 1;
+}
+struct fsl_esdhc_cfg usdhc_cfg[] = {
{USDHC3_BASE_ADDR},
+};
+int board_mmc_init(bd_t *bis) +{
usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
usdhc_cfg[0].max_bus_width = 8;
imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+}
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+/* I2C2 - EDID */ +static struct i2c_pads_info i2c_pad_info1 = {
.scl = {
.i2c_mode = MX6_PAD_EIM_EB2__I2C2_SCL | PC,
.gpio_mode = MX6_PAD_EIM_EB2__GPIO_2_30 | PC,
.gp = IMX_GPIO_NR(2, 30)
},
.sda = {
.i2c_mode = MX6_PAD_EIM_D16__I2C2_SDA | PC,
.gpio_mode = MX6_PAD_EIM_D16__GPIO_3_16 | PC,
.gp = IMX_GPIO_NR(3, 16)
}
+};
+/* I2C3 - IO expander */ +static struct i2c_pads_info i2c_pad_info2 = {
.scl = {
.i2c_mode = MX6_PAD_EIM_D17__I2C3_SCL | PC,
.gpio_mode = MX6_PAD_EIM_D17__GPIO_3_17 | PC,
.gp = IMX_GPIO_NR(3, 17)
},
.sda = {
.i2c_mode = MX6_PAD_EIM_D18__I2C3_SDA | PC,
.gpio_mode = MX6_PAD_EIM_D18__GPIO_3_18 | PC,
.gp = IMX_GPIO_NR(3, 18)
}
+};
+static iomux_v3_cfg_t const pwm_pad[] = {
MX6_PAD_SD1_CMD__PWM4_PWMO | MUX_PAD_CTRL(OUTPUT_40OHM),
+};
+static void leds_on(void) +{
i2c_set_bus_num(2);
pca953x_set_dir(0x20, 0xffff, PCA953X_DIR_OUT);
pca953x_set_val(0x20, 0xffff, 0x0);
It would be nice to use a #define for the I2C address. Please also add a couple of useful comments to indicate which leds are turned on.
ok
+}
+static void backlight_off(void) +{
unsigned gpio = IMX_GPIO_NR(2, 0);
//gpio_direction_input(gpio);
No dead code
ups
gpio_direction_output(gpio, 0);
//gpio_set_value(gpio, 0);
ditto.
ups
+}
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) +void ft_board_setup(void *blob, bd_t *bd) +{
struct edid1_info edid;
struct fb_videomode mode;
i2c_set_bus_num(1);
if (i2c_read(0x52, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
I would like that all I2 addresses are defined together in a header file.
ok
puts("Error reading EDID content.\n");
return;
}
if (edid_check_info(&edid)) {
puts("Content isn't valid EDID.\n");
return;
}
edid_to_fb_videomode(&edid, &mode);
/* find display-timings node */
int noff = fdt_node_offset_by_compatible(blob, -1, "fsl,imx6q-ldb");
int channel = fdt_subnode_offset(blob, noff, "lvds-channel"); // lvds-channel@0
int timings = fdt_subnode_offset(blob, channel, "display-timings");
/* clean-up all the mess */
fdt_del_node(blob, timings);
fdt_add_subnode(blob, channel, "display-timings");
timings = fdt_subnode_offset(blob, channel, "display-timings");
int final = fdt_add_subnode(blob, timings, "timing");
/* fill with useful values */
fdt_add_display_timings(blob, final, &mode);
return;
+} +#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
+int board_init(void) +{
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
backlight_off();
setup_spi();
setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
leds_on();
return 0;
+}
+int checkboard(void) +{
puts("Board: "CONFIG_SYS_BOARD" "CONFIG_SYS_VARIANT"\n");
CONFIG_SYS_VARIANT is not yet used. You need to add description in a README file if it is a CONFIG_SYS_ option.
There also CONFIG_SYS_BOARD_NAME, near CONFIG_SYS_BOARD. Having both is misleading, I think we have to clean it up. But boards define CONFIG_SYS_BOARD_NAME, that is a more descriptive name.
ok
return 0;
+} diff --git a/boards.cfg b/boards.cfg index c602a16..d5175f5 100644 --- a/boards.cfg +++ b/boards.cfg @@ -295,6 +295,7 @@ Active arm armv7 mx6 - udoo udoo_qua Active arm armv7 mx6 - wandboard wandboard_dl wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024 Fabio Estevam fabio.estevam@freescale.com Active arm armv7 mx6 - wandboard wandboard_quad wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q2g.cfg,MX6Q,DDR_MB=2048 Fabio Estevam fabio.estevam@freescale.com Active arm armv7 mx6 - wandboard wandboard_solo wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s.cfg,MX6S,DDR_MB=512 Fabio Estevam fabio.estevam@freescale.com +Active arm armv7 mx6 bachmann ot1200 ot1200_mr ot1200:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg,SYS_VARIANT="mr",MX6Q
Are you using the correct boards.cfg ? Field for Maintainers is missing.
will fix that
Active arm armv7 mx6 boundary nitrogen6x mx6qsabrelite nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q.cfg,MX6Q,DDR_MB=1024,SABRELITE Eric Nelson eric.nelson@boundarydevices.com Active arm armv7 mx6 boundary nitrogen6x nitrogen6dl nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024 Eric Nelson eric.nelson@boundarydevices.com Active arm armv7 mx6 boundary nitrogen6x nitrogen6dl2g nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl2g.cfg,MX6DL,DDR_MB=2048 Eric Nelson eric.nelson@boundarydevices.com diff --git a/include/configs/ot1200.h b/include/configs/ot1200.h new file mode 100644 index 0000000..1c1e5fc --- /dev/null +++ b/include/configs/ot1200.h @@ -0,0 +1,241 @@ +/*
- Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
- Copyright (C) 2013, Bachmann electronic GmbH
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __CONFIG_H +#define __CONFIG_H
+#define CONFIG_MX6 +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO
+#include <asm/arch/imx-regs.h> +#include <asm/imx-common/gpio.h>
+#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_INITRD_TAG +#define CONFIG_REVISION_TAG
It seems you are booting only new kernels, that is DT based. Do you need TAG ? Then no, please remove it !
ok
+/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (10 * 1024 * 1024)
+#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_MXC_GPIO
+#define CONFIG_CMD_FUSE +#ifdef CONFIG_CMD_FUSE +#define CONFIG_MXC_OCOTP +#endif
+/* UART Configs */ +#define CONFIG_MXC_UART +#define CONFIG_MXC_UART_BASE UART1_BASE
+/* SF Configs */ +#define CONFIG_CMD_SF +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_STMICRO +#define CONFIG_MXC_SPI +#define CONFIG_SF_DEFAULT_BUS 2 +#define CONFIG_SF_DEFAULT_CS (0|(IMX_GPIO_NR(1, 3)<<8)) +#define CONFIG_SF_DEFAULT_SPEED 25000000 +#define CONFIG_SF_DEFAULT_MODE (SPI_MODE_0)
+/* IO expander */ +#define CONFIG_PCA953X +#define CONFIG_SYS_I2C_PCA953X_ADDR 0x20
You have defined the address ! Please use it in code.
ok
+#define CONFIG_SYS_I2C_PCA953X_WIDTH { {0x20, 16} } +#define CONFIG_CMD_PCA953X +#define CONFIG_CMD_PCA953X_INFO
+/* I2C Configs */ +#define CONFIG_CMD_I2C +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_SPEED 100000
+/* OF Configs */ +#define CONFIG_I2C_EDID +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_BOARD_SETUP
+/* OCOTP Configs */ +#define CONFIG_CMD_IMXOTP +#ifdef CONFIG_CMD_IMXOTP +#define CONFIG_IMX_OTP +#define IMX_OTP_BASE OCOTP_BASE_ADDR +#define IMX_OTP_ADDR_MAX 0x7F +#define IMX_OTP_DATA_ERROR_VAL 0xBADABADA +#define IMX_OTPWRITE_ENABLED +#endif
+/* MMC Configs */ +#define CONFIG_FSL_ESDHC +#define CONFIG_FSL_USDHC +#define CONFIG_SYS_FSL_ESDHC_ADDR 0 +#define CONFIG_SYS_FSL_USDHC_NUM 2
+#define CONFIG_MMC +#define CONFIG_CMD_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#define CONFIG_CMD_NET +#define CONFIG_FEC_MXC +#define CONFIG_MII +#define IMX_FEC_BASE ENET_BASE_ADDR +#define CONFIG_FEC_XCV_TYPE MII100 +#define CONFIG_ETHPRIME "FEC" +#define CONFIG_FEC_MXC_PHYADDR 0x5 +#define CONFIG_PHYLIB
+/* Miscellaneous commands */ +#define CONFIG_CMD_BMODE +#define CONFIG_CMD_SETEXPR
+/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 115200
+/* Command definition */ +#include <config_cmd_default.h>
+#undef CONFIG_CMD_IMLS
+#define CONFIG_BOOTDELAY 1
+#define CONFIG_PREBOOT ""
+#define CONFIG_LOADADDR 0x12000000 +#define CONFIG_SYS_TEXT_BASE 0x17800000
+/* Miscellaneous configurable options */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT "U-Boot > "
You do not need to define CONFIG_SYS_PROMPT, there is a default. Please remove it.
ok
+#define CONFIG_SYS_CBSIZE 1024
+/* Print Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
+#define CONFIG_CMDLINE_EDITING
+/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR +#define PHYS_SDRAM_SIZE (1u * 1024 * 1024 * 1024) /* TODO: needed? */
+#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM +#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR +#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE
+#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+/* FLASH and environment organization */ +#define CONFIG_SYS_NO_FLASH
+#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_SIZE (8 * 1024) /* 8 kb */ +#define CONFIG_ENV_OFFSET (768 * 1024) +#define CONFIG_ENV_SECT_SIZE (8 * 1024) +#define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS +#define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS +#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE +#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
+#define CONFIG_OF_LIBFDT +#define CONFIG_CMD_BOOTZ
+#ifndef CONFIG_SYS_DCACHE_OFF +#define CONFIG_CMD_CACHE +#endif
+#define CONFIG_CMD_BOOTZ +#define CONFIG_SUPPORT_RAW_INITRD
+/* FS Configs */ +#define CONFIG_CMD_EXT3 +#define CONFIG_CMD_EXT4 +#define CONFIG_DOS_PARTITION +#define CONFIG_CMD_FS_GENERIC
+/* needed for run-in etc. */ +#define CONFIG_BOOTP_SERVERIP +#define CONFIG_BOOTP_BOOTFILE
+/*
- Memory layout for where various images get loaded by boot scripts
- */
+#define MEM_LAYOUT_ENV_SETTINGS \
"scriptaddr=0x14000000\0" \
"kernel_addr_r=0x10000000\0" \
"fdt_addr_r=0x11000000\0" \
"ramdisk_addr_r=0x12A00000\0" \
"fdt_high=0xffffffff\0" \
"initrd_high=0xffffffff\0"
We had problems setting fdt_high. Please check commit 6584a1b52624d60249c3d5115b176315dbac3939. Dropping and or unsetting fdt_high leads to issues if CONFIG_HIGHMEM in kernel is not set. Please take a look at the previous thread on this topic.
Will do...
+#ifdef CONFIG_CMD_MMC +#define BOOTCMDS_MMC \
"mmc_boot=" \
"setenv devtype mmc; " \
"if mmc dev ${devnum}; then " \
"run scan_boot; " \
"fi\0" \
"bootcmd_mmc0=setenv devnum 0; run mmc_boot;\0"
+#define BOOT_TARGETS_MMC "mmc0" +#endif
+#define BOOTCMDS_COMMON \
"rootpart=2\0" \
\
"script_boot=" \
"if load ${devtype} ${devnum}:${rootpart} " \
"${scriptaddr} ${prefix}${script}; then " \
"echo ${script} found! Executing ...;" \
"source ${scriptaddr};" \
"fi;\0" \
\
"scan_boot=" \
"echo Scanning ${devtype} ${devnum}...; " \
"for prefix in ${boot_prefixes}; do " \
"for script in ${boot_scripts}; do " \
"run script_boot; " \
"done; " \
"done;\0" \
\
"boot_targets=" \
BOOT_TARGETS_MMC " " \
"\0" \
\
"boot_prefixes=/boot/ \0" \
\
"boot_scripts=boot.scr\0" \
\
BOOTCMDS_MMC \
+#define CONFIG_BOOTCOMMAND \
"for target in ${boot_targets}; do run bootcmd_${target}; done"
+#define CONFIG_EXTRA_ENV_SETTINGS \
"soc=imx6d\0" \
"board="CONFIG_SYS_BOARD"\0" \
"boardver="CONFIG_SYS_VARIANT"\0" \
MEM_LAYOUT_ENV_SETTINGS \
BOOTCMDS_COMMON
+#endif /* __CONFIG_H */
greets -- Christian Gmeiner, MSc

Commit 762a88ccf8540948fbf8c31b40a29d1e0684a25b introduces a 64-bit division without using the lldiv() function, which pulls in previously unused libgcc stuff.
Signed-off-by: Måns Rullgård mans@mansr.com Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- arch/arm/cpu/armv7/mx6/clock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 873d9d0..4eeb09b 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -5,6 +5,7 @@ */
#include <common.h> +#include <div64.h> #include <asm/io.h> #include <asm/errno.h> #include <asm/arch/imx-regs.h> @@ -123,7 +124,7 @@ static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num) return 0; }
- return (freq * 18) / ((div & ANATOP_PFD_FRAC_MASK(pfd_num)) >> + return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >> ANATOP_PFD_FRAC_SHIFT(pfd_num)); }

Hi Christian,
On 08/01/2014 08:24, Christian Gmeiner wrote:
Commit 762a88ccf8540948fbf8c31b40a29d1e0684a25b introduces a 64-bit division without using the lldiv() function, which pulls in previously unused libgcc stuff.
Signed-off-by: Måns Rullgård mans@mansr.com Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
arch/arm/cpu/armv7/mx6/clock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 873d9d0..4eeb09b 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -5,6 +5,7 @@ */
#include <common.h> +#include <div64.h> #include <asm/io.h> #include <asm/errno.h> #include <asm/arch/imx-regs.h> @@ -123,7 +124,7 @@ static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num) return 0; }
- return (freq * 18) / ((div & ANATOP_PFD_FRAC_MASK(pfd_num)) >>
- return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >> ANATOP_PFD_FRAC_SHIFT(pfd_num));
}
Thanks to repost this patch. I will apply it for the current release.
Acked-by: Stefano Babic sbabic@denx.de
Best regards, Stefano Babic

Hi Stefano,
2014/1/8 Stefano Babic sbabic@denx.de:
Hi Christian,
On 08/01/2014 08:24, Christian Gmeiner wrote:
Commit 762a88ccf8540948fbf8c31b40a29d1e0684a25b introduces a 64-bit division without using the lldiv() function, which pulls in previously unused libgcc stuff.
Signed-off-by: Måns Rullgård mans@mansr.com Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
arch/arm/cpu/armv7/mx6/clock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 873d9d0..4eeb09b 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -5,6 +5,7 @@ */
#include <common.h> +#include <div64.h> #include <asm/io.h> #include <asm/errno.h> #include <asm/arch/imx-regs.h> @@ -123,7 +124,7 @@ static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num) return 0; }
return (freq * 18) / ((div & ANATOP_PFD_FRAC_MASK(pfd_num)) >>
return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >> ANATOP_PFD_FRAC_SHIFT(pfd_num));
}
Thanks to repost this patch. I will apply it for the current release.
Acked-by: Stefano Babic sbabic@denx.de
Fine.. one patch less to keep track of :) -- Christian Gmeiner, MSc

On 08/01/2014 08:24, Christian Gmeiner wrote:
Commit 762a88ccf8540948fbf8c31b40a29d1e0684a25b introduces a 64-bit division without using the lldiv() function, which pulls in previously unused libgcc stuff.
Signed-off-by: Måns Rullgård mans@mansr.com Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
Applied to u-boot-imx, thanks !
Best regards, Stefano Babic

CC to Anatolij as video custodian
On 08/01/2014 08:24, Christian Gmeiner wrote:
There may be some custom boards in the field which have an seperate eeprom chip to store edid informations in it. To make use of those edid information in the board code this patch add a function to convert edid to fb_videomode.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
common/edid.c | 29 +++++++++++++++++++++++++++++ include/edid.h | 3 +++ 2 files changed, 32 insertions(+)
diff --git a/common/edid.c b/common/edid.c index e66108f..8841c25 100644 --- a/common/edid.c +++ b/common/edid.c @@ -12,6 +12,7 @@
#include <common.h> #include <edid.h> +#include <linux/fb.h> #include <linux/ctype.h> #include <linux/string.h>
@@ -288,3 +289,31 @@ void edid_print_info(struct edid1_info *edid_info) if (!have_timing) printf("\tNone\n"); }
+void edid_to_fb_videomode(struct edid1_info *edid, struct fb_videomode *mode) +{
struct edid_monitor_descriptor *monitor = &edid->monitor_details.descriptor[0];
unsigned char *bytes = (unsigned char *)monitor;
struct edid_detailed_timing *timing = (struct edid_detailed_timing *)monitor;
uint32_t pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing);
uint32_t h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing);
uint32_t h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing);
uint32_t h_sync_offset = EDID_DETAILED_TIMING_HSYNC_OFFSET(*timing);
uint32_t h_sync_width = EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*timing);
uint32_t v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing);
uint32_t v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing);
uint32_t v_sync_offset = EDID_DETAILED_TIMING_VSYNC_OFFSET(*timing);
uint32_t v_sync_width = EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*timing);
mode->name = "EDID";
mode->pixclock = pixclock;
mode->yres = v_active;
mode->xres = h_active;
mode->left_margin = h_blanking - h_sync_offset - h_sync_width;
mode->right_margin = h_sync_offset;
mode->upper_margin = v_blanking - v_sync_offset - v_sync_width;
mode->lower_margin = v_sync_offset;
mode->hsync_len = h_sync_width;
mode->vsync_len = v_sync_width;
+} diff --git a/include/edid.h b/include/edid.h index 480a773..4423062 100644 --- a/include/edid.h +++ b/include/edid.h @@ -233,6 +233,9 @@ struct edid1_info { */ void edid_print_info(struct edid1_info *edid_info);
+struct fb_videomode; +void edid_to_fb_videomode(struct edid1_info *edid, struct fb_videomode *mode);
/**
- Check the EDID info.

Hi Christian,
On 01/08/2014 12:24 AM, Christian Gmeiner wrote:
There may be some custom boards in the field which have an seperate eeprom chip to store edid informations in it. To make use of those edid information in the board code this patch add a function to convert edid to fb_videomode.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
common/edid.c | 29 +++++++++++++++++++++++++++++ include/edid.h | 3 +++ 2 files changed, 32 insertions(+)
diff --git a/common/edid.c b/common/edid.c index e66108f..8841c25 100644 --- a/common/edid.c +++ b/common/edid.c @@ -12,6 +12,7 @@
#include <common.h> #include <edid.h> +#include <linux/fb.h> #include <linux/ctype.h> #include <linux/string.h>
@@ -288,3 +289,31 @@ void edid_print_info(struct edid1_info *edid_info) if (!have_timing) printf("\tNone\n"); }
+void edid_to_fb_videomode(struct edid1_info *edid, struct fb_videomode *mode) +{
struct edid_monitor_descriptor *monitor = &edid->monitor_details.descriptor[0];
unsigned char *bytes = (unsigned char *)monitor;
struct edid_detailed_timing *timing = (struct edid_detailed_timing *)monitor;
uint32_t pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing);
uint32_t h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing);
uint32_t h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing);
uint32_t h_sync_offset = EDID_DETAILED_TIMING_HSYNC_OFFSET(*timing);
uint32_t h_sync_width = EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*timing);
uint32_t v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing);
uint32_t v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing);
uint32_t v_sync_offset = EDID_DETAILED_TIMING_VSYNC_OFFSET(*timing);
uint32_t v_sync_width = EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*timing);
mode->name = "EDID";
I think this wants to be KHZTOPICOS((pixclock/1000)), since the pixclock returned above seems to be in Hz.
mode->pixclock = pixclock;
mode->yres = v_active;
mode->xres = h_active;
mode->left_margin = h_blanking - h_sync_offset - h_sync_width;
mode->right_margin = h_sync_offset;
mode->upper_margin = v_blanking - v_sync_offset - v_sync_width;
mode->lower_margin = v_sync_offset;
mode->hsync_len = h_sync_width;
mode->vsync_len = v_sync_width;
+}
I just tried gluing this up for use in the Nitrogen6X HDMI channel, but found that this is more difficult than expected.
Apparently the i.MX6 clock tree doesn't (yet) support use with the 1080P monitor I have connected.
Everything else looks okay though.
Regards,
Eric

Hi Eric,
On Fri, Jan 10, 2014 at 7:36 PM, Eric Nelson eric.nelson@boundarydevices.com wrote:
I just tried gluing this up for use in the Nitrogen6X HDMI channel, but found that this is more difficult than expected.
Apparently the i.MX6 clock tree doesn't (yet) support use with the 1080P monitor I have connected.
Yes, that's true.
Should we try adding the common clock framework driver from the kernel into U-boot?
Regards,
Fabio Estevam

Hi Fabio,
On 01/13/2014 05:36 PM, Fabio Estevam wrote:
Hi Eric,
On Fri, Jan 10, 2014 at 7:36 PM, Eric Nelson eric.nelson@boundarydevices.com wrote:
I just tried gluing this up for use in the Nitrogen6X HDMI channel, but found that this is more difficult than expected.
Apparently the i.MX6 clock tree doesn't (yet) support use with the 1080P monitor I have connected.
Yes, that's true.
Should we try adding the common clock framework driver from the kernel into U-boot?
I think if we don't do it all at once, we'll end up doing it in pieces...
Regards
Eric

On Wed, 8 Jan 2014 08:24:21 +0100 Christian Gmeiner christian.gmeiner@gmail.com wrote:
There may be some custom boards in the field which have an seperate eeprom chip to store edid informations in it. To make use of those edid information in the board code this patch add a function to convert edid to fb_videomode.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
common/edid.c | 29 +++++++++++++++++++++++++++++ include/edid.h | 3 +++ 2 files changed, 32 insertions(+)
Please check your patches with tools/checkpatch.pl and fix the reported errors/warnings. Thanks!
diff --git a/common/edid.c b/common/edid.c index e66108f..8841c25 100644 --- a/common/edid.c +++ b/common/edid.c @@ -12,6 +12,7 @@
#include <common.h> #include <edid.h> +#include <linux/fb.h> #include <linux/ctype.h> #include <linux/string.h>
@@ -288,3 +289,31 @@ void edid_print_info(struct edid1_info *edid_info) if (!have_timing) printf("\tNone\n"); }
+void edid_to_fb_videomode(struct edid1_info *edid, struct fb_videomode *mode) +{
struct edid_monitor_descriptor *monitor = &edid->monitor_details.descriptor[0];
unsigned char *bytes = (unsigned char *)monitor;
struct edid_detailed_timing *timing = (struct edid_detailed_timing *)monitor;
uint32_t pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing);
uint32_t h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing);
uint32_t h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing);
uint32_t h_sync_offset = EDID_DETAILED_TIMING_HSYNC_OFFSET(*timing);
uint32_t h_sync_width = EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*timing);
uint32_t v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing);
uint32_t v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing);
uint32_t v_sync_offset = EDID_DETAILED_TIMING_VSYNC_OFFSET(*timing);
uint32_t v_sync_width = EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*timing);
mode->name = "EDID";
mode->pixclock = pixclock;
as Eric already noticed, please use
mode->pixclock = KHZ2PICOS(pixclock/1000);
The unit for fb_videomode.pixclock is picoseconds, the EDID macro returned the value in Hz. And when converting to device tree timing node in patch 3/5 please use PICOS2KHZ(mode->pixclock) * 1000 when setting the clock-frequency property.
Thanks,
Anatolij

2014/1/12 Anatolij Gustschin agust@denx.de:
On Wed, 8 Jan 2014 08:24:21 +0100 Christian Gmeiner christian.gmeiner@gmail.com wrote:
There may be some custom boards in the field which have an seperate eeprom chip to store edid informations in it. To make use of those edid information in the board code this patch add a function to convert edid to fb_videomode.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com
common/edid.c | 29 +++++++++++++++++++++++++++++ include/edid.h | 3 +++ 2 files changed, 32 insertions(+)
Please check your patches with tools/checkpatch.pl and fix the reported errors/warnings. Thanks!
diff --git a/common/edid.c b/common/edid.c index e66108f..8841c25 100644 --- a/common/edid.c +++ b/common/edid.c @@ -12,6 +12,7 @@
#include <common.h> #include <edid.h> +#include <linux/fb.h> #include <linux/ctype.h> #include <linux/string.h>
@@ -288,3 +289,31 @@ void edid_print_info(struct edid1_info *edid_info) if (!have_timing) printf("\tNone\n"); }
+void edid_to_fb_videomode(struct edid1_info *edid, struct fb_videomode *mode) +{
struct edid_monitor_descriptor *monitor = &edid->monitor_details.descriptor[0];
unsigned char *bytes = (unsigned char *)monitor;
struct edid_detailed_timing *timing = (struct edid_detailed_timing *)monitor;
uint32_t pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing);
uint32_t h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing);
uint32_t h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing);
uint32_t h_sync_offset = EDID_DETAILED_TIMING_HSYNC_OFFSET(*timing);
uint32_t h_sync_width = EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*timing);
uint32_t v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing);
uint32_t v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing);
uint32_t v_sync_offset = EDID_DETAILED_TIMING_VSYNC_OFFSET(*timing);
uint32_t v_sync_width = EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*timing);
mode->name = "EDID";
mode->pixclock = pixclock;
as Eric already noticed, please use
mode->pixclock = KHZ2PICOS(pixclock/1000);
The unit for fb_videomode.pixclock is picoseconds, the EDID macro returned the value in Hz. And when converting to device tree timing node in patch 3/5 please use PICOS2KHZ(mode->pixclock) * 1000 when setting the clock-frequency property.
Fine... will fix this in the next version of the patch set.
thanks -- Christian Gmeiner, MSc
participants (6)
-
Anatolij Gustschin
-
Christian Gmeiner
-
Eric Nelson
-
Fabio Estevam
-
Stefano Babic
-
Stephen Warren