[U-Boot] [PATCH v4 00/17] arm: rpi: Enable USB, Ethernet, MMC, Video driver model on Raspberry Pi

Raspberry Pi uses a DWC2 USB controller and a SMSC USB Ethernet adaptor. Driver model support for these is available.
This series does the following: - Enable CONFIG_DM_ETH and CONFIG_DM_USB on Raspberry Pi - Convert the MMC driver to driver model - Convert the video driver to driver model - Fixes a driver model video bug which accessed beyond the frame buffer - Fixes start-up of MMC with driver model (e.g. at present it does not support env_fat) - Clean up a few loose ends
With Ethernet active the device list looks something like this:
U-Boot> dm tree Class Probed Name ---------------------------------------- root [ + ] root_driver simple_bus [ + ] |-- soc gpio [ + ] | |-- gpio@7e200000 serial [ + ] | |-- serial@7e215040 mmc [ + ] | |-- sdhci@7e300000 blk [ + ] | | `-- sdhci@7e300000.blk video [ + ] | |-- hdmi@7e902000 vidconsole0 [ + ] | | `-- hdmi@7e902000.vidconsole0 usb [ + ] | `-- usb@7e980000 usb_hub [ + ] | `-- usb_hub usb_hub [ + ] | `-- usb_hub eth [ + ] | `-- smsc95xx_eth simple_bus [ ] `-- clocks
Changes in v4: - Add patches to convert video and MMC to driver model also - Rebase to master
Changes in v3: - Drop applied patches from series - Drop patch to introduce usbethaddr for driver model
Simon Glass (17): dm: mmc: Set up the MMC device when controller is probed dm: video: Correct line clearing code string: Use memcpy() within memmove() when we can arm: rpi: Drop the GPIO device addresses arm: rpi: Drop CONFIG_CONS_INDEX dm: arm: rpi: Move to driver model for USB dm: arm: rpi: Use driver model for Ethernet arm: rpi: Add a file to handle messages arm: rpi: Add a function to obtain the MMC clock dm: mmc: rpi: Convert Raspberry Pi to driver model for MMC dm: arm: rpi: Drop CONFIG_OF_EMBED video: arm: rpi: Move the video query out of the driver video: arm: rpi: Move the video settings out of the driver dm: video: Refactor lcd_simplefb to prepare for driver model dm: video: Add driver-model support to lcd_simplefb dm: video: arm: rpi: Convert to use driver model for video arm: rpi: Add a TODO to move all messages into the msg handler
arch/arm/mach-bcm283x/Makefile | 2 +- arch/arm/mach-bcm283x/include/mach/gpio.h | 5 - arch/arm/mach-bcm283x/include/mach/msg.h | 51 ++++++++++ arch/arm/mach-bcm283x/msg.c | 154 ++++++++++++++++++++++++++++++ board/raspberrypi/rpi/rpi.c | 62 +----------- common/lcd_simplefb.c | 47 +++++++-- configs/rpi_2_defconfig | 6 +- configs/rpi_3_32b_defconfig | 6 +- configs/rpi_3_defconfig | 6 +- configs/rpi_defconfig | 6 +- drivers/mmc/bcm2835_sdhci.c | 81 ++++++++++++---- drivers/mmc/mmc-uclass.c | 12 +++ drivers/video/bcm2835.c | 140 +++++++-------------------- drivers/video/console_normal.c | 3 +- include/configs/rpi.h | 17 +--- lib/string.c | 11 +-- 16 files changed, 382 insertions(+), 227 deletions(-) create mode 100644 arch/arm/mach-bcm283x/include/mach/msg.h create mode 100644 arch/arm/mach-bcm283x/msg.c

When an MMC controller is set up we should probe the device to find out what it is. This includes finding its capacity and reading its partition table.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
drivers/mmc/mmc-uclass.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 2fe5d61e263..a5286541c1c 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -232,6 +232,15 @@ int mmc_unbind(struct udevice *dev) return 0; }
+#ifdef CONFIG_BLK +static int mmc_post_probe(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return mmc_init(mmc); +} +#endif + static int mmc_select_hwpart(struct udevice *bdev, int hwpart) { struct udevice *mmc_dev = dev_get_parent(bdev); @@ -273,4 +282,7 @@ UCLASS_DRIVER(mmc) = { .name = "mmc", .flags = DM_UC_FLAG_SEQ_ALIAS, .per_device_auto_alloc_size = sizeof(struct mmc_uclass_priv), +#ifdef CONFIG_BLK + .post_probe = mmc_post_probe, +#endif };

On 01/20/2017 11:07 PM, Simon Glass wrote:
When an MMC controller is set up we should probe the device to find out what it is. This includes finding its capacity and reading its partition table.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
Changes in v4: None Changes in v3: None
drivers/mmc/mmc-uclass.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 2fe5d61e263..a5286541c1c 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -232,6 +232,15 @@ int mmc_unbind(struct udevice *dev) return 0; }
+#ifdef CONFIG_BLK +static int mmc_post_probe(struct udevice *dev) +{
- struct mmc *mmc = mmc_get_mmc_dev(dev);
- return mmc_init(mmc);
+} +#endif
static int mmc_select_hwpart(struct udevice *bdev, int hwpart) { struct udevice *mmc_dev = dev_get_parent(bdev); @@ -273,4 +282,7 @@ UCLASS_DRIVER(mmc) = { .name = "mmc", .flags = DM_UC_FLAG_SEQ_ALIAS, .per_device_auto_alloc_size = sizeof(struct mmc_uclass_priv), +#ifdef CONFIG_BLK
- .post_probe = mmc_post_probe,
+#endif };

At present we clear many more bytes than we should on 16bpp and 32bpp displays. The number of pixels to clear is currently calculated as the line length (in bytes) multiplied by the number of lines to clear. This is only correct for 8bpp displays.
Correct the calculation to use the number of text columns multiplied by the width of each character multiplied by the number of lines to clear.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
drivers/video/console_normal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index 89a55dd11df..744345d58e4 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -16,9 +16,10 @@
static int console_normal_set_row(struct udevice *dev, uint row, int clr) { + struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); void *line; - int pixels = VIDEO_FONT_HEIGHT * vid_priv->line_length; + int pixels = VIDEO_FONT_HEIGHT * vc_priv->cols * VIDEO_FONT_WIDTH; int i;
line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length;

On Fri, 20 Jan 2017 07:07:37 -0700 Simon Glass sjg@chromium.org wrote:
At present we clear many more bytes than we should on 16bpp and 32bpp displays. The number of pixels to clear is currently calculated as the line length (in bytes) multiplied by the number of lines to clear. This is only correct for 8bpp displays.
Correct the calculation to use the number of text columns multiplied by the width of each character multiplied by the number of lines to clear.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Anatolij Gustschin agust@denx.de
-- Anatolij

A common use of memmove() can be handled by memcpy(). Also memcpy() includes an optimisation for large sizes: it copies a word at a time. So we can get a speed-up by calling memcpy() to handle our move in this case.
Update memmove() to call memcpy() if the destination is before the source.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
lib/string.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/lib/string.c b/lib/string.c index 67d5f6a4213..6a75efb180b 100644 --- a/lib/string.c +++ b/lib/string.c @@ -509,16 +509,9 @@ void * memmove(void * dest,const void *src,size_t count) { char *tmp, *s;
- if (src == dest) - return dest; - if (dest <= src) { - tmp = (char *) dest; - s = (char *) src; - while (count--) - *tmp++ = *s++; - } - else { + memcpy(dest, src, count); + } else { tmp = (char *) dest + count; s = (char *) src + count; while (count--)

On Fri, Jan 20, 2017 at 07:07:38AM -0700, Simon Glass wrote:
A common use of memmove() can be handled by memcpy(). Also memcpy() includes an optimisation for large sizes: it copies a word at a time. So we can get a speed-up by calling memcpy() to handle our move in this case.
Update memmove() to call memcpy() if the destination is before the source.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Tom Rini trini@konsulko.com

We can rely on the device tree to provide this information.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
arch/arm/mach-bcm283x/include/mach/gpio.h | 5 ----- 1 file changed, 5 deletions(-)
diff --git a/arch/arm/mach-bcm283x/include/mach/gpio.h b/arch/arm/mach-bcm283x/include/mach/gpio.h index b2df75ad3f2..daaee52f810 100644 --- a/arch/arm/mach-bcm283x/include/mach/gpio.h +++ b/arch/arm/mach-bcm283x/include/mach/gpio.h @@ -9,11 +9,6 @@ #ifndef _BCM2835_GPIO_H_ #define _BCM2835_GPIO_H_
-#ifndef CONFIG_BCM2835 -#define BCM2835_GPIO_BASE 0x3f200000 -#else -#define BCM2835_GPIO_BASE 0x20200000 -#endif #define BCM2835_GPIO_COUNT 54
#define BCM2835_GPIO_FSEL_MASK 0x7

This is not needed now that serial uses driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
include/configs/rpi.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/include/configs/rpi.h b/include/configs/rpi.h index ce539a008cc..fe0e6a060ae 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -89,7 +89,6 @@ #else #define CONFIG_PL01X_SERIAL #endif -#define CONFIG_CONS_INDEX 0 #define CONFIG_BAUDRATE 115200
/* Console configuration */

Start using driver model for USB on the Raspberry Pi. The dwc2 supports this now so this is just a config change.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
configs/rpi_2_defconfig | 1 + configs/rpi_3_32b_defconfig | 1 + configs/rpi_3_defconfig | 1 + configs/rpi_defconfig | 1 + include/configs/rpi.h | 5 ----- 5 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index 9d669c92e42..4de1d206bcc 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -17,6 +17,7 @@ CONFIG_OF_EMBED=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y CONFIG_CONSOLE_SCROLL_LINES=10 diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index d0f7beaa0b3..746a6e28169 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -19,6 +19,7 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y # CONFIG_REQUIRE_SERIAL_CONSOLE is not set CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y CONFIG_CONSOLE_SCROLL_LINES=10 diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index ce28c312832..b916ced65a1 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -19,6 +19,7 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y # CONFIG_REQUIRE_SERIAL_CONSOLE is not set CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y CONFIG_CONSOLE_SCROLL_LINES=10 diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 4a90ca83486..514b29b5cd8 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -17,6 +17,7 @@ CONFIG_OF_EMBED=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y CONFIG_CONSOLE_SCROLL_LINES=10 diff --git a/include/configs/rpi.h b/include/configs/rpi.h index fe0e6a060ae..a0afeadcaa2 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -71,11 +71,6 @@
#ifdef CONFIG_CMD_USB #define CONFIG_USB_DWC2 -#ifndef CONFIG_BCM2835 -#define CONFIG_USB_DWC2_REG_ADDR 0x3f980000 -#else -#define CONFIG_USB_DWC2_REG_ADDR 0x20980000 -#endif #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_SMSC95XX #define CONFIG_TFTP_TSIZE

Enable CONFIG_DM_ETH so that driver model is used for the USB Ethernet device.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
configs/rpi_2_defconfig | 1 + configs/rpi_3_32b_defconfig | 1 + configs/rpi_3_defconfig | 1 + configs/rpi_defconfig | 1 + 4 files changed, 4 insertions(+)
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index 4de1d206bcc..090a0b07140 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -16,6 +16,7 @@ CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_DM_ETH=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_STORAGE=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index 746a6e28169..785bf21e9a3 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -17,6 +17,7 @@ CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_DM_ETH=y # CONFIG_REQUIRE_SERIAL_CONSOLE is not set CONFIG_USB=y CONFIG_DM_USB=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index b916ced65a1..5ff8ed1cf2b 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -17,6 +17,7 @@ CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_DM_ETH=y # CONFIG_REQUIRE_SERIAL_CONSOLE is not set CONFIG_USB=y CONFIG_DM_USB=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 514b29b5cd8..5d44f297267 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -16,6 +16,7 @@ CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_DM_ETH=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_STORAGE=y

The bcm283x chips provide a way for the ARM core to communicate with the graphics processor, which is in charge of many things. This is handled by way of a message prototcol.
At present the code for sending message (and receiving a reply) is spread around U-Boot, primarily in the board file. This means that sending a message from a driver requires duplicating the code.
Create a new message implementation with a function to support powering on a subsystem as a starting point.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
arch/arm/mach-bcm283x/Makefile | 2 +- arch/arm/mach-bcm283x/include/mach/msg.h | 18 +++++++++++++++ arch/arm/mach-bcm283x/msg.c | 39 ++++++++++++++++++++++++++++++++ board/raspberrypi/rpi/rpi.c | 35 +++------------------------- 4 files changed, 61 insertions(+), 33 deletions(-) create mode 100644 arch/arm/mach-bcm283x/include/mach/msg.h create mode 100644 arch/arm/mach-bcm283x/msg.c
diff --git a/arch/arm/mach-bcm283x/Makefile b/arch/arm/mach-bcm283x/Makefile index 5cb1b2fe94b..b5f606ef0bf 100644 --- a/arch/arm/mach-bcm283x/Makefile +++ b/arch/arm/mach-bcm283x/Makefile @@ -5,4 +5,4 @@ #
obj-$(CONFIG_BCM2835) += lowlevel_init.o -obj-y += init.o reset.o mbox.o phys2bus.o +obj-y += init.o reset.o mbox.o msg.o phys2bus.o diff --git a/arch/arm/mach-bcm283x/include/mach/msg.h b/arch/arm/mach-bcm283x/include/mach/msg.h new file mode 100644 index 00000000000..3bcb5db3e60 --- /dev/null +++ b/arch/arm/mach-bcm283x/include/mach/msg.h @@ -0,0 +1,18 @@ +/* + * (C) Copyright 2012,2015 Stephen Warren + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _BCM2835_MSG_H +#define _BCM2835_MSG_H + +/** + * bcm2835_power_on_module() - power on an SoC module + * + * @module: ID of module to power on (BCM2835_MBOX_POWER_DEVID_...) + * @return 0 if OK, -EIO on error + */ +int bcm2835_power_on_module(u32 module); + +#endif diff --git a/arch/arm/mach-bcm283x/msg.c b/arch/arm/mach-bcm283x/msg.c new file mode 100644 index 00000000000..08b1beaa539 --- /dev/null +++ b/arch/arm/mach-bcm283x/msg.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2012 Stephen Warren + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <memalign.h> +#include <asm/arch/mbox.h> + +struct msg_set_power_state { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_set_power_state set_power_state; + u32 end_tag; +}; + +int bcm2835_power_on_module(u32 module) +{ + ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1); + int ret; + + BCM2835_MBOX_INIT_HDR(msg_pwr); + BCM2835_MBOX_INIT_TAG(&msg_pwr->set_power_state, + SET_POWER_STATE); + msg_pwr->set_power_state.body.req.device_id = module; + msg_pwr->set_power_state.body.req.state = + BCM2835_MBOX_SET_POWER_STATE_REQ_ON | + BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT; + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, + &msg_pwr->hdr); + if (ret) { + printf("bcm2835: Could not set module %u power state\n", + module); + return -EIO; + } + + return 0; +} diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 22e87a2a13d..231d86b7996 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -16,6 +16,7 @@ #include <mmc.h> #include <asm/gpio.h> #include <asm/arch/mbox.h> +#include <asm/arch/msg.h> #include <asm/arch/sdhci.h> #include <asm/global_data.h> #include <dm/platform_data/serial_bcm283x_mu.h> @@ -53,12 +54,6 @@ struct msg_get_mac_address { u32 end_tag; };
-struct msg_set_power_state { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_set_power_state set_power_state; - u32 end_tag; -}; - struct msg_get_clock_rate { struct bcm2835_mbox_hdr hdr; struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; @@ -359,30 +354,6 @@ int misc_init_r(void) return 0; }
-static int power_on_module(u32 module) -{ - ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1); - int ret; - - BCM2835_MBOX_INIT_HDR(msg_pwr); - BCM2835_MBOX_INIT_TAG(&msg_pwr->set_power_state, - SET_POWER_STATE); - msg_pwr->set_power_state.body.req.device_id = module; - msg_pwr->set_power_state.body.req.state = - BCM2835_MBOX_SET_POWER_STATE_REQ_ON | - BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT; - - ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, - &msg_pwr->hdr); - if (ret) { - printf("bcm2835: Could not set module %u power state\n", - module); - return -1; - } - - return 0; -} - static void get_board_rev(void) { ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1); @@ -486,7 +457,7 @@ int board_init(void)
gd->bd->bi_boot_params = 0x100;
- return power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); + return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); }
int board_mmc_init(bd_t *bis) @@ -494,7 +465,7 @@ int board_mmc_init(bd_t *bis) ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1); int ret;
- power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI); + bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
BCM2835_MBOX_INIT_HDR(msg_clk); BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE);

Move this code into the new message handler file.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
arch/arm/mach-bcm283x/include/mach/msg.h | 7 +++++++ arch/arm/mach-bcm283x/msg.c | 28 ++++++++++++++++++++++++++++ board/raspberrypi/rpi/rpi.c | 22 ++++------------------ 3 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mach-bcm283x/include/mach/msg.h b/arch/arm/mach-bcm283x/include/mach/msg.h index 3bcb5db3e60..8fd4ace124d 100644 --- a/arch/arm/mach-bcm283x/include/mach/msg.h +++ b/arch/arm/mach-bcm283x/include/mach/msg.h @@ -15,4 +15,11 @@ */ int bcm2835_power_on_module(u32 module);
+/** + * bcm2835_get_mmc_clock() - get the frequency of the MMC clock + * + * @return clock frequency, or -ve on error + */ +int bcm2835_get_mmc_clock(void); + #endif diff --git a/arch/arm/mach-bcm283x/msg.c b/arch/arm/mach-bcm283x/msg.c index 08b1beaa539..facb916711c 100644 --- a/arch/arm/mach-bcm283x/msg.c +++ b/arch/arm/mach-bcm283x/msg.c @@ -14,6 +14,12 @@ struct msg_set_power_state { u32 end_tag; };
+struct msg_get_clock_rate { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; + u32 end_tag; +}; + int bcm2835_power_on_module(u32 module) { ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1); @@ -37,3 +43,25 @@ int bcm2835_power_on_module(u32 module)
return 0; } + +int bcm2835_get_mmc_clock(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1); + int ret; + + ret = bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI); + if (ret) + return ret; + + BCM2835_MBOX_INIT_HDR(msg_clk); + BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE); + msg_clk->get_clock_rate.body.req.clock_id = BCM2835_MBOX_CLOCK_ID_EMMC; + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr); + if (ret) { + printf("bcm2835: Could not query eMMC clock rate\n"); + return -EIO; + } + + return msg_clk->get_clock_rate.body.resp.rate_hz; +} diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 231d86b7996..dd318df72b2 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -54,12 +54,6 @@ struct msg_get_mac_address { u32 end_tag; };
-struct msg_get_clock_rate { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; - u32 end_tag; -}; - /* * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-re... * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733 @@ -462,23 +456,15 @@ int board_init(void)
int board_mmc_init(bd_t *bis) { - ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1); int ret;
bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
- BCM2835_MBOX_INIT_HDR(msg_clk); - BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE); - msg_clk->get_clock_rate.body.req.clock_id = BCM2835_MBOX_CLOCK_ID_EMMC; - - ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr); - if (ret) { - printf("bcm2835: Could not query eMMC clock rate\n"); - return -1; - } + ret = bcm2835_get_mmc_clock(); + if (ret) + return ret;
- return bcm2835_sdhci_init(BCM2835_SDHCI_BASE, - msg_clk->get_clock_rate.body.resp.rate_hz); + return bcm2835_sdhci_init(BCM2835_SDHCI_BASE, ret); }
int ft_board_setup(void *blob, bd_t *bd)

Convert the bcm2835 SDHCI driver over to support CONFIG_DM_MMC and move all boards over. There is no need to keep the old code since there are no other users.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
board/raspberrypi/rpi/rpi.c | 13 -------- configs/rpi_2_defconfig | 1 + configs/rpi_3_32b_defconfig | 1 + configs/rpi_3_defconfig | 1 + configs/rpi_defconfig | 1 + drivers/mmc/bcm2835_sdhci.c | 81 ++++++++++++++++++++++++++++++++++++--------- 6 files changed, 69 insertions(+), 29 deletions(-)
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index dd318df72b2..3d44cd4e55d 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -454,19 +454,6 @@ int board_init(void) return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); }
-int board_mmc_init(bd_t *bis) -{ - int ret; - - bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI); - - ret = bcm2835_get_mmc_clock(); - if (ret) - return ret; - - return bcm2835_sdhci_init(BCM2835_SDHCI_BASE, ret); -} - int ft_board_setup(void *blob, bd_t *bd) { /* diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index 090a0b07140..3d6f2a33377 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -14,6 +14,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index 785bf21e9a3..ca0ef7afe74 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -15,6 +15,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index 5ff8ed1cf2b..185a56c2807 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -15,6 +15,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 5d44f297267..89ecef8994e 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -14,6 +14,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index cb2bd40c65e..c96c35a9da4 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -37,14 +37,23 @@ */
#include <common.h> +#include <dm.h> #include <malloc.h> +#include <memalign.h> #include <sdhci.h> -#include <mach/timer.h> +#include <asm/arch/msg.h> +#include <asm/arch/mbox.h> #include <mach/sdhci.h> +#include <mach/timer.h>
/* 400KHz is max freq for card ID etc. Use that as min */ #define MIN_FREQ 400000
+struct bcm2835_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + struct bcm2835_sdhci_host { struct sdhci_host host; uint twoticks_delay; @@ -57,7 +66,7 @@ static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host) }
static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, - int reg) + int reg) { struct bcm2835_sdhci_host *bcm_host = to_bcm(host);
@@ -149,16 +158,33 @@ static const struct sdhci_ops bcm2835_ops = { .read_b = bcm2835_sdhci_readb, };
-int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) +static int bcm2835_sdhci_bind(struct udevice *dev) { - struct bcm2835_sdhci_host *bcm_host; - struct sdhci_host *host; + struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev);
- bcm_host = calloc(1, sizeof(*bcm_host)); - if (!bcm_host) { - printf("sdhci_host calloc fail!\n"); - return -ENOMEM; + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static int bcm2835_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev); + struct bcm2835_sdhci_host *priv = dev_get_priv(dev); + struct sdhci_host *host = &priv->host; + fdt_addr_t base; + int emmc_freq; + int ret; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + ret = bcm2835_get_mmc_clock(); + if (ret < 0) { + debug("%s: Failed to set MMC clock (err=%d)\n", __func__, ret); + return ret; } + emmc_freq = ret;
/* * See the comments in bcm2835_sdhci_raw_writel(). @@ -173,18 +199,41 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) * Multiply by 1000000 to get uS per two ticks. * +1 for hack rounding. */ - bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1; - bcm_host->last_write = 0; + priv->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1; + priv->last_write = 0;
- host = &bcm_host->host; - host->name = "bcm2835_sdhci"; - host->ioaddr = (void *)(unsigned long)regbase; + host->name = dev->name; + host->ioaddr = (void *)base; host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; host->ops = &bcm2835_ops;
- add_sdhci(host, emmc_freq, MIN_FREQ); + ret = sdhci_setup_cfg(&plat->cfg, host, emmc_freq, MIN_FREQ); + if (ret) { + debug("%s: Failed to setup SDHCI (err=%d)\n", __func__, ret); + return ret; + } + + upriv->mmc = &plat->mmc; + host->mmc = &plat->mmc; + host->mmc->priv = host;
- return 0; + return sdhci_probe(dev); } + +static const struct udevice_id bcm2835_sdhci_match[] = { + { .compatible = "brcm,bcm2835-sdhci" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sdhci_cdns) = { + .name = "sdhci-bcm2835", + .id = UCLASS_MMC, + .of_match = bcm2835_sdhci_match, + .bind = bcm2835_sdhci_bind, + .probe = bcm2835_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct bcm2835_sdhci_host), + .platdata_auto_alloc_size = sizeof(struct bcm2835_sdhci_plat), + .ops = &sdhci_ops, +};

On 01/20/2017 11:07 PM, Simon Glass wrote:
Convert the bcm2835 SDHCI driver over to support CONFIG_DM_MMC and move all boards over. There is no need to keep the old code since there are no other users.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
Changes in v4: None Changes in v3: None
board/raspberrypi/rpi/rpi.c | 13 -------- configs/rpi_2_defconfig | 1 + configs/rpi_3_32b_defconfig | 1 + configs/rpi_3_defconfig | 1 + configs/rpi_defconfig | 1 + drivers/mmc/bcm2835_sdhci.c | 81 ++++++++++++++++++++++++++++++++++++--------- 6 files changed, 69 insertions(+), 29 deletions(-)
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index dd318df72b2..3d44cd4e55d 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -454,19 +454,6 @@ int board_init(void) return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); }
-int board_mmc_init(bd_t *bis) -{
- int ret;
- bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
- ret = bcm2835_get_mmc_clock();
- if (ret)
return ret;
- return bcm2835_sdhci_init(BCM2835_SDHCI_BASE, ret);
-}
int ft_board_setup(void *blob, bd_t *bd) { /* diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index 090a0b07140..3d6f2a33377 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -14,6 +14,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index 785bf21e9a3..ca0ef7afe74 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -15,6 +15,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index 5ff8ed1cf2b..185a56c2807 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -15,6 +15,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 5d44f297267..89ecef8994e 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -14,6 +14,7 @@ CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y CONFIG_OF_EMBED=y +CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_DM_ETH=y diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index cb2bd40c65e..c96c35a9da4 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -37,14 +37,23 @@ */
#include <common.h> +#include <dm.h> #include <malloc.h> +#include <memalign.h> #include <sdhci.h> -#include <mach/timer.h> +#include <asm/arch/msg.h> +#include <asm/arch/mbox.h> #include <mach/sdhci.h> +#include <mach/timer.h>
/* 400KHz is max freq for card ID etc. Use that as min */ #define MIN_FREQ 400000
+struct bcm2835_sdhci_plat {
- struct mmc_config cfg;
- struct mmc mmc;
+};
struct bcm2835_sdhci_host { struct sdhci_host host; uint twoticks_delay; @@ -57,7 +66,7 @@ static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host) }
static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val,
int reg)
int reg)
{ struct bcm2835_sdhci_host *bcm_host = to_bcm(host);
@@ -149,16 +158,33 @@ static const struct sdhci_ops bcm2835_ops = { .read_b = bcm2835_sdhci_readb, };
-int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) +static int bcm2835_sdhci_bind(struct udevice *dev) {
- struct bcm2835_sdhci_host *bcm_host;
- struct sdhci_host *host;
- struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev);
- bcm_host = calloc(1, sizeof(*bcm_host));
- if (!bcm_host) {
printf("sdhci_host calloc fail!\n");
return -ENOMEM;
- return sdhci_bind(dev, &plat->mmc, &plat->cfg);
+}
+static int bcm2835_sdhci_probe(struct udevice *dev) +{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev);
struct bcm2835_sdhci_host *priv = dev_get_priv(dev);
struct sdhci_host *host = &priv->host;
fdt_addr_t base;
int emmc_freq;
int ret;
base = dev_get_addr(dev);
if (base == FDT_ADDR_T_NONE)
return -EINVAL;
ret = bcm2835_get_mmc_clock();
if (ret < 0) {
debug("%s: Failed to set MMC clock (err=%d)\n", __func__, ret);
return ret;
}
emmc_freq = ret;
/*
- See the comments in bcm2835_sdhci_raw_writel().
@@ -173,18 +199,41 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) * Multiply by 1000000 to get uS per two ticks. * +1 for hack rounding. */
- bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1;
- bcm_host->last_write = 0;
- priv->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1;
- priv->last_write = 0;
- host = &bcm_host->host;
- host->name = "bcm2835_sdhci";
- host->ioaddr = (void *)(unsigned long)regbase;
- host->name = dev->name;
- host->ioaddr = (void *)base; host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; host->ops = &bcm2835_ops;
- add_sdhci(host, emmc_freq, MIN_FREQ);
- ret = sdhci_setup_cfg(&plat->cfg, host, emmc_freq, MIN_FREQ);
- if (ret) {
debug("%s: Failed to setup SDHCI (err=%d)\n", __func__, ret);
return ret;
- }
- upriv->mmc = &plat->mmc;
- host->mmc = &plat->mmc;
- host->mmc->priv = host;
- return 0;
- return sdhci_probe(dev);
}
+static const struct udevice_id bcm2835_sdhci_match[] = {
- { .compatible = "brcm,bcm2835-sdhci" },
- { /* sentinel */ }
+};
+U_BOOT_DRIVER(sdhci_cdns) = {
- .name = "sdhci-bcm2835",
- .id = UCLASS_MMC,
- .of_match = bcm2835_sdhci_match,
- .bind = bcm2835_sdhci_bind,
- .probe = bcm2835_sdhci_probe,
- .priv_auto_alloc_size = sizeof(struct bcm2835_sdhci_host),
- .platdata_auto_alloc_size = sizeof(struct bcm2835_sdhci_plat),
- .ops = &sdhci_ops,
+};

We should not use an embedded device tree on a production board. There does not seem to be any reason for it in commit 7670909. So drop this.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
configs/rpi_2_defconfig | 1 - configs/rpi_3_32b_defconfig | 1 - configs/rpi_3_defconfig | 1 - configs/rpi_defconfig | 1 - 4 files changed, 4 deletions(-)
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index 3d6f2a33377..f8f123c4a62 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -13,7 +13,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y -CONFIG_OF_EMBED=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index ca0ef7afe74..3ff932c3617 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -14,7 +14,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y -CONFIG_OF_EMBED=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index 185a56c2807..98d7bd2c500 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -14,7 +14,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y -CONFIG_OF_EMBED=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 89ecef8994e..23d540d1298 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -13,7 +13,6 @@ CONFIG_CMD_MMC=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y -CONFIG_OF_EMBED=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCM2835=y

Add a function to get the video size to the msg handler and remove it from the video driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
arch/arm/mach-bcm283x/include/mach/msg.h | 9 +++++++++ arch/arm/mach-bcm283x/msg.c | 26 ++++++++++++++++++++++++++ drivers/video/bcm2835.c | 20 +++----------------- 3 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-bcm283x/include/mach/msg.h b/arch/arm/mach-bcm283x/include/mach/msg.h index 8fd4ace124d..c785c43a67a 100644 --- a/arch/arm/mach-bcm283x/include/mach/msg.h +++ b/arch/arm/mach-bcm283x/include/mach/msg.h @@ -22,4 +22,13 @@ int bcm2835_power_on_module(u32 module); */ int bcm2835_get_mmc_clock(void);
+/** + * bcm2835_get_video_size() - get the current display size + * + * @widthp: Returns the width in pixels + * @heightp: Returns the height in pixels + * @return 0 if OK, -ve on error + */ +int bcm2835_get_video_size(int *widthp, int *heightp); + #endif diff --git a/arch/arm/mach-bcm283x/msg.c b/arch/arm/mach-bcm283x/msg.c index facb916711c..17266c01a69 100644 --- a/arch/arm/mach-bcm283x/msg.c +++ b/arch/arm/mach-bcm283x/msg.c @@ -6,6 +6,7 @@
#include <common.h> #include <memalign.h> +#include <phys2bus.h> #include <asm/arch/mbox.h>
struct msg_set_power_state { @@ -20,6 +21,12 @@ struct msg_get_clock_rate { u32 end_tag; };
+struct msg_query { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_physical_w_h physical_w_h; + u32 end_tag; +}; + int bcm2835_power_on_module(u32 module) { ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1); @@ -65,3 +72,22 @@ int bcm2835_get_mmc_clock(void)
return msg_clk->get_clock_rate.body.resp.rate_hz; } + +int bcm2835_get_video_size(int *widthp, int *heightp) +{ + ALLOC_CACHE_ALIGN_BUFFER(struct msg_query, msg_query, 1); + int ret; + + BCM2835_MBOX_INIT_HDR(msg_query); + BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h, + GET_PHYSICAL_W_H); + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr); + if (ret) { + printf("bcm2835: Could not query display resolution\n"); + return ret; + } + *widthp = msg_query->physical_w_h.body.resp.width; + *heightp = msg_query->physical_w_h.body.resp.height; + + return 0; +} diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c index cc6454f10d4..eb137be11ca 100644 --- a/drivers/video/bcm2835.c +++ b/drivers/video/bcm2835.c @@ -9,6 +9,7 @@ #include <memalign.h> #include <phys2bus.h> #include <asm/arch/mbox.h> +#include <asm/arch/msg.h> #include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR; @@ -18,12 +19,6 @@ vidinfo_t panel_info;
static u32 bcm2835_pitch;
-struct msg_query { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_physical_w_h physical_w_h; - u32 end_tag; -}; - struct msg_setup { struct bcm2835_mbox_hdr hdr; struct bcm2835_mbox_tag_physical_w_h physical_w_h; @@ -40,27 +35,18 @@ struct msg_setup {
void lcd_ctrl_init(void *lcdbase) { - ALLOC_CACHE_ALIGN_BUFFER(struct msg_query, msg_query, 1); ALLOC_CACHE_ALIGN_BUFFER(struct msg_setup, msg_setup, 1); int ret; - u32 w, h; + int w, h; u32 fb_start, fb_end;
debug("bcm2835: Query resolution...\n"); - - BCM2835_MBOX_INIT_HDR(msg_query); - BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h, - GET_PHYSICAL_W_H); - ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr); + ret = bcm2835_get_video_size(&w, &h); if (ret) { - printf("bcm2835: Could not query display resolution\n"); /* FIXME: How to disable the LCD to prevent errors? hang()? */ return; }
- w = msg_query->physical_w_h.body.resp.width; - h = msg_query->physical_w_h.body.resp.height; - debug("bcm2835: Setting up display for %d x %d\n", w, h);
BCM2835_MBOX_INIT_HDR(msg_setup);

On Fri, 20 Jan 2017 07:07:47 -0700 Simon Glass sjg@chromium.org wrote:
Add a function to get the video size to the msg handler and remove it from the video driver.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Anatolij Gustschin agust@denx.de
-- Anatolij

Add a function to set the video parameters to the msg handler and remove it from the video driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
arch/arm/mach-bcm283x/include/mach/msg.h | 17 ++++++++ arch/arm/mach-bcm283x/msg.c | 61 ++++++++++++++++++++++++++++ drivers/video/bcm2835.c | 68 +++++--------------------------- 3 files changed, 88 insertions(+), 58 deletions(-)
diff --git a/arch/arm/mach-bcm283x/include/mach/msg.h b/arch/arm/mach-bcm283x/include/mach/msg.h index c785c43a67a..478b1f1c501 100644 --- a/arch/arm/mach-bcm283x/include/mach/msg.h +++ b/arch/arm/mach-bcm283x/include/mach/msg.h @@ -31,4 +31,21 @@ int bcm2835_get_mmc_clock(void); */ int bcm2835_get_video_size(int *widthp, int *heightp);
+/** + * bcm2835_set_video_params() - set the video parameters + * + * @widthp: Video width to request (returns the actual width selected) + * @heightp: Video height to request (returns the actual height selected) + * @depth_bpp: Requested bit depth + * @pixel_order: Pixel order to use (BCM2835_MBOX_PIXEL_ORDER_...) + * @alpha_mode: Alpha transparency mode to use (BCM2835_MBOX_ALPHA_MODE_...) + * @fb_basep: Returns base address of frame buffer + * @fb_sizep: Returns size of frame buffer + * @pitchp: Returns number of bytes in each frame buffer line + * @return 0 if OK, -ve on error + */ +int bcm2835_set_video_params(int *widthp, int *heightp, int depth_bpp, + int pixel_order, int alpha_mode, ulong *fb_basep, + ulong *fb_sizep, int *pitchp); + #endif diff --git a/arch/arm/mach-bcm283x/msg.c b/arch/arm/mach-bcm283x/msg.c index 17266c01a69..92e93ad9e55 100644 --- a/arch/arm/mach-bcm283x/msg.c +++ b/arch/arm/mach-bcm283x/msg.c @@ -27,6 +27,20 @@ struct msg_query { u32 end_tag; };
+struct msg_setup { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_physical_w_h physical_w_h; + struct bcm2835_mbox_tag_virtual_w_h virtual_w_h; + struct bcm2835_mbox_tag_depth depth; + struct bcm2835_mbox_tag_pixel_order pixel_order; + struct bcm2835_mbox_tag_alpha_mode alpha_mode; + struct bcm2835_mbox_tag_virtual_offset virtual_offset; + struct bcm2835_mbox_tag_overscan overscan; + struct bcm2835_mbox_tag_allocate_buffer allocate_buffer; + struct bcm2835_mbox_tag_pitch pitch; + u32 end_tag; +}; + int bcm2835_power_on_module(u32 module) { ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1); @@ -91,3 +105,50 @@ int bcm2835_get_video_size(int *widthp, int *heightp)
return 0; } + +int bcm2835_set_video_params(int *widthp, int *heightp, int depth_bpp, + int pixel_order, int alpha_mode, ulong *fb_basep, + ulong *fb_sizep, int *pitchp) +{ + ALLOC_CACHE_ALIGN_BUFFER(struct msg_setup, msg_setup, 1); + int ret; + + BCM2835_MBOX_INIT_HDR(msg_setup); + BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H); + msg_setup->physical_w_h.body.req.width = *widthp; + msg_setup->physical_w_h.body.req.height = *heightp; + BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H); + msg_setup->virtual_w_h.body.req.width = *widthp; + msg_setup->virtual_w_h.body.req.height = *heightp; + BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH); + msg_setup->depth.body.req.bpp = 32; + BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER); + msg_setup->pixel_order.body.req.order = pixel_order; + BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE); + msg_setup->alpha_mode.body.req.alpha = alpha_mode; + BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET); + msg_setup->virtual_offset.body.req.x = 0; + msg_setup->virtual_offset.body.req.y = 0; + BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN); + msg_setup->overscan.body.req.top = 0; + msg_setup->overscan.body.req.bottom = 0; + msg_setup->overscan.body.req.left = 0; + msg_setup->overscan.body.req.right = 0; + BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER); + msg_setup->allocate_buffer.body.req.alignment = 0x100; + BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_setup->pitch, GET_PITCH); + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr); + if (ret) { + printf("bcm2835: Could not configure display\n"); + return ret; + } + *widthp = msg_setup->physical_w_h.body.resp.width; + *heightp = msg_setup->physical_w_h.body.resp.height; + *pitchp = msg_setup->pitch.body.resp.pitch; + *fb_basep = bus_to_phys( + msg_setup->allocate_buffer.body.resp.fb_address); + *fb_sizep = msg_setup->allocate_buffer.body.resp.fb_size; + + return 0; +} diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c index eb137be11ca..cd15f7f32ae 100644 --- a/drivers/video/bcm2835.c +++ b/drivers/video/bcm2835.c @@ -17,28 +17,13 @@ DECLARE_GLOBAL_DATA_PTR; /* Global variables that lcd.c expects to exist */ vidinfo_t panel_info;
-static u32 bcm2835_pitch; - -struct msg_setup { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_physical_w_h physical_w_h; - struct bcm2835_mbox_tag_virtual_w_h virtual_w_h; - struct bcm2835_mbox_tag_depth depth; - struct bcm2835_mbox_tag_pixel_order pixel_order; - struct bcm2835_mbox_tag_alpha_mode alpha_mode; - struct bcm2835_mbox_tag_virtual_offset virtual_offset; - struct bcm2835_mbox_tag_overscan overscan; - struct bcm2835_mbox_tag_allocate_buffer allocate_buffer; - struct bcm2835_mbox_tag_pitch pitch; - u32 end_tag; -}; +static int bcm2835_pitch;
void lcd_ctrl_init(void *lcdbase) { - ALLOC_CACHE_ALIGN_BUFFER(struct msg_setup, msg_setup, 1); int ret; int w, h; - u32 fb_start, fb_end; + ulong fb_base, fb_size, fb_start, fb_end;
debug("bcm2835: Query resolution...\n"); ret = bcm2835_get_video_size(&w, &h); @@ -48,42 +33,9 @@ void lcd_ctrl_init(void *lcdbase) }
debug("bcm2835: Setting up display for %d x %d\n", w, h); - - BCM2835_MBOX_INIT_HDR(msg_setup); - BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H); - msg_setup->physical_w_h.body.req.width = w; - msg_setup->physical_w_h.body.req.height = h; - BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H); - msg_setup->virtual_w_h.body.req.width = w; - msg_setup->virtual_w_h.body.req.height = h; - BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH); - msg_setup->depth.body.req.bpp = 32; - BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER); - msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_RGB; - BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE); - msg_setup->alpha_mode.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED; - BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET); - msg_setup->virtual_offset.body.req.x = 0; - msg_setup->virtual_offset.body.req.y = 0; - BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN); - msg_setup->overscan.body.req.top = 0; - msg_setup->overscan.body.req.bottom = 0; - msg_setup->overscan.body.req.left = 0; - msg_setup->overscan.body.req.right = 0; - BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER); - msg_setup->allocate_buffer.body.req.alignment = 0x100; - BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_setup->pitch, GET_PITCH); - - ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr); - if (ret) { - printf("bcm2835: Could not configure display\n"); - /* FIXME: How to disable the LCD to prevent errors? hang()? */ - return; - } - - w = msg_setup->physical_w_h.body.resp.width; - h = msg_setup->physical_w_h.body.resp.height; - bcm2835_pitch = msg_setup->pitch.body.resp.pitch; + ret = bcm2835_set_video_params(&w, &h, 32, BCM2835_MBOX_PIXEL_ORDER_RGB, + BCM2835_MBOX_ALPHA_MODE_IGNORED, + &fb_base, &fb_size, &bcm2835_pitch);
debug("bcm2835: Final resolution is %d x %d\n", w, h);
@@ -91,15 +43,14 @@ void lcd_ctrl_init(void *lcdbase) panel_info.vl_row = h; panel_info.vl_bpix = LCD_COLOR32;
- gd->fb_base = bus_to_phys( - msg_setup->allocate_buffer.body.resp.fb_address); + gd->fb_base = fb_base;
/* Enable dcache for the frame buffer */ - fb_start = gd->fb_base & ~(MMU_SECTION_SIZE - 1); - fb_end = gd->fb_base + msg_setup->allocate_buffer.body.resp.fb_size; + fb_start = fb_base & ~(MMU_SECTION_SIZE - 1); + fb_end = fb_base + fb_size; fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT); mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start, - DCACHE_WRITEBACK); + DCACHE_WRITEBACK); lcd_set_flush_dcache(1); }
@@ -110,5 +61,6 @@ void lcd_enable(void) int lcd_get_size(int *line_length) { *line_length = bcm2835_pitch; + return *line_length * panel_info.vl_row; }

On Fri, 20 Jan 2017 07:07:48 -0700 Simon Glass sjg@chromium.org wrote:
Add a function to set the video parameters to the msg handler and remove it from the video driver.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Anatolij Gustschin agust@denx.de
-- Anatolij

Adjust this function so that we can convert it to support CONFIG_DM_VIDEO without a lot of code duplication.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
common/lcd_simplefb.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/common/lcd_simplefb.c b/common/lcd_simplefb.c index 2ba00f6d34c..e479b492b88 100644 --- a/common/lcd_simplefb.c +++ b/common/lcd_simplefb.c @@ -16,17 +16,28 @@ DECLARE_GLOBAL_DATA_PTR;
static int lcd_dt_simplefb_configure_node(void *blob, int off) { - int vl_col = lcd_get_pixel_width(); - int vl_row = lcd_get_pixel_height(); -#if LCD_BPP == LCD_COLOR16 - return fdt_setup_simplefb_node(blob, off, gd->fb_base, vl_col, vl_row, - vl_col * 2, "r5g6b5"); -#elif LCD_BPP == LCD_COLOR32 - return fdt_setup_simplefb_node(blob, off, gd->fb_base, vl_col, vl_row, - vl_col * 4, "a8r8g8b8"); -#else - return -1; -#endif + int xsize, ysize; + int bpix; /* log2 of bits per pixel */ + const char *name; + ulong fb_base; + + xsize = lcd_get_pixel_width(); + ysize = lcd_get_pixel_height(); + bpix = LCD_BPP; + fb_base = gd->fb_base; + switch (bpix) { + case 4: /* VIDEO_BPP16 */ + name = "r5g6b5"; + break; + case 5: /* VIDEO_BPP32 */ + name = "a8r8g8b8"; + break; + default: + return -EINVAL; + } + + return fdt_setup_simplefb_node(blob, off, fb_base, xsize, ysize, + xsize * (1 << bpix) / 8, name); }
int lcd_dt_simplefb_add_node(void *blob)

On Fri, 20 Jan 2017 07:07:49 -0700 Simon Glass sjg@chromium.org wrote:
Adjust this function so that we can convert it to support CONFIG_DM_VIDEO without a lot of code duplication.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Anatolij Gustschin agust@denx.de
-- Anatolij

Allow this to work with CONFIG_DM_VIDEO enabled.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
common/lcd_simplefb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/common/lcd_simplefb.c b/common/lcd_simplefb.c index e479b492b88..d7e9fc9f65c 100644 --- a/common/lcd_simplefb.c +++ b/common/lcd_simplefb.c @@ -8,9 +8,11 @@ */
#include <common.h> +#include <dm.h> #include <lcd.h> #include <fdt_support.h> #include <libfdt.h> +#include <video.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -20,11 +22,27 @@ static int lcd_dt_simplefb_configure_node(void *blob, int off) int bpix; /* log2 of bits per pixel */ const char *name; ulong fb_base; +#ifdef CONFIG_DM_VIDEO + struct video_uc_platdata *plat; + struct video_priv *uc_priv; + struct udevice *dev; + int ret;
+ ret = uclass_first_device_err(UCLASS_VIDEO, &dev); + if (ret) + return ret; + uc_priv = dev_get_uclass_priv(dev); + plat = dev_get_uclass_platdata(dev); + xsize = uc_priv->xsize; + ysize = uc_priv->ysize; + bpix = uc_priv->bpix; + fb_base = plat->base; +#else xsize = lcd_get_pixel_width(); ysize = lcd_get_pixel_height(); bpix = LCD_BPP; fb_base = gd->fb_base; +#endif switch (bpix) { case 4: /* VIDEO_BPP16 */ name = "r5g6b5";

On Fri, 20 Jan 2017 07:07:50 -0700 Simon Glass sjg@chromium.org wrote:
Allow this to work with CONFIG_DM_VIDEO enabled.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Anatolij Gustschin agust@denx.de
-- Anatolij

Adjust the video driver to work with driver model and move over existing baords. There is no need to keep the old code.
We can also drop setting of CONFIG_FB_ADDR since driver model doesn't have this problem.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None
configs/rpi_2_defconfig | 2 +- configs/rpi_3_32b_defconfig | 2 +- configs/rpi_3_defconfig | 2 +- configs/rpi_defconfig | 2 +- drivers/video/bcm2835.c | 62 ++++++++++++++++++++------------------------- include/configs/rpi.h | 11 ++------ 6 files changed, 34 insertions(+), 47 deletions(-)
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index f8f123c4a62..e492468a840 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -21,6 +21,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y +CONFIG_DM_VIDEO=y CONFIG_CONSOLE_SCROLL_LINES=10 -CONFIG_LCD=y CONFIG_PHYS_TO_BUS=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index 3ff932c3617..efcc23e5f4b 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -23,6 +23,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y +CONFIG_DM_VIDEO=y CONFIG_CONSOLE_SCROLL_LINES=10 -CONFIG_LCD=y CONFIG_PHYS_TO_BUS=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index 98d7bd2c500..8f39d32cd61 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -23,6 +23,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y +CONFIG_DM_VIDEO=y CONFIG_CONSOLE_SCROLL_LINES=10 -CONFIG_LCD=y CONFIG_PHYS_TO_BUS=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 23d540d1298..62a1d981e99 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -21,6 +21,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y +CONFIG_DM_VIDEO=y CONFIG_CONSOLE_SCROLL_LINES=10 -CONFIG_LCD=y CONFIG_PHYS_TO_BUS=y diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c index cd15f7f32ae..952ef596611 100644 --- a/drivers/video/bcm2835.c +++ b/drivers/video/bcm2835.c @@ -5,62 +5,56 @@ */
#include <common.h> -#include <lcd.h> -#include <memalign.h> -#include <phys2bus.h> +#include <dm.h> +#include <video.h> #include <asm/arch/mbox.h> #include <asm/arch/msg.h> -#include <asm/global_data.h>
-DECLARE_GLOBAL_DATA_PTR; - -/* Global variables that lcd.c expects to exist */ -vidinfo_t panel_info; - -static int bcm2835_pitch; - -void lcd_ctrl_init(void *lcdbase) +static int bcm2835_video_probe(struct udevice *dev) { + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); int ret; - int w, h; + int w, h, pitch; ulong fb_base, fb_size, fb_start, fb_end;
debug("bcm2835: Query resolution...\n"); ret = bcm2835_get_video_size(&w, &h); - if (ret) { - /* FIXME: How to disable the LCD to prevent errors? hang()? */ - return; - } + if (ret) + return -EIO;
debug("bcm2835: Setting up display for %d x %d\n", w, h); ret = bcm2835_set_video_params(&w, &h, 32, BCM2835_MBOX_PIXEL_ORDER_RGB, BCM2835_MBOX_ALPHA_MODE_IGNORED, - &fb_base, &fb_size, &bcm2835_pitch); + &fb_base, &fb_size, &pitch);
debug("bcm2835: Final resolution is %d x %d\n", w, h);
- panel_info.vl_col = w; - panel_info.vl_row = h; - panel_info.vl_bpix = LCD_COLOR32; - - gd->fb_base = fb_base; - /* Enable dcache for the frame buffer */ fb_start = fb_base & ~(MMU_SECTION_SIZE - 1); fb_end = fb_base + fb_size; fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT); mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start, DCACHE_WRITEBACK); - lcd_set_flush_dcache(1); -} + video_set_flush_dcache(dev, true);
-void lcd_enable(void) -{ -} + uc_priv->xsize = w; + uc_priv->ysize = h; + uc_priv->bpix = VIDEO_BPP32; + plat->base = fb_base; + plat->size = fb_size;
-int lcd_get_size(int *line_length) -{ - *line_length = bcm2835_pitch; - - return *line_length * panel_info.vl_row; + return 0; } + +static const struct udevice_id bcm2835_video_ids[] = { + { .compatible = "brcm,bcm2835-hdmi" }, + { } +}; + +U_BOOT_DRIVER(bcm2835_video) = { + .name = "bcm2835_video", + .id = UCLASS_VIDEO, + .of_match = bcm2835_video_ids, + .probe = bcm2835_video_probe, +}; diff --git a/include/configs/rpi.h b/include/configs/rpi.h index a0afeadcaa2..960b19345cc 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -56,13 +56,6 @@ #define CONFIG_BCM2835_GPIO /* LCD */ #define CONFIG_LCD_DT_SIMPLEFB -#define LCD_BPP LCD_COLOR32 -/* - * Prevent allocation of RAM for FB; the real FB address is queried - * dynamically from the VideoCore co-processor, and comes from RAM - * not owned by the ARM CPU. - */ -#define CONFIG_FB_ADDR 0 #define CONFIG_VIDEO_BCM2835 #define CONFIG_SYS_WHITE_ON_BLACK
@@ -121,8 +114,8 @@ #define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG #define ENV_DEVICE_SETTINGS \ "stdin=serial,usbkbd\0" \ - "stdout=serial,lcd\0" \ - "stderr=serial,lcd\0" + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0"
/* * Memory layout for where various images get loaded by boot scripts:

On Fri, 20 Jan 2017 07:07:51 -0700 Simon Glass sjg@chromium.org wrote:
Adjust the video driver to work with driver model and move over existing baords. There is no need to keep the old code.
We can also drop setting of CONFIG_FB_ADDR since driver model doesn't have this problem.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Anatolij Gustschin agust@denx.de
-- Anatolij

The board code should all move into msg.c for consistency. Add a TODO for this.
Signed-off-by: Simon Glass sjg@chromium.org
---
Changes in v4: - Add patches to convert video and MMC to driver model also - Rebase to master
Changes in v3: - Drop applied patches from series - Drop patch to introduce usbethaddr for driver model
board/raspberrypi/rpi/rpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 3d44cd4e55d..eb43a0c86d7 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -29,7 +29,7 @@ DECLARE_GLOBAL_DATA_PTR; /* From lowlevel_init.S */ extern unsigned long fw_dtb_pointer;
- +/* TODO(sjg@chromium.org): Move these to the msg.c file */ struct msg_get_arm_mem { struct bcm2835_mbox_hdr hdr; struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;

On Fri, Jan 20, 2017 at 07:07:35AM -0700, Simon Glass wrote:
Raspberry Pi uses a DWC2 USB controller and a SMSC USB Ethernet adaptor. Driver model support for these is available.
This series does the following:
- Enable CONFIG_DM_ETH and CONFIG_DM_USB on Raspberry Pi
- Convert the MMC driver to driver model
- Convert the video driver to driver model
- Fixes a driver model video bug which accessed beyond the frame buffer
- Fixes start-up of MMC with driver model (e.g. at present it does not support env_fat)
- Clean up a few loose ends
With Ethernet active the device list looks something like this:
There's something wrong with the ethernet changes, at least on RPi 3. The test.py TFTP test fails as the CRC32 on the file doesn't match, so something got corrupted along the way. I haven't thrown my monitor and USB keyboard on the Pi yet to try out the video parts. Thanks!

Hi Tom,
On 23 January 2017 at 10:22, Tom Rini trini@konsulko.com wrote:
On Fri, Jan 20, 2017 at 07:07:35AM -0700, Simon Glass wrote:
Raspberry Pi uses a DWC2 USB controller and a SMSC USB Ethernet adaptor. Driver model support for these is available.
This series does the following:
- Enable CONFIG_DM_ETH and CONFIG_DM_USB on Raspberry Pi
- Convert the MMC driver to driver model
- Convert the video driver to driver model
- Fixes a driver model video bug which accessed beyond the frame buffer
- Fixes start-up of MMC with driver model (e.g. at present it does not support env_fat)
- Clean up a few loose ends
With Ethernet active the device list looks something like this:
There's something wrong with the ethernet changes, at least on RPi 3. The test.py TFTP test fails as the CRC32 on the file doesn't match, so something got corrupted along the way. I haven't thrown my monitor and USB keyboard on the Pi yet to try out the video parts. Thanks!
OK, I will take a look at the CONFIG_DM_ETH patch. Feel free to pick up the other patches if you like.
Regards, Simon

Hi Tom,
On 6 February 2017 at 08:32, Simon Glass sjg@chromium.org wrote:
Hi Tom,
On 23 January 2017 at 10:22, Tom Rini trini@konsulko.com wrote:
On Fri, Jan 20, 2017 at 07:07:35AM -0700, Simon Glass wrote:
Raspberry Pi uses a DWC2 USB controller and a SMSC USB Ethernet adaptor. Driver model support for these is available.
This series does the following:
- Enable CONFIG_DM_ETH and CONFIG_DM_USB on Raspberry Pi
- Convert the MMC driver to driver model
- Convert the video driver to driver model
- Fixes a driver model video bug which accessed beyond the frame buffer
- Fixes start-up of MMC with driver model (e.g. at present it does not support env_fat)
- Clean up a few loose ends
With Ethernet active the device list looks something like this:
There's something wrong with the ethernet changes, at least on RPi 3. The test.py TFTP test fails as the CRC32 on the file doesn't match, so something got corrupted along the way. I haven't thrown my monitor and USB keyboard on the Pi yet to try out the video parts. Thanks!
OK, I will take a look at the CONFIG_DM_ETH patch. Feel free to pick up the other patches if you like.
I have been able to repeat this. The problem (strangely) appears to be that invalidate_dcache_range() does not work correctly. The symptom is that only the first half of the first block of file data is received (the rest is zeroes).
There is something odd about this on armv8. For one thing it uses the same function for invalidate and flush, which clearly cannot work if the buffer has been modified by the CPU since it was last used. In fact we do this in the dwc2.c driver But armv7 doesn't have this problem and the problem repeated on rpi2. On the original rpi the problem does not occur.
If I change the invalidate_dcache_range() call in transfer_chunk() in drivers/usb/host/dwc2.c to invalidate_dcache_all() then everything works.
If I put a flush_dcache_range() call immediately after the call at the top (in the if (!in && xfer_len) block) then it works. This is making sure that the CPU doesn't have that data cached.
If I I try the tftpboot a second time it seems to work. In fact things settle down after a few block transfers and the rest of the file seems OK.
If I disable the cache ('dcache off') then it works.
I tried creating a new invalidate_dcache_range() function on armv8 to use 'dc ivac' instead of 'dc civac' but no dice.
I cannot really explain why it works correctly without DM for USB, or why rpi is unaffected.
So in summary there is definitely a bug somewhere, but I cannot see where exactly it is. Ideas welcome!
Regards, Simon

Hi Tom,
On 31 March 2017 at 22:19, Simon Glass sjg@chromium.org wrote:
Hi Tom,
On 6 February 2017 at 08:32, Simon Glass sjg@chromium.org wrote:
Hi Tom,
On 23 January 2017 at 10:22, Tom Rini trini@konsulko.com wrote:
On Fri, Jan 20, 2017 at 07:07:35AM -0700, Simon Glass wrote:
Raspberry Pi uses a DWC2 USB controller and a SMSC USB Ethernet adaptor. Driver model support for these is available.
This series does the following:
- Enable CONFIG_DM_ETH and CONFIG_DM_USB on Raspberry Pi
- Convert the MMC driver to driver model
- Convert the video driver to driver model
- Fixes a driver model video bug which accessed beyond the frame buffer
- Fixes start-up of MMC with driver model (e.g. at present it does not support env_fat)
- Clean up a few loose ends
With Ethernet active the device list looks something like this:
There's something wrong with the ethernet changes, at least on RPi 3. The test.py TFTP test fails as the CRC32 on the file doesn't match, so something got corrupted along the way. I haven't thrown my monitor and USB keyboard on the Pi yet to try out the video parts. Thanks!
OK, I will take a look at the CONFIG_DM_ETH patch. Feel free to pick up the other patches if you like.
I have been able to repeat this. The problem (strangely) appears to be that invalidate_dcache_range() does not work correctly. The symptom is that only the first half of the first block of file data is received (the rest is zeroes).
There is something odd about this on armv8. For one thing it uses the same function for invalidate and flush, which clearly cannot work if the buffer has been modified by the CPU since it was last used. In fact we do this in the dwc2.c driver But armv7 doesn't have this problem and the problem repeated on rpi2. On the original rpi the problem does not occur.
If I change the invalidate_dcache_range() call in transfer_chunk() in drivers/usb/host/dwc2.c to invalidate_dcache_all() then everything works.
If I put a flush_dcache_range() call immediately after the call at the top (in the if (!in && xfer_len) block) then it works. This is making sure that the CPU doesn't have that data cached.
If I I try the tftpboot a second time it seems to work. In fact things settle down after a few block transfers and the rest of the file seems OK.
If I disable the cache ('dcache off') then it works.
I tried creating a new invalidate_dcache_range() function on armv8 to use 'dc ivac' instead of 'dc civac' but no dice.
I cannot really explain why it works correctly without DM for USB, or why rpi is unaffected.
So in summary there is definitely a bug somewhere, but I cannot see where exactly it is. Ideas welcome!
I forgot to mention that I can easily create a patch to make the dwc2 USB driver work, by using separate input and output buffers. That way the CPU will (likely) never cache incoming data and the clean/invalidate is fine. I've tested this and it seems to work.
But I must be missing something.
Regards, Simon

On Fri, Mar 31, 2017 at 10:34:35PM -0600, Simon Glass wrote:
Hi Tom,
On 31 March 2017 at 22:19, Simon Glass sjg@chromium.org wrote:
Hi Tom,
On 6 February 2017 at 08:32, Simon Glass sjg@chromium.org wrote:
Hi Tom,
On 23 January 2017 at 10:22, Tom Rini trini@konsulko.com wrote:
On Fri, Jan 20, 2017 at 07:07:35AM -0700, Simon Glass wrote:
Raspberry Pi uses a DWC2 USB controller and a SMSC USB Ethernet adaptor. Driver model support for these is available.
This series does the following:
- Enable CONFIG_DM_ETH and CONFIG_DM_USB on Raspberry Pi
- Convert the MMC driver to driver model
- Convert the video driver to driver model
- Fixes a driver model video bug which accessed beyond the frame buffer
- Fixes start-up of MMC with driver model (e.g. at present it does not support env_fat)
- Clean up a few loose ends
With Ethernet active the device list looks something like this:
There's something wrong with the ethernet changes, at least on RPi 3. The test.py TFTP test fails as the CRC32 on the file doesn't match, so something got corrupted along the way. I haven't thrown my monitor and USB keyboard on the Pi yet to try out the video parts. Thanks!
OK, I will take a look at the CONFIG_DM_ETH patch. Feel free to pick up the other patches if you like.
I have been able to repeat this. The problem (strangely) appears to be that invalidate_dcache_range() does not work correctly. The symptom is that only the first half of the first block of file data is received (the rest is zeroes).
There is something odd about this on armv8. For one thing it uses the same function for invalidate and flush, which clearly cannot work if the buffer has been modified by the CPU since it was last used. In fact we do this in the dwc2.c driver But armv7 doesn't have this problem and the problem repeated on rpi2. On the original rpi the problem does not occur.
If I change the invalidate_dcache_range() call in transfer_chunk() in drivers/usb/host/dwc2.c to invalidate_dcache_all() then everything works.
If I put a flush_dcache_range() call immediately after the call at the top (in the if (!in && xfer_len) block) then it works. This is making sure that the CPU doesn't have that data cached.
If I I try the tftpboot a second time it seems to work. In fact things settle down after a few block transfers and the rest of the file seems OK.
If I disable the cache ('dcache off') then it works.
I tried creating a new invalidate_dcache_range() function on armv8 to use 'dc ivac' instead of 'dc civac' but no dice.
I cannot really explain why it works correctly without DM for USB, or why rpi is unaffected.
So in summary there is definitely a bug somewhere, but I cannot see where exactly it is. Ideas welcome!
I forgot to mention that I can easily create a patch to make the dwc2 USB driver work, by using separate input and output buffers. That way the CPU will (likely) never cache incoming data and the clean/invalidate is fine. I've tested this and it seems to work.
But I must be missing something.
And you've since fixed it I believe and I'm testing that PR now. Can you re-spin this series when you have time? Thanks!

Hi Tom,
On 5 April 2017 at 07:41, Tom Rini trini@konsulko.com wrote:
On Fri, Mar 31, 2017 at 10:34:35PM -0600, Simon Glass wrote:
Hi Tom,
On 31 March 2017 at 22:19, Simon Glass sjg@chromium.org wrote:
Hi Tom,
On 6 February 2017 at 08:32, Simon Glass sjg@chromium.org wrote:
Hi Tom,
On 23 January 2017 at 10:22, Tom Rini trini@konsulko.com wrote:
On Fri, Jan 20, 2017 at 07:07:35AM -0700, Simon Glass wrote:
Raspberry Pi uses a DWC2 USB controller and a SMSC USB Ethernet adaptor. Driver model support for these is available.
This series does the following:
- Enable CONFIG_DM_ETH and CONFIG_DM_USB on Raspberry Pi
- Convert the MMC driver to driver model
- Convert the video driver to driver model
- Fixes a driver model video bug which accessed beyond the frame buffer
- Fixes start-up of MMC with driver model (e.g. at present it does not support env_fat)
- Clean up a few loose ends
With Ethernet active the device list looks something like this:
There's something wrong with the ethernet changes, at least on RPi 3. The test.py TFTP test fails as the CRC32 on the file doesn't match, so something got corrupted along the way. I haven't thrown my monitor and USB keyboard on the Pi yet to try out the video parts. Thanks!
OK, I will take a look at the CONFIG_DM_ETH patch. Feel free to pick up the other patches if you like.
I have been able to repeat this. The problem (strangely) appears to be that invalidate_dcache_range() does not work correctly. The symptom is that only the first half of the first block of file data is received (the rest is zeroes).
There is something odd about this on armv8. For one thing it uses the same function for invalidate and flush, which clearly cannot work if the buffer has been modified by the CPU since it was last used. In fact we do this in the dwc2.c driver But armv7 doesn't have this problem and the problem repeated on rpi2. On the original rpi the problem does not occur.
If I change the invalidate_dcache_range() call in transfer_chunk() in drivers/usb/host/dwc2.c to invalidate_dcache_all() then everything works.
If I put a flush_dcache_range() call immediately after the call at the top (in the if (!in && xfer_len) block) then it works. This is making sure that the CPU doesn't have that data cached.
If I I try the tftpboot a second time it seems to work. In fact things settle down after a few block transfers and the rest of the file seems OK.
If I disable the cache ('dcache off') then it works.
I tried creating a new invalidate_dcache_range() function on armv8 to use 'dc ivac' instead of 'dc civac' but no dice.
I cannot really explain why it works correctly without DM for USB, or why rpi is unaffected.
So in summary there is definitely a bug somewhere, but I cannot see where exactly it is. Ideas welcome!
I forgot to mention that I can easily create a patch to make the dwc2 USB driver work, by using separate input and output buffers. That way the CPU will (likely) never cache incoming data and the clean/invalidate is fine. I've tested this and it seems to work.
But I must be missing something.
And you've since fixed it I believe and I'm testing that PR now. Can you re-spin this series when you have time? Thanks!
OK I have resent it without the dmc2 patch.
My preferred fix for the problem is this:
http://patchwork.ozlabs.org/patch/746917/
Regards, Simon
participants (4)
-
Anatolij Gustschin
-
Jaehoon Chung
-
Simon Glass
-
Tom Rini