diff mbox

[U-Boot,06/42] Use separate options for TPL support

Message ID 1472057546-10360-7-git-send-email-sjg@chromium.org
State Accepted
Commit 76f1f38816d8763b51e5f1d6ca099a88aa1fd077
Delegated to: Tom Rini
Headers show

Commit Message

Simon Glass Aug. 24, 2016, 4:51 p.m. UTC
At present TPL uses the same options as SPL support. In a few cases the board
config enables or disables the SPL options depending on whether
CONFIG_TPL_BUILD is defined.

With the move to Kconfig, options are determined for the whole build and
(without a hack like an #undef in a header file) cannot be controlled in this
way.

Create new TPL options for these and update users. This will allow Kconfig
conversion to proceed for these boards.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/Makefile                | 12 +++++++++++-
 drivers/Makefile               | 16 +++++++++++++++-
 include/common.h               | 15 +++++++++------
 include/configs/C29XPCIE.h     | 16 ++++++++--------
 include/configs/P1010RDB.h     | 14 +++++++-------
 include/configs/P1022DS.h      | 14 +++++++-------
 include/configs/p1_p2_rdb_pc.h | 14 +++++++-------
 lib/Makefile                   |  9 +++++++--
 scripts/Makefile.spl           | 10 +++++++++-
 9 files changed, 80 insertions(+), 40 deletions(-)

Comments

Stephen Warren Aug. 24, 2016, 6:16 p.m. UTC | #1
On 08/24/2016 10:51 AM, Simon Glass wrote:
> At present TPL uses the same options as SPL support. In a few cases the board
> config enables or disables the SPL options depending on whether
> CONFIG_TPL_BUILD is defined.
>
> With the move to Kconfig, options are determined for the whole build and
> (without a hack like an #undef in a header file) cannot be controlled in this
> way.
>
> Create new TPL options for these and update users. This will allow Kconfig
> conversion to proceed for these boards.

> diff --git a/common/Makefile b/common/Makefile

>  # environment
> -ifdef CONFIG_SPL_ENV_SUPPORT
> +ifdef CONFIG_TPL_BUILD
> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o
> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o
> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o
> +else
>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
> +endif

This feels like it will become an unbounded mess as the set of Kconfig 
options for SPL and TPL grow.

Rather, I think we should have a separate U-Boot build/binary, separate 
defconfig, etc. for main U-Boot, SPL (if a board uses it), TPL (if a 
board uses it), etc., plug perhaps some top-level definition to bind 
them all back together.

That way, we'll just have CONFIG_ENV_SUPPPORT, and never have any 
CONFIG_$(xxx)_ENV_SUPPORT. We completely avoid the proliferation of 
duplicated Kconfig symbols.

I vaguely recall mention of SPL choosing the DT for the main U-Boot. 
What if SPL needs different DTs? We'd need to use TPL to choose the DT. 
What if TPL needs different DT to? We'd need to introduce a new binary 
(QPL?) to do the selection. That might then need CONFIG_QPL_*. If we 
just use the same Kconfig symbols everywhere, and just configure which 
options are enabled via a separate defconfig for main, SPL, TPL, QPL, 
we'll have a much more manageable system.

Of course, that would probably require some Kconfig work to allow the 
defconfigs for ${board}_spl_defconfig, ${board}_tpl_defconfig, 
${board}_qpl_defconfig, and ${board}_defconfig to all include 
${board}_common_defconfig (or whatever set common files are appropriate) 
to avoid duplication. ChromeOS already solved that for the kernel IIRC. 
Also, we'd likely need some kind of top-level ${board}_xxx file to 
indicate that plain "make" should separately build spl, tpl, main for 
the boad, and how to munge them together.
Tom Rini Aug. 25, 2016, 12:41 a.m. UTC | #2
On Wed, Aug 24, 2016 at 12:16:23PM -0600, Stephen Warren wrote:
> On 08/24/2016 10:51 AM, Simon Glass wrote:
> >At present TPL uses the same options as SPL support. In a few cases the board
> >config enables or disables the SPL options depending on whether
> >CONFIG_TPL_BUILD is defined.
> >
> >With the move to Kconfig, options are determined for the whole build and
> >(without a hack like an #undef in a header file) cannot be controlled in this
> >way.
> >
> >Create new TPL options for these and update users. This will allow Kconfig
> >conversion to proceed for these boards.
> 
> >diff --git a/common/Makefile b/common/Makefile
> 
> > # environment
> >-ifdef CONFIG_SPL_ENV_SUPPORT
> >+ifdef CONFIG_TPL_BUILD
> >+obj-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o
> >+obj-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o
> >+obj-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o
> >+else
> > obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
> > obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
> > obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
> >+endif
> 
> This feels like it will become an unbounded mess as the set of
> Kconfig options for SPL and TPL grow.
> 
> Rather, I think we should have a separate U-Boot build/binary,
> separate defconfig, etc. for main U-Boot, SPL (if a board uses it),
> TPL (if a board uses it), etc., plug perhaps some top-level
> definition to bind them all back together.
> 
> That way, we'll just have CONFIG_ENV_SUPPPORT, and never have any
> CONFIG_$(xxx)_ENV_SUPPORT. We completely avoid the proliferation of
> duplicated Kconfig symbols.
> 
> I vaguely recall mention of SPL choosing the DT for the main U-Boot.
> What if SPL needs different DTs? We'd need to use TPL to choose the
> DT. What if TPL needs different DT to? We'd need to introduce a new
> binary (QPL?) to do the selection. That might then need
> CONFIG_QPL_*. If we just use the same Kconfig symbols everywhere,
> and just configure which options are enabled via a separate
> defconfig for main, SPL, TPL, QPL, we'll have a much more manageable
> system.
> 
> Of course, that would probably require some Kconfig work to allow
> the defconfigs for ${board}_spl_defconfig, ${board}_tpl_defconfig,
> ${board}_qpl_defconfig, and ${board}_defconfig to all include
> ${board}_common_defconfig (or whatever set common files are
> appropriate) to avoid duplication. ChromeOS already solved that for
> the kernel IIRC. Also, we'd likely need some kind of top-level
> ${board}_xxx file to indicate that plain "make" should separately
> build spl, tpl, main for the boad, and how to munge them together.

It's a bit of a mess, yes.  And it doesn't help matters that there's now
a growing number of boards that would like to / could go in the
direction of dropping SPL as they have sufficient initial memory to have
real U-Boot there to start with.  But I think the additional tooling
required to make the end user experience be at least as good as it is
now means we need to revisit this topic once things are largely in
Kconfig. I think the binary manager Simon showed a while ago will be
part this too, so that we can continue to have a functional output at
the end.
Masahiro Yamada Aug. 25, 2016, 2:20 a.m. UTC | #3
2016-08-25 1:51 GMT+09:00 Simon Glass <sjg@chromium.org>:
> At present TPL uses the same options as SPL support. In a few cases the board
> config enables or disables the SPL options depending on whether
> CONFIG_TPL_BUILD is defined.
>
> With the move to Kconfig, options are determined for the whole build and
> (without a hack like an #undef in a header file) cannot be controlled in this
> way.
>
> Create new TPL options for these and update users. This will allow Kconfig
> conversion to proceed for these boards.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>  common/Makefile                | 12 +++++++++++-
>  drivers/Makefile               | 16 +++++++++++++++-
>  include/common.h               | 15 +++++++++------
>  include/configs/C29XPCIE.h     | 16 ++++++++--------
>  include/configs/P1010RDB.h     | 14 +++++++-------
>  include/configs/P1022DS.h      | 14 +++++++-------
>  include/configs/p1_p2_rdb_pc.h | 14 +++++++-------
>  lib/Makefile                   |  9 +++++++--
>  scripts/Makefile.spl           | 10 +++++++++-
>  9 files changed, 80 insertions(+), 40 deletions(-)
>
> diff --git a/common/Makefile b/common/Makefile
> index 21619b3..9a9a065 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -99,10 +99,16 @@ obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o
>  obj-$(CONFIG_USB_STORAGE) += usb_storage.o
>  endif
>  # environment
> -ifdef CONFIG_SPL_ENV_SUPPORT
> +ifdef CONFIG_TPL_BUILD
> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o
> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o
> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o
> +else
>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
> +endif
> +ifneq ($(CONFIG_TPL_ENV_SUPPORT)$(CONFIG_SPL_ENV_SUPPORT),)
>  obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
>  obj-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
>  obj-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o
> @@ -123,7 +129,11 @@ obj-$(CONFIG_SPD_EEPROM) += ddr_spd.o
>  obj-$(CONFIG_HWCONFIG) += hwconfig.o
>  obj-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
>  ifdef CONFIG_SPL_BUILD
> +ifdef CONFIG_TPL_BUILD
> +obj-$(CONFIG_TPL_SERIAL_SUPPORT) += console.o
> +else
>  obj-$(CONFIG_SPL_SERIAL_SUPPORT) += console.o
> +endif
>  else
>  obj-y += console.o
>  endif
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 7861d34..ca98273 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -40,8 +40,22 @@ obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/
>  obj-$(CONFIG_SPL_SATA_SUPPORT) += block/
>  obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/
>  obj-$(CONFIG_SPL_MMC_SUPPORT) += block/
> +endif
> +
> +ifdef CONFIG_TPL_BUILD
> +
> +obj-$(CONFIG_TPL_I2C_SUPPORT) += i2c/
> +obj-$(CONFIG_TPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/
> +obj-$(CONFIG_TPL_MMC_SUPPORT) += mmc/
> +obj-$(CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
> +obj-$(CONFIG_TPL_NAND_SUPPORT) += mtd/nand/
> +obj-$(CONFIG_TPL_SERIAL_SUPPORT) += serial/
> +obj-$(CONFIG_TPL_SPI_FLASH_SUPPORT) += mtd/spi/
> +obj-$(CONFIG_TPL_SPI_SUPPORT) += spi/
> +
> +endif
>
> -else
> +ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
>
>  obj-y += adc/
>  obj-$(CONFIG_DM_DEMO) += demo/
> diff --git a/include/common.h b/include/common.h



I'd say a strong "no" to this patch.

The root cause of this pita is in the booting order.

For CONFIG_SPL=y && CONFIG_TPL=n,
    Boot ROM ->  SPL  ->  U-Boot proper


For CONFIG_SPL=y && CONFIG_TPL=y,
    Boot ROM ->  SPL  ->  TPL  -> U-Boot proper


For the latter case, TPL can be big enough to use
environments and/or device drivers.
While, SPL is a really small program
that is only possible in ad-hoc implementation,
so that probably enable none of CONFIG_SPL_ options.


How about this idea:
Let's exploit the fact that TPL exists for SoCs
that load a really small program (4KB or less).
Swap the order of SPL and TPL like follows:

  Boot ROM ->  TPL  ->  SPL   ->  U-Boot proper

With this change,  TPL is too small to enable luxury features.
No need to add CONFIG_TPL_ stuff in Kconfig.

Let's think TPL is a short of "Tiny Program Loader" instead of
"Tertiary Program Loader".
(SPL is no longer "Secondary" in this case, so a bit funny, though.)
Simon Glass Aug. 25, 2016, 12:04 p.m. UTC | #4
Hi Stephen,

On 24 August 2016 at 12:16, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/24/2016 10:51 AM, Simon Glass wrote:
>>
>> At present TPL uses the same options as SPL support. In a few cases the
>> board
>> config enables or disables the SPL options depending on whether
>> CONFIG_TPL_BUILD is defined.
>>
>> With the move to Kconfig, options are determined for the whole build and
>> (without a hack like an #undef in a header file) cannot be controlled in
>> this
>> way.
>>
>> Create new TPL options for these and update users. This will allow Kconfig
>> conversion to proceed for these boards.
>
>
>> diff --git a/common/Makefile b/common/Makefile
>
>
>>  # environment
>> -ifdef CONFIG_SPL_ENV_SUPPORT
>> +ifdef CONFIG_TPL_BUILD
>> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o
>> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o
>> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o
>> +else
>>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
>>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
>>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
>> +endif
>
>
> This feels like it will become an unbounded mess as the set of Kconfig
> options for SPL and TPL grow.

It is possible to refactor this a bit to avoid the duplication by
defining a variable which is TPL or SPL. I didn't think it worth it
for 3 lines.

>
> Rather, I think we should have a separate U-Boot build/binary, separate
> defconfig, etc. for main U-Boot, SPL (if a board uses it), TPL (if a board
> uses it), etc., plug perhaps some top-level definition to bind them all back
> together.
>
> That way, we'll just have CONFIG_ENV_SUPPPORT, and never have any
> CONFIG_$(xxx)_ENV_SUPPORT. We completely avoid the proliferation of
> duplicated Kconfig symbols.

We has it that way originally and changed to separate options a few
releases later. While I understand that this can look bad in
Makefiles, it isn't that bad. It is *much* easier for a user to deal
with a single config that has a few extra CONFIG options, than 3
configs.

While we have about 8000 CONFIG options, we have <150 for SPL and with
this series 10 for TPL. It just doesn't make sense to treat everything
the same.

>
> I vaguely recall mention of SPL choosing the DT for the main U-Boot. What if
> SPL needs different DTs? We'd need to use TPL to choose the DT. What if TPL
> needs different DT to? We'd need to introduce a new binary (QPL?) to do the
> selection. That might then need CONFIG_QPL_*. If we just use the same
> Kconfig symbols everywhere, and just configure which options are enabled via
> a separate defconfig for main, SPL, TPL, QPL, we'll have a much more
> manageable system.

Never say never, but I can't imagine why we would introduce a new boot
element just to choose the device tree. SPL can easily do this itself
if needed - we would just need to support attaching multiple DTs to
SPL, which is easy enough.

>
> Of course, that would probably require some Kconfig work to allow the
> defconfigs for ${board}_spl_defconfig, ${board}_tpl_defconfig,
> ${board}_qpl_defconfig, and ${board}_defconfig to all include
> ${board}_common_defconfig (or whatever set common files are appropriate) to
> avoid duplication. ChromeOS already solved that for the kernel IIRC. Also,
> we'd likely need some kind of top-level ${board}_xxx file to indicate that
> plain "make" should separately build spl, tpl, main for the boad, and how to
> munge them together.

Yes it would be nice to split out the build a little better.

Chrome OS is trying to solve the problem that boards that use the same
arch tend  to share options. We already handle that with Kconfig and
it seems easier to add 'default y' for an option under in the arch's
Kconfig definition than have multiple levels of defconfig files that
we join together. Although it does have drawbacks, such as that people
might unset a required option and break the board. We can use 'select'
it is really cannot be unset, but then someone comes along with a
special-case board..

In terms of munging binaries together to make an image, see my recent
binman series for some ideas as Tom says.

Regards,
Simon
Simon Glass Aug. 25, 2016, 12:04 p.m. UTC | #5
Hi Masahiro,

On 24 August 2016 at 20:20, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> 2016-08-25 1:51 GMT+09:00 Simon Glass <sjg@chromium.org>:
>> At present TPL uses the same options as SPL support. In a few cases the board
>> config enables or disables the SPL options depending on whether
>> CONFIG_TPL_BUILD is defined.
>>
>> With the move to Kconfig, options are determined for the whole build and
>> (without a hack like an #undef in a header file) cannot be controlled in this
>> way.
>>
>> Create new TPL options for these and update users. This will allow Kconfig
>> conversion to proceed for these boards.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>>  common/Makefile                | 12 +++++++++++-
>>  drivers/Makefile               | 16 +++++++++++++++-
>>  include/common.h               | 15 +++++++++------
>>  include/configs/C29XPCIE.h     | 16 ++++++++--------
>>  include/configs/P1010RDB.h     | 14 +++++++-------
>>  include/configs/P1022DS.h      | 14 +++++++-------
>>  include/configs/p1_p2_rdb_pc.h | 14 +++++++-------
>>  lib/Makefile                   |  9 +++++++--
>>  scripts/Makefile.spl           | 10 +++++++++-
>>  9 files changed, 80 insertions(+), 40 deletions(-)
>>
>> diff --git a/common/Makefile b/common/Makefile
>> index 21619b3..9a9a065 100644
>> --- a/common/Makefile
>> +++ b/common/Makefile
>> @@ -99,10 +99,16 @@ obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o
>>  obj-$(CONFIG_USB_STORAGE) += usb_storage.o
>>  endif
>>  # environment
>> -ifdef CONFIG_SPL_ENV_SUPPORT
>> +ifdef CONFIG_TPL_BUILD
>> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o
>> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o
>> +obj-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o
>> +else
>>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
>>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
>>  obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
>> +endif
>> +ifneq ($(CONFIG_TPL_ENV_SUPPORT)$(CONFIG_SPL_ENV_SUPPORT),)
>>  obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
>>  obj-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
>>  obj-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o
>> @@ -123,7 +129,11 @@ obj-$(CONFIG_SPD_EEPROM) += ddr_spd.o
>>  obj-$(CONFIG_HWCONFIG) += hwconfig.o
>>  obj-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
>>  ifdef CONFIG_SPL_BUILD
>> +ifdef CONFIG_TPL_BUILD
>> +obj-$(CONFIG_TPL_SERIAL_SUPPORT) += console.o
>> +else
>>  obj-$(CONFIG_SPL_SERIAL_SUPPORT) += console.o
>> +endif
>>  else
>>  obj-y += console.o
>>  endif
>> diff --git a/drivers/Makefile b/drivers/Makefile
>> index 7861d34..ca98273 100644
>> --- a/drivers/Makefile
>> +++ b/drivers/Makefile
>> @@ -40,8 +40,22 @@ obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/
>>  obj-$(CONFIG_SPL_SATA_SUPPORT) += block/
>>  obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/
>>  obj-$(CONFIG_SPL_MMC_SUPPORT) += block/
>> +endif
>> +
>> +ifdef CONFIG_TPL_BUILD
>> +
>> +obj-$(CONFIG_TPL_I2C_SUPPORT) += i2c/
>> +obj-$(CONFIG_TPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/
>> +obj-$(CONFIG_TPL_MMC_SUPPORT) += mmc/
>> +obj-$(CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
>> +obj-$(CONFIG_TPL_NAND_SUPPORT) += mtd/nand/
>> +obj-$(CONFIG_TPL_SERIAL_SUPPORT) += serial/
>> +obj-$(CONFIG_TPL_SPI_FLASH_SUPPORT) += mtd/spi/
>> +obj-$(CONFIG_TPL_SPI_SUPPORT) += spi/
>> +
>> +endif
>>
>> -else
>> +ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
>>
>>  obj-y += adc/
>>  obj-$(CONFIG_DM_DEMO) += demo/
>> diff --git a/include/common.h b/include/common.h
>
>
>
> I'd say a strong "no" to this patch.
>
> The root cause of this pita is in the booting order.
>
> For CONFIG_SPL=y && CONFIG_TPL=n,
>     Boot ROM ->  SPL  ->  U-Boot proper
>
>
> For CONFIG_SPL=y && CONFIG_TPL=y,
>     Boot ROM ->  SPL  ->  TPL  -> U-Boot proper
>
>
> For the latter case, TPL can be big enough to use
> environments and/or device drivers.
> While, SPL is a really small program
> that is only possible in ad-hoc implementation,
> so that probably enable none of CONFIG_SPL_ options.
>
>
> How about this idea:
> Let's exploit the fact that TPL exists for SoCs
> that load a really small program (4KB or less).
> Swap the order of SPL and TPL like follows:
>
>   Boot ROM ->  TPL  ->  SPL   ->  U-Boot proper
>
> With this change,  TPL is too small to enable luxury features.
> No need to add CONFIG_TPL_ stuff in Kconfig.
>
> Let's think TPL is a short of "Tiny Program Loader" instead of
> "Tertiary Program Loader".
> (SPL is no longer "Secondary" in this case, so a bit funny, though.)

At present SPL is full-featured for many board, but for things that
use TPL, SPL is very small. That is a mismatch. It makes sense I think
that SPL is the full-featured thing in all cases. Thus TPL is the
small thing, if it is needed at all.

That would involve refactoring the boards that use TPL. I think it
could be done though, and the idea has merit.

However, this is certainly not feasible in the same patch that moves
these things to Kconfig. We need to move things forward in stages. If
people want to bisect to find problems they really can't deal with
landing on a patch that moves things to Kconfig and changes the
meaning of the options at the same time.

Also, I notice that even TPL does enable some options (e.g. serial,
NAND), so we can't get away without the TPL options. They exist for a
reason.

Regards,
Simon
diff mbox

Patch

diff --git a/common/Makefile b/common/Makefile
index 21619b3..9a9a065 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -99,10 +99,16 @@  obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o
 obj-$(CONFIG_USB_STORAGE) += usb_storage.o
 endif
 # environment
-ifdef CONFIG_SPL_ENV_SUPPORT
+ifdef CONFIG_TPL_BUILD
+obj-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o
+obj-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o
+obj-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o
+else
 obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
 obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
 obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
+endif
+ifneq ($(CONFIG_TPL_ENV_SUPPORT)$(CONFIG_SPL_ENV_SUPPORT),)
 obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
 obj-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
 obj-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o
@@ -123,7 +129,11 @@  obj-$(CONFIG_SPD_EEPROM) += ddr_spd.o
 obj-$(CONFIG_HWCONFIG) += hwconfig.o
 obj-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
 ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_TPL_BUILD
+obj-$(CONFIG_TPL_SERIAL_SUPPORT) += console.o
+else
 obj-$(CONFIG_SPL_SERIAL_SUPPORT) += console.o
+endif
 else
 obj-y += console.o
 endif
diff --git a/drivers/Makefile b/drivers/Makefile
index 7861d34..ca98273 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -40,8 +40,22 @@  obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/
 obj-$(CONFIG_SPL_SATA_SUPPORT) += block/
 obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/
 obj-$(CONFIG_SPL_MMC_SUPPORT) += block/
+endif
+
+ifdef CONFIG_TPL_BUILD
+
+obj-$(CONFIG_TPL_I2C_SUPPORT) += i2c/
+obj-$(CONFIG_TPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/
+obj-$(CONFIG_TPL_MMC_SUPPORT) += mmc/
+obj-$(CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
+obj-$(CONFIG_TPL_NAND_SUPPORT) += mtd/nand/
+obj-$(CONFIG_TPL_SERIAL_SUPPORT) += serial/
+obj-$(CONFIG_TPL_SPI_FLASH_SUPPORT) += mtd/spi/
+obj-$(CONFIG_TPL_SPI_SUPPORT) += spi/
+
+endif
 
-else
+ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
 
 obj-y += adc/
 obj-$(CONFIG_DM_DEMO) += demo/
diff --git a/include/common.h b/include/common.h
index e9f0dea..a8d833b 100644
--- a/include/common.h
+++ b/include/common.h
@@ -866,17 +866,20 @@  int	getc(void);
 int	tstc(void);
 
 /* stdout */
-#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SERIAL_SUPPORT)
-#define	putc(...) do { } while (0)
-#define puts(...) do { } while (0)
-#define printf(...) do { } while (0)
-#define vprintf(...) do { } while (0)
-#else
+#if !defined(CONFIG_SPL_BUILD) || \
+	(defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_SERIAL_SUPPORT)) || \
+	(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) && \
+		defined(CONFIG_SPL_SERIAL_SUPPORT))
 void	putc(const char c);
 void	puts(const char *s);
 int	printf(const char *fmt, ...)
 		__attribute__ ((format (__printf__, 1, 2)));
 int	vprintf(const char *fmt, va_list args);
+#else
+#define	putc(...) do { } while (0)
+#define puts(...) do { } while (0)
+#define printf(...) do { } while (0)
+#define vprintf(...) do { } while (0)
 #endif
 
 /* stderr */
diff --git a/include/configs/C29XPCIE.h b/include/configs/C29XPCIE.h
index f75919d..8ec1a90 100644
--- a/include/configs/C29XPCIE.h
+++ b/include/configs/C29XPCIE.h
@@ -27,15 +27,15 @@ 
 #ifdef CONFIG_TPL_BUILD
 #define CONFIG_SPL_NAND_BOOT
 #define CONFIG_SPL_FLUSH_IMAGE
-#define CONFIG_SPL_ENV_SUPPORT
+#define CONFIG_TPL_ENV_SUPPORT
 #define CONFIG_SPL_NAND_INIT
-#define CONFIG_SPL_SERIAL_SUPPORT
-#define CONFIG_SPL_LIBGENERIC_SUPPORT
-#define CONFIG_SPL_LIBCOMMON_SUPPORT
-#define CONFIG_SPL_I2C_SUPPORT
-#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
-#define CONFIG_SPL_NAND_SUPPORT
-#define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
+#define CONFIG_TPL_SERIAL_SUPPORT
+#define CONFIG_TPL_LIBGENERIC_SUPPORT
+#define CONFIG_TPL_LIBCOMMON_SUPPORT
+#define CONFIG_TPL_I2C_SUPPORT
+#define CONFIG_TPL_DRIVERS_MISC_SUPPORT
+#define CONFIG_TPL_NAND_SUPPORT
+#define CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT
 #define CONFIG_SPL_COMMON_INIT_DDR
 #define CONFIG_SPL_MAX_SIZE		(128 << 10)
 #define CONFIG_SPL_TEXT_BASE		0xf8f81000
diff --git a/include/configs/P1010RDB.h b/include/configs/P1010RDB.h
index 5ab6602..fecaebe 100644
--- a/include/configs/P1010RDB.h
+++ b/include/configs/P1010RDB.h
@@ -106,15 +106,15 @@ 
 #ifdef CONFIG_TPL_BUILD
 #define CONFIG_SPL_NAND_BOOT
 #define CONFIG_SPL_FLUSH_IMAGE
-#define CONFIG_SPL_ENV_SUPPORT
+#define CONFIG_TPL_ENV_SUPPORT
 #define CONFIG_SPL_NAND_INIT
-#define CONFIG_SPL_SERIAL_SUPPORT
-#define CONFIG_SPL_LIBGENERIC_SUPPORT
-#define CONFIG_SPL_LIBCOMMON_SUPPORT
-#define CONFIG_SPL_I2C_SUPPORT
-#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_TPL_SERIAL_SUPPORT
+#define CONFIG_TPL_LIBGENERIC_SUPPORT
+#define CONFIG_TPL_LIBCOMMON_SUPPORT
+#define CONFIG_TPL_I2C_SUPPORT
+#define CONFIG_TPL_NAND_SUPPORT
 #define CONFIG_SPL_DRIVERS_MISC_SUPPORT
-#define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
+#define CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT
 #define CONFIG_SPL_COMMON_INIT_DDR
 #define CONFIG_SPL_MAX_SIZE		(128 << 10)
 #define CONFIG_SPL_TEXT_BASE		0xD0001000
diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h
index 5d572b4..fac72f3 100644
--- a/include/configs/P1022DS.h
+++ b/include/configs/P1022DS.h
@@ -78,14 +78,14 @@ 
 #ifdef CONFIG_TPL_BUILD
 #define CONFIG_SPL_NAND_BOOT
 #define CONFIG_SPL_FLUSH_IMAGE
-#define CONFIG_SPL_ENV_SUPPORT
+#define CONFIG_TPL_ENV_SUPPORT
 #define CONFIG_SPL_NAND_INIT
-#define CONFIG_SPL_SERIAL_SUPPORT
-#define CONFIG_SPL_LIBGENERIC_SUPPORT
-#define CONFIG_SPL_LIBCOMMON_SUPPORT
-#define CONFIG_SPL_I2C_SUPPORT
-#define CONFIG_SPL_NAND_SUPPORT
-#define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
+#define CONFIG_TPL_SERIAL_SUPPORT
+#define CONFIG_TPL_LIBGENERIC_SUPPORT
+#define CONFIG_TPL_LIBCOMMON_SUPPORT
+#define CONFIG_TPL_I2C_SUPPORT
+#define CONFIG_TPL_NAND_SUPPORT
+#define CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT
 #define CONFIG_SPL_COMMON_INIT_DDR
 #define CONFIG_SPL_MAX_SIZE		(128 << 10)
 #define CONFIG_SPL_TEXT_BASE		0xf8f81000
diff --git a/include/configs/p1_p2_rdb_pc.h b/include/configs/p1_p2_rdb_pc.h
index 5d0a570..4a277e4 100644
--- a/include/configs/p1_p2_rdb_pc.h
+++ b/include/configs/p1_p2_rdb_pc.h
@@ -241,14 +241,14 @@ 
 #ifdef CONFIG_TPL_BUILD
 #define CONFIG_SPL_NAND_BOOT
 #define CONFIG_SPL_FLUSH_IMAGE
-#define CONFIG_SPL_ENV_SUPPORT
+#define CONFIG_TPL_ENV_SUPPORT
 #define CONFIG_SPL_NAND_INIT
-#define CONFIG_SPL_SERIAL_SUPPORT
-#define CONFIG_SPL_LIBGENERIC_SUPPORT
-#define CONFIG_SPL_LIBCOMMON_SUPPORT
-#define CONFIG_SPL_I2C_SUPPORT
-#define CONFIG_SPL_NAND_SUPPORT
-#define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
+#define CONFIG_TPL_SERIAL_SUPPORT
+#define CONFIG_TPL_LIBGENERIC_SUPPORT
+#define CONFIG_TPL_LIBCOMMON_SUPPORT
+#define CONFIG_TPL_I2C_SUPPORT
+#define CONFIG_TPL_NAND_SUPPORT
+#define CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT
 #define CONFIG_SPL_COMMON_INIT_DDR
 #define CONFIG_SPL_MAX_SIZE		(128 << 10)
 #define CONFIG_SPL_TEXT_BASE		0xf8f81000
diff --git a/lib/Makefile b/lib/Makefile
index f6a8ba1..c81bfeb 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -78,11 +78,16 @@  obj-$(CONFIG_LIB_UUID) += uuid.o
 obj-$(CONFIG_LIB_RAND) += rand.o
 
 ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_TPL_BUILD
+SERIAL_SUPPORT := $(CONFIG_TPL_SERIAL_SUPPORT)
+else
+SERIAL_SUPPORT := $(CONFIG_SPL_SERIAL_SUPPORT)
+endif
 # SPL U-Boot may use full-printf, tiny-printf or none at all
 ifdef CONFIG_USE_TINY_PRINTF
-obj-$(CONFIG_SPL_SERIAL_SUPPORT) += tiny-printf.o panic.o strto.o
+obj-$(SERIAL_SUPPORT) += tiny-printf.o panic.o strto.o
 else
-obj-$(CONFIG_SPL_SERIAL_SUPPORT) += vsprintf.o panic.o strto.o strmhz.o
+obj-$(SERIAL_SUPPORT) += vsprintf.o panic.o strto.o strmhz.o
 endif
 else
 # Main U-Boot always uses the full printf support
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 3ba9742..4994fa8 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -54,12 +54,20 @@  libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
 
 libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
 libs-y += common/init/
+
+# Special handling for a few options which support SPL/TPL
+ifeq ($(CONFIG_TPL_BUILD),y)
+libs-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += common/ cmd/
+libs-$(CONFIG_TPL_LIBGENERIC_SUPPORT) += lib/
+else
 libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ cmd/
+libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/
+endif
+
 libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/
 libs-y += drivers/
 libs-y += dts/
 libs-y += fs/
-libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/
 libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/
 libs-$(CONFIG_SPL_NET_SUPPORT) += net/