diff mbox

[U-Boot,38/60] ARM: tegra: remove tegra_get_chip()

Message ID 1461099580-3866-39-git-send-email-swarren@wwwdotorg.org
State Rejected
Delegated to: Tom Warren
Headers show

Commit Message

Stephen Warren April 19, 2016, 8:59 p.m. UTC
From: Stephen Warren <swarren@nvidia.com>

U-Boot is compiled for a single board, which in turn uses a specific SoC.
There's no need to make runtime decisions based on SoC ID. While there's
certainly an argument for making the code support different SoCs at
run-time, the Tegra code is so far from that possible ideal that the
existing runtime code is an anomaly. If this changes in the future, all
runtime decisions should likely be based on DT anyway.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/mach-tegra/ap.c               | 106 ++++++++++-----------------------
 arch/arm/mach-tegra/cache.c            |  20 +++----
 arch/arm/mach-tegra/cpu.c              |  16 ++---
 arch/arm/mach-tegra/cpu.h              |   6 --
 arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
 5 files changed, 51 insertions(+), 117 deletions(-)

Comments

Simon Glass April 23, 2016, 5:14 p.m. UTC | #1
Hi Stephen,

On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> U-Boot is compiled for a single board, which in turn uses a specific SoC.
> There's no need to make runtime decisions based on SoC ID. While there's
> certainly an argument for making the code support different SoCs at
> run-time, the Tegra code is so far from that possible ideal that the
> existing runtime code is an anomaly. If this changes in the future, all
> runtime decisions should likely be based on DT anyway.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  arch/arm/mach-tegra/ap.c               | 106 ++++++++++-----------------------
>  arch/arm/mach-tegra/cache.c            |  20 +++----
>  arch/arm/mach-tegra/cpu.c              |  16 ++---
>  arch/arm/mach-tegra/cpu.h              |   6 --
>  arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>  5 files changed, 51 insertions(+), 117 deletions(-)

What exactly is missing to prevent multi-arch support? Shouldn't we
head towards that rather than making it harder?

Regards,
Simon
Stephen Warren April 25, 2016, 7:25 p.m. UTC | #2
On 04/23/2016 11:14 AM, Simon Glass wrote:
> Hi Stephen,
>
> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> From: Stephen Warren <swarren@nvidia.com>
>>
>> U-Boot is compiled for a single board, which in turn uses a specific SoC.
>> There's no need to make runtime decisions based on SoC ID. While there's
>> certainly an argument for making the code support different SoCs at
>> run-time, the Tegra code is so far from that possible ideal that the
>> existing runtime code is an anomaly. If this changes in the future, all
>> runtime decisions should likely be based on DT anyway.
>>
>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>> ---
>>   arch/arm/mach-tegra/ap.c               | 106 ++++++++++-----------------------
>>   arch/arm/mach-tegra/cache.c            |  20 +++----
>>   arch/arm/mach-tegra/cpu.c              |  16 ++---
>>   arch/arm/mach-tegra/cpu.h              |   6 --
>>   arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>   5 files changed, 51 insertions(+), 117 deletions(-)
>
> What exactly is missing to prevent multi-arch support?

In a word: everything:-)

Pretty much all decisions in core architecture code, core Tegra code, 
drivers, and even board files are currently made at compile time. For 
example, consider drivers where the register layouts are different 
between different SoCs; not just new fields added, but existing fields 
moved to different offsets. Right now, we handle this by changing the 
register struct definition at compile time. To support multiple chips, 
we'd have to either (a) link in n copies of the driver, one per register 
layout, or (b) rework the driver to use #defines and runtime 
calculations for register offsets, like the Linux kernel drivers do. 
Tegra USB is one example. The pinmux and clock drivers have a 
significantly different sets of pins/clocks/resets/... per SoC, and 
enums/tables describing those sets are currently configured at compile 
time. Some PMIC constants (e.g. vdd_cpu voltage) are configured at 
compile-time, and even differ per board.

> Shouldn't we head towards that rather than making it harder?

I don't see any need for that, no.

U-Boot is built for a specific board (or in some cases a set of 
extremely closely related set of boards, such as the RPI A/B/A+/B+). 
There's no need to determine almost anything at run-time since almost 
all information is known at compile time, with exceptions such as 
standardized enumerable buses such as USB, PCIe. If we support multiple 
HW in a single binary, it gets bloated with code that simply isn't going 
to be used, since all the extra code is either for a platform that the 
build won't be installed on (e.g. clock/pinmux tables), or is overhead 
to add runtime detection of which block of code to use, which simply 
isn't needed in the current model.

In my opinion, firmware/bootloaders run on a single specific board, 
whereas full-featured operating systems support multiple systems.

As an aside, I've wondered whether U-Boot should be split into multiple 
parts; one HW-specific binary providing various drivers (e.g. via 
DM-related APIs?) and the other containing just high-level 
user-interface code such as the shell, high-level USB/... protocols, 
which would only call into those APIs. Still, I don't think we're 
anywhere close to that, and I'm not aware that it's a goal of the 
project at the moment.
Simon Glass April 27, 2016, 2:50 p.m. UTC | #3
Hi Stephen,

On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>
>> Hi Stephen,
>>
>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>
>>> From: Stephen Warren <swarren@nvidia.com>
>>>
>>> U-Boot is compiled for a single board, which in turn uses a specific SoC.
>>> There's no need to make runtime decisions based on SoC ID. While there's
>>> certainly an argument for making the code support different SoCs at
>>> run-time, the Tegra code is so far from that possible ideal that the
>>> existing runtime code is an anomaly. If this changes in the future, all
>>> runtime decisions should likely be based on DT anyway.
>>>
>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>> ---
>>>   arch/arm/mach-tegra/ap.c               | 106
>>> ++++++++++-----------------------
>>>   arch/arm/mach-tegra/cache.c            |  20 +++----
>>>   arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>   arch/arm/mach-tegra/cpu.h              |   6 --
>>>   arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>   5 files changed, 51 insertions(+), 117 deletions(-)
>>
>>
>> What exactly is missing to prevent multi-arch support?
>
>
> In a word: everything:-)
>
> Pretty much all decisions in core architecture code, core Tegra code,
> drivers, and even board files are currently made at compile time. For
> example, consider drivers where the register layouts are different between
> different SoCs; not just new fields added, but existing fields moved to
> different offsets. Right now, we handle this by changing the register struct
> definition at compile time. To support multiple chips, we'd have to either
> (a) link in n copies of the driver, one per register layout, or (b) rework
> the driver to use #defines and runtime calculations for register offsets,
> like the Linux kernel drivers do. Tegra USB is one example. The pinmux and
> clock drivers have a significantly different sets of pins/clocks/resets/...
> per SoC, and enums/tables describing those sets are currently configured at
> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are configured at
> compile-time, and even differ per board.

I wonder how far we would get by converting clock, pinctrl, reset to
driver model drivers?

>
>> Shouldn't we head towards that rather than making it harder?
>
>
> I don't see any need for that, no.
>
> U-Boot is built for a specific board (or in some cases a set of extremely
> closely related set of boards, such as the RPI A/B/A+/B+). There's no need
> to determine almost anything at run-time since almost all information is
> known at compile time, with exceptions such as standardized enumerable buses
> such as USB, PCIe. If we support multiple HW in a single binary, it gets
> bloated with code that simply isn't going to be used, since all the extra
> code is either for a platform that the build won't be installed on (e.g.
> clock/pinmux tables), or is overhead to add runtime detection of which block
> of code to use, which simply isn't needed in the current model.

It's not so much that. Presumably a build for a particular board would
not include support for and SoC it doesn't have. But it is still
useful to build the code. For example it would be nice to have an
overall Tegra build that enables all SoCs to avoid building every
board.

So it is a serious question. I suspect the main impediment may be
moving the clock and other core stuff to driver model.

>
> In my opinion, firmware/bootloaders run on a single specific board, whereas
> full-featured operating systems support multiple systems.

Except when the boards are pretty similar. Also, doesn't barebox have
only one build for Tegra?

>
> As an aside, I've wondered whether U-Boot should be split into multiple
> parts; one HW-specific binary providing various drivers (e.g. via DM-related
> APIs?) and the other containing just high-level user-interface code such as
> the shell, high-level USB/... protocols, which would only call into those
> APIs. Still, I don't think we're anywhere close to that, and I'm not aware
> that it's a goal of the project at the moment.

Well it gets built as one binary, but there's a pretty clear
separation in the code, at least with driver model. What's the purpose
of this?

Regards,
Simon
Stephen Warren April 27, 2016, 4:13 p.m. UTC | #4
On 04/27/2016 08:50 AM, Simon Glass wrote:
> Hi Stephen,
>
> On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>>
>>> Hi Stephen,
>>>
>>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>
>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>
>>>> U-Boot is compiled for a single board, which in turn uses a specific SoC.
>>>> There's no need to make runtime decisions based on SoC ID. While there's
>>>> certainly an argument for making the code support different SoCs at
>>>> run-time, the Tegra code is so far from that possible ideal that the
>>>> existing runtime code is an anomaly. If this changes in the future, all
>>>> runtime decisions should likely be based on DT anyway.
>>>>
>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>> ---
>>>>    arch/arm/mach-tegra/ap.c               | 106
>>>> ++++++++++-----------------------
>>>>    arch/arm/mach-tegra/cache.c            |  20 +++----
>>>>    arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>>    arch/arm/mach-tegra/cpu.h              |   6 --
>>>>    arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>>    5 files changed, 51 insertions(+), 117 deletions(-)
>>>
>>>
>>> What exactly is missing to prevent multi-arch support?
>>
>> In a word: everything:-)
>>
>> Pretty much all decisions in core architecture code, core Tegra code,
>> drivers, and even board files are currently made at compile time. For
>> example, consider drivers where the register layouts are different between
>> different SoCs; not just new fields added, but existing fields moved to
>> different offsets. Right now, we handle this by changing the register struct
>> definition at compile time. To support multiple chips, we'd have to either
>> (a) link in n copies of the driver, one per register layout, or (b) rework
>> the driver to use #defines and runtime calculations for register offsets,
>> like the Linux kernel drivers do. Tegra USB is one example. The pinmux and
>> clock drivers have a significantly different sets of pins/clocks/resets/...
>> per SoC, and enums/tables describing those sets are currently configured at
>> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are configured at
>> compile-time, and even differ per board.
>
> I wonder how far we would get by converting clock, pinctrl, reset to
> driver model drivers?

Well, I expect we'll find out soon. The next SoC has radically different 
clock/reset mechanisms, so we'll need to switch to standardized APIs for 
clock/reset on Tegra to isolate drivers from those differences, and I 
imagine that conversion would also involve conversion to DM since any 
standard APIs probably assume use of DM. I haven't investigated this in 
detail yet though.

>>> Shouldn't we head towards that rather than making it harder?
>>
>> I don't see any need for that, no.
>>
>> U-Boot is built for a specific board (or in some cases a set of extremely
>> closely related set of boards, such as the RPI A/B/A+/B+). There's no need
>> to determine almost anything at run-time since almost all information is
>> known at compile time, with exceptions such as standardized enumerable buses
>> such as USB, PCIe. If we support multiple HW in a single binary, it gets
>> bloated with code that simply isn't going to be used, since all the extra
>> code is either for a platform that the build won't be installed on (e.g.
>> clock/pinmux tables), or is overhead to add runtime detection of which block
>> of code to use, which simply isn't needed in the current model.
>
> It's not so much that. Presumably a build for a particular board would
> not include support for and SoC it doesn't have. But it is still
> useful to build the code. For example it would be nice to have an
> overall Tegra build that enables all SoCs to avoid building every
> board.
>
> So it is a serious question. I suspect the main impediment may be
> moving the clock and other core stuff to driver model.

Yes, everything is a bit too tightly coupled at the moment, and in many 
cases each SoC-specific implementation exposes the same global symbols 
which clients use. DM or similar conversions may well solve a lot of this.

>> In my opinion, firmware/bootloaders run on a single specific board, whereas
>> full-featured operating systems support multiple systems.
>
> Except when the boards are pretty similar. Also, doesn't barebox have
> only one build for Tegra?

I haven't looked at Barebox much. IIRC it only supports Tegra20 and not 
later SoCs which could simplify things. Besides, I'm not arguing that 
it's impossible to make a unified binary, simply that I don't see any 
need to do so, except perhaps your compile-coverage suggestion.

>> As an aside, I've wondered whether U-Boot should be split into multiple
>> parts; one HW-specific binary providing various drivers (e.g. via DM-related
>> APIs?) and the other containing just high-level user-interface code such as
>> the shell, high-level USB/... protocols, which would only call into those
>> APIs. Still, I don't think we're anywhere close to that, and I'm not aware
>> that it's a goal of the project at the moment.
>
> Well it gets built as one binary, but there's a pretty clear
> separation in the code, at least with driver model. What's the purpose
> of this?

It would allow the HW-agnostic portion to be compiled once (or once for 
a CPU ISA) and re-used with any of the HW-/board-specific "driver" 
blobs. It'd get use to "single binary" for the generic stuff, but 
without requiring the for HW-specific code. Perhaps the generic portion 
could even run on top of other driver stacks if they implemented the API 
it needed! However, this does ignore potential feature differences in 
the common binary, e.g. someone might want dfu/ums commands, but someone 
else might not need them and hence consider them bloat. Still, those 
configurations would be differentiated by feature more than HW, so it 
might still be useful.
Simon Glass April 29, 2016, 2:02 p.m. UTC | #5
Hi Stephen,

On 27 April 2016 at 10:13, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 04/27/2016 08:50 AM, Simon Glass wrote:
>>
>> Hi Stephen,
>>
>> On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>
>>> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>>>
>>>>
>>>> Hi Stephen,
>>>>
>>>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>
>>>>>
>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>
>>>>> U-Boot is compiled for a single board, which in turn uses a specific
>>>>> SoC.
>>>>> There's no need to make runtime decisions based on SoC ID. While
>>>>> there's
>>>>> certainly an argument for making the code support different SoCs at
>>>>> run-time, the Tegra code is so far from that possible ideal that the
>>>>> existing runtime code is an anomaly. If this changes in the future, all
>>>>> runtime decisions should likely be based on DT anyway.
>>>>>
>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>> ---
>>>>>    arch/arm/mach-tegra/ap.c               | 106
>>>>> ++++++++++-----------------------
>>>>>    arch/arm/mach-tegra/cache.c            |  20 +++----
>>>>>    arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>>>    arch/arm/mach-tegra/cpu.h              |   6 --
>>>>>    arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>>>    5 files changed, 51 insertions(+), 117 deletions(-)
>>>>
>>>>
>>>>
>>>> What exactly is missing to prevent multi-arch support?
>>>
>>>
>>> In a word: everything:-)
>>>
>>> Pretty much all decisions in core architecture code, core Tegra code,
>>> drivers, and even board files are currently made at compile time. For
>>> example, consider drivers where the register layouts are different
>>> between
>>> different SoCs; not just new fields added, but existing fields moved to
>>> different offsets. Right now, we handle this by changing the register
>>> struct
>>> definition at compile time. To support multiple chips, we'd have to
>>> either
>>> (a) link in n copies of the driver, one per register layout, or (b)
>>> rework
>>> the driver to use #defines and runtime calculations for register offsets,
>>> like the Linux kernel drivers do. Tegra USB is one example. The pinmux
>>> and
>>> clock drivers have a significantly different sets of
>>> pins/clocks/resets/...
>>> per SoC, and enums/tables describing those sets are currently configured
>>> at
>>> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are configured
>>> at
>>> compile-time, and even differ per board.
>>
>>
>> I wonder how far we would get by converting clock, pinctrl, reset to
>> driver model drivers?
>
>
> Well, I expect we'll find out soon. The next SoC has radically different
> clock/reset mechanisms, so we'll need to switch to standardized APIs for
> clock/reset on Tegra to isolate drivers from those differences, and I
> imagine that conversion would also involve conversion to DM since any
> standard APIs probably assume use of DM. I haven't investigated this in
> detail yet though.

That sounds like a good move.

>
>>>> Shouldn't we head towards that rather than making it harder?
>>>
>>>
>>> I don't see any need for that, no.
>>>
>>> U-Boot is built for a specific board (or in some cases a set of extremely
>>> closely related set of boards, such as the RPI A/B/A+/B+). There's no
>>> need
>>> to determine almost anything at run-time since almost all information is
>>> known at compile time, with exceptions such as standardized enumerable
>>> buses
>>> such as USB, PCIe. If we support multiple HW in a single binary, it gets
>>> bloated with code that simply isn't going to be used, since all the extra
>>> code is either for a platform that the build won't be installed on (e.g.
>>> clock/pinmux tables), or is overhead to add runtime detection of which
>>> block
>>> of code to use, which simply isn't needed in the current model.
>>
>>
>> It's not so much that. Presumably a build for a particular board would
>> not include support for and SoC it doesn't have. But it is still
>> useful to build the code. For example it would be nice to have an
>> overall Tegra build that enables all SoCs to avoid building every
>> board.
>>
>> So it is a serious question. I suspect the main impediment may be
>> moving the clock and other core stuff to driver model.
>
>
> Yes, everything is a bit too tightly coupled at the moment, and in many
> cases each SoC-specific implementation exposes the same global symbols which
> clients use. DM or similar conversions may well solve a lot of this.

With a suitable API (even it if is pretty basic) the coupling can
often go away. The current driver-model pinctrl/clock APIs are pretty
simple, but they are effective in this regard for the SoCs I've tried.

>
>>> In my opinion, firmware/bootloaders run on a single specific board,
>>> whereas
>>> full-featured operating systems support multiple systems.
>>
>>
>> Except when the boards are pretty similar. Also, doesn't barebox have
>> only one build for Tegra?
>
>
> I haven't looked at Barebox much. IIRC it only supports Tegra20 and not
> later SoCs which could simplify things. Besides, I'm not arguing that it's
> impossible to make a unified binary, simply that I don't see any need to do
> so, except perhaps your compile-coverage suggestion.

Sure. I think it might help push the APIs along though. I recall
creating a clock API for tegra20 some years ago. I think if we go to
the next level (clock drivers for each SoC) the SoC differences start
to look a lot less. It's mostly this core code that is the problem and
much of it should move to drivers IMO.

>
>>> As an aside, I've wondered whether U-Boot should be split into multiple
>>> parts; one HW-specific binary providing various drivers (e.g. via
>>> DM-related
>>> APIs?) and the other containing just high-level user-interface code such
>>> as
>>> the shell, high-level USB/... protocols, which would only call into those
>>> APIs. Still, I don't think we're anywhere close to that, and I'm not
>>> aware
>>> that it's a goal of the project at the moment.
>>
>>
>> Well it gets built as one binary, but there's a pretty clear
>> separation in the code, at least with driver model. What's the purpose
>> of this?
>
>
> It would allow the HW-agnostic portion to be compiled once (or once for a
> CPU ISA) and re-used with any of the HW-/board-specific "driver" blobs. It'd
> get use to "single binary" for the generic stuff, but without requiring the
> for HW-specific code. Perhaps the generic portion could even run on top of
> other driver stacks if they implemented the API it needed! However, this
> does ignore potential feature differences in the common binary, e.g. someone
> might want dfu/ums commands, but someone else might not need them and hence
> consider them bloat. Still, those configurations would be differentiated by
> feature more than HW, so it might still be useful.

Sounds cool. It would certainly tidy up the U-Boot API a lot, I
suppose. You could have a micro-module approach where every little
feature is its own loadable module. But really, what is the benefit?

Regards,
Simon
Stephen Warren April 29, 2016, 4:27 p.m. UTC | #6
On 04/29/2016 08:02 AM, Simon Glass wrote:
> Hi Stephen,
>
> On 27 April 2016 at 10:13, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 04/27/2016 08:50 AM, Simon Glass wrote:
>>>
>>> Hi Stephen,
>>>
>>> On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>
>>>> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>>>>
>>>>>
>>>>> Hi Stephen,
>>>>>
>>>>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>>
>>>>>>
>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>
>>>>>> U-Boot is compiled for a single board, which in turn uses a specific
>>>>>> SoC.
>>>>>> There's no need to make runtime decisions based on SoC ID. While
>>>>>> there's
>>>>>> certainly an argument for making the code support different SoCs at
>>>>>> run-time, the Tegra code is so far from that possible ideal that the
>>>>>> existing runtime code is an anomaly. If this changes in the future, all
>>>>>> runtime decisions should likely be based on DT anyway.
>>>>>>
>>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>>> ---
>>>>>>     arch/arm/mach-tegra/ap.c               | 106 ++++++++++-----------------------
>>>>>>     arch/arm/mach-tegra/cache.c            |  20 +++----
>>>>>>     arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>>>>     arch/arm/mach-tegra/cpu.h              |   6 --
>>>>>>     arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>>>>     5 files changed, 51 insertions(+), 117 deletions(-)
>>>>>
>>>>>
>>>>> What exactly is missing to prevent multi-arch support?
>>>>
>>>> In a word: everything:-)
>>>>
>>>> Pretty much all decisions in core architecture code, core Tegra code,
>>>> drivers, and even board files are currently made at compile time. For
>>>> example, consider drivers where the register layouts are different between
>>>> different SoCs; not just new fields added, but existing fields moved to
>>>> different offsets. Right now, we handle this by changing the register struct
>>>> definition at compile time. To support multiple chips, we'd have to either
>>>> (a) link in n copies of the driver, one per register layout, or (b) rework
>>>> the driver to use #defines and runtime calculations for register offsets,
>>>> like the Linux kernel drivers do. Tegra USB is one example. The pinmux and
>>>> clock drivers have a significantly different sets of pins/clocks/resets/...
>>>> per SoC, and enums/tables describing those sets are currently configured at
>>>> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are configured at
>>>> compile-time, and even differ per board.
>>>
>>> I wonder how far we would get by converting clock, pinctrl, reset to
>>> driver model drivers?
>>
>> Well, I expect we'll find out soon. The next SoC has radically different
>> clock/reset mechanisms, so we'll need to switch to standardized APIs for
>> clock/reset on Tegra to isolate drivers from those differences, and I
>> imagine that conversion would also involve conversion to DM since any
>> standard APIs probably assume use of DM. I haven't investigated this in
>> detail yet though.
>
> That sounds like a good move.

I'm not sure if you still object to this patch for now, or would be 
happy giving it an ack?
Simon Glass April 29, 2016, 4:53 p.m. UTC | #7
Hi Stephen,

On 29 April 2016 at 10:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 04/29/2016 08:02 AM, Simon Glass wrote:
>>
>> Hi Stephen,
>>
>> On 27 April 2016 at 10:13, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>
>>> On 04/27/2016 08:50 AM, Simon Glass wrote:
>>>>
>>>>
>>>> Hi Stephen,
>>>>
>>>> On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>
>>>>>
>>>>> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> Hi Stephen,
>>>>>>
>>>>>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org>
>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>>
>>>>>>> U-Boot is compiled for a single board, which in turn uses a specific
>>>>>>> SoC.
>>>>>>> There's no need to make runtime decisions based on SoC ID. While
>>>>>>> there's
>>>>>>> certainly an argument for making the code support different SoCs at
>>>>>>> run-time, the Tegra code is so far from that possible ideal that the
>>>>>>> existing runtime code is an anomaly. If this changes in the future,
>>>>>>> all
>>>>>>> runtime decisions should likely be based on DT anyway.
>>>>>>>
>>>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>>>> ---
>>>>>>>     arch/arm/mach-tegra/ap.c               | 106
>>>>>>> ++++++++++-----------------------
>>>>>>>     arch/arm/mach-tegra/cache.c            |  20 +++----
>>>>>>>     arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>>>>>     arch/arm/mach-tegra/cpu.h              |   6 --
>>>>>>>     arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>>>>>     5 files changed, 51 insertions(+), 117 deletions(-)
>>>>>>
>>>>>>
>>>>>>
>>>>>> What exactly is missing to prevent multi-arch support?
>>>>>
>>>>>
>>>>> In a word: everything:-)
>>>>>
>>>>> Pretty much all decisions in core architecture code, core Tegra code,
>>>>> drivers, and even board files are currently made at compile time. For
>>>>> example, consider drivers where the register layouts are different
>>>>> between
>>>>> different SoCs; not just new fields added, but existing fields moved to
>>>>> different offsets. Right now, we handle this by changing the register
>>>>> struct
>>>>> definition at compile time. To support multiple chips, we'd have to
>>>>> either
>>>>> (a) link in n copies of the driver, one per register layout, or (b)
>>>>> rework
>>>>> the driver to use #defines and runtime calculations for register
>>>>> offsets,
>>>>> like the Linux kernel drivers do. Tegra USB is one example. The pinmux
>>>>> and
>>>>> clock drivers have a significantly different sets of
>>>>> pins/clocks/resets/...
>>>>> per SoC, and enums/tables describing those sets are currently
>>>>> configured at
>>>>> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are configured
>>>>> at
>>>>> compile-time, and even differ per board.
>>>>
>>>>
>>>> I wonder how far we would get by converting clock, pinctrl, reset to
>>>> driver model drivers?
>>>
>>>
>>> Well, I expect we'll find out soon. The next SoC has radically different
>>> clock/reset mechanisms, so we'll need to switch to standardized APIs for
>>> clock/reset on Tegra to isolate drivers from those differences, and I
>>> imagine that conversion would also involve conversion to DM since any
>>> standard APIs probably assume use of DM. I haven't investigated this in
>>> detail yet though.
>>
>>
>> That sounds like a good move.
>
>
> I'm not sure if you still object to this patch for now, or would be happy
> giving it an ack?

Sorry, I still feel this is going in the wrong
direction...CONFIG_TEGRA124 should mean that the code supports it,
rather than the code exclusively supports it.

In your commit message you say:

"While there's
certainly an argument for making the code support different SoCs at
run-time, the Tegra code is so far from that possible ideal that the
existing runtime code is an anomaly. If this changes in the future, all
runtime decisions should likely be based on DT anyway."

Or even build time.... That statement  seems like saying that
everything is so terrible that we might as well give up.

What's your plan to move code into drivers? I am happy to help move
things over and get towards the goal rather than further away. But
really that should happen first.

Also, the model that seems to be emerging is that SPL detects the
platform and passes the correct DT to U-Boot proper.

Specifically I think the end state should be:
- Most SoC code is in drivers using driver model
- It is possible to build most of the tegra code without building each
SoC (just by having a 'tegra' board which enables all drivers)
- If someone wanted to support multiple SoCs it would not be
impossible to do so (even if mainline doesn't make it)
- New SoCs are supported mostly by adding new drivers (although there
is always of course some core/start-up code)

Do you agree with that?

Regards,
Simon
Simon Glass April 29, 2016, 5:42 p.m. UTC | #8
Hi Stephen,

On 29 April 2016 at 10:53, Simon Glass <sjg@chromium.org> wrote:
> Hi Stephen,
>
> On 29 April 2016 at 10:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 04/29/2016 08:02 AM, Simon Glass wrote:
>>>
>>> Hi Stephen,
>>>
>>> On 27 April 2016 at 10:13, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>
>>>> On 04/27/2016 08:50 AM, Simon Glass wrote:
>>>>>
>>>>>
>>>>> Hi Stephen,
>>>>>
>>>>> On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>>
>>>>>>
>>>>>> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Hi Stephen,
>>>>>>>
>>>>>>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>>>
>>>>>>>> U-Boot is compiled for a single board, which in turn uses a specific
>>>>>>>> SoC.
>>>>>>>> There's no need to make runtime decisions based on SoC ID. While
>>>>>>>> there's
>>>>>>>> certainly an argument for making the code support different SoCs at
>>>>>>>> run-time, the Tegra code is so far from that possible ideal that the
>>>>>>>> existing runtime code is an anomaly. If this changes in the future,
>>>>>>>> all
>>>>>>>> runtime decisions should likely be based on DT anyway.
>>>>>>>>
>>>>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>>>>> ---
>>>>>>>>     arch/arm/mach-tegra/ap.c               | 106
>>>>>>>> ++++++++++-----------------------
>>>>>>>>     arch/arm/mach-tegra/cache.c            |  20 +++----
>>>>>>>>     arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>>>>>>     arch/arm/mach-tegra/cpu.h              |   6 --
>>>>>>>>     arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>>>>>>     5 files changed, 51 insertions(+), 117 deletions(-)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> What exactly is missing to prevent multi-arch support?
>>>>>>
>>>>>>
>>>>>> In a word: everything:-)
>>>>>>
>>>>>> Pretty much all decisions in core architecture code, core Tegra code,
>>>>>> drivers, and even board files are currently made at compile time. For
>>>>>> example, consider drivers where the register layouts are different
>>>>>> between
>>>>>> different SoCs; not just new fields added, but existing fields moved to
>>>>>> different offsets. Right now, we handle this by changing the register
>>>>>> struct
>>>>>> definition at compile time. To support multiple chips, we'd have to
>>>>>> either
>>>>>> (a) link in n copies of the driver, one per register layout, or (b)
>>>>>> rework
>>>>>> the driver to use #defines and runtime calculations for register
>>>>>> offsets,
>>>>>> like the Linux kernel drivers do. Tegra USB is one example. The pinmux
>>>>>> and
>>>>>> clock drivers have a significantly different sets of
>>>>>> pins/clocks/resets/...
>>>>>> per SoC, and enums/tables describing those sets are currently
>>>>>> configured at
>>>>>> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are configured
>>>>>> at
>>>>>> compile-time, and even differ per board.
>>>>>
>>>>>
>>>>> I wonder how far we would get by converting clock, pinctrl, reset to
>>>>> driver model drivers?
>>>>
>>>>
>>>> Well, I expect we'll find out soon. The next SoC has radically different
>>>> clock/reset mechanisms, so we'll need to switch to standardized APIs for
>>>> clock/reset on Tegra to isolate drivers from those differences, and I
>>>> imagine that conversion would also involve conversion to DM since any
>>>> standard APIs probably assume use of DM. I haven't investigated this in
>>>> detail yet though.
>>>
>>>
>>> That sounds like a good move.
>>
>>
>> I'm not sure if you still object to this patch for now, or would be happy
>> giving it an ack?

And just to be clear, I'm always keen to move things forward and I can
see you have put a lot of work into this series. It would be easier to
just apply it as is. What I am looking for is how we might get closer
to the goal, perhaps after this series. This series has exposed this
which is why I have brought it up.

>
> Sorry, I still feel this is going in the wrong
> direction...CONFIG_TEGRA124 should mean that the code supports it,
> rather than the code exclusively supports it.
>
> In your commit message you say:
>
> "While there's
> certainly an argument for making the code support different SoCs at
> run-time, the Tegra code is so far from that possible ideal that the
> existing runtime code is an anomaly. If this changes in the future, all
> runtime decisions should likely be based on DT anyway."
>
> Or even build time.... That statement  seems like saying that
> everything is so terrible that we might as well give up.
>
> What's your plan to move code into drivers? I am happy to help move
> things over and get towards the goal rather than further away. But
> really that should happen first.
>
> Also, the model that seems to be emerging is that SPL detects the
> platform and passes the correct DT to U-Boot proper.
>
> Specifically I think the end state should be:
> - Most SoC code is in drivers using driver model
> - It is possible to build most of the tegra code without building each
> SoC (just by having a 'tegra' board which enables all drivers)
> - If someone wanted to support multiple SoCs it would not be
> impossible to do so (even if mainline doesn't make it)
> - New SoCs are supported mostly by adding new drivers (although there
> is always of course some core/start-up code)
>
> Do you agree with that?
>
> Regards,
> Simon

Regards,
Simon
Stephen Warren April 29, 2016, 7:21 p.m. UTC | #9
On 04/29/2016 11:42 AM, Simon Glass wrote:
> Hi Stephen,
>
> On 29 April 2016 at 10:53, Simon Glass <sjg@chromium.org> wrote:
>> Hi Stephen,
>>
>> On 29 April 2016 at 10:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 04/29/2016 08:02 AM, Simon Glass wrote:
>>>>
>>>> Hi Stephen,
>>>>
>>>> On 27 April 2016 at 10:13, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>
>>>>> On 04/27/2016 08:50 AM, Simon Glass wrote:
>>>>>>
>>>>>>
>>>>>> Hi Stephen,
>>>>>>
>>>>>> On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi Stephen,
>>>>>>>>
>>>>>>>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>>>>
>>>>>>>>> U-Boot is compiled for a single board, which in turn uses a specific
>>>>>>>>> SoC.
>>>>>>>>> There's no need to make runtime decisions based on SoC ID. While
>>>>>>>>> there's
>>>>>>>>> certainly an argument for making the code support different SoCs at
>>>>>>>>> run-time, the Tegra code is so far from that possible ideal that the
>>>>>>>>> existing runtime code is an anomaly. If this changes in the future,
>>>>>>>>> all
>>>>>>>>> runtime decisions should likely be based on DT anyway.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>>>>>> ---
>>>>>>>>>      arch/arm/mach-tegra/ap.c               | 106
>>>>>>>>> ++++++++++-----------------------
>>>>>>>>>      arch/arm/mach-tegra/cache.c            |  20 +++----
>>>>>>>>>      arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>>>>>>>      arch/arm/mach-tegra/cpu.h              |   6 --
>>>>>>>>>      arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>>>>>>>      5 files changed, 51 insertions(+), 117 deletions(-)
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> What exactly is missing to prevent multi-arch support?
>>>>>>>
>>>>>>>
>>>>>>> In a word: everything:-)
>>>>>>>
>>>>>>> Pretty much all decisions in core architecture code, core Tegra code,
>>>>>>> drivers, and even board files are currently made at compile time. For
>>>>>>> example, consider drivers where the register layouts are different
>>>>>>> between
>>>>>>> different SoCs; not just new fields added, but existing fields moved to
>>>>>>> different offsets. Right now, we handle this by changing the register
>>>>>>> struct
>>>>>>> definition at compile time. To support multiple chips, we'd have to
>>>>>>> either
>>>>>>> (a) link in n copies of the driver, one per register layout, or (b)
>>>>>>> rework
>>>>>>> the driver to use #defines and runtime calculations for register
>>>>>>> offsets,
>>>>>>> like the Linux kernel drivers do. Tegra USB is one example. The pinmux
>>>>>>> and
>>>>>>> clock drivers have a significantly different sets of
>>>>>>> pins/clocks/resets/...
>>>>>>> per SoC, and enums/tables describing those sets are currently
>>>>>>> configured at
>>>>>>> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are configured
>>>>>>> at
>>>>>>> compile-time, and even differ per board.
>>>>>>
>>>>>>
>>>>>> I wonder how far we would get by converting clock, pinctrl, reset to
>>>>>> driver model drivers?
>>>>>
>>>>>
>>>>> Well, I expect we'll find out soon. The next SoC has radically different
>>>>> clock/reset mechanisms, so we'll need to switch to standardized APIs for
>>>>> clock/reset on Tegra to isolate drivers from those differences, and I
>>>>> imagine that conversion would also involve conversion to DM since any
>>>>> standard APIs probably assume use of DM. I haven't investigated this in
>>>>> detail yet though.
>>>>
>>>>
>>>> That sounds like a good move.
>>>
>>> I'm not sure if you still object to this patch for now, or would be happy
>>> giving it an ack?
>
> And just to be clear, I'm always keen to move things forward and I can
> see you have put a lot of work into this series. It would be easier to
> just apply it as is. What I am looking for is how we might get closer
> to the goal, perhaps after this series. This series has exposed this
> which is why I have brought it up.

So, just to be clear: TomW can apply this (once I post V2) even if 
you're not giving an ack?

>> Sorry, I still feel this is going in the wrong
>> direction...CONFIG_TEGRA124 should mean that the code supports it,
>> rather than the code exclusively supports it.

That's certainly not what it means right now, and my intention in this 
series was not to address any short-comings in the current meanings of 
Kconfig.

No matter what, if we do drive all this core SoC code from DT 
eventually, I don't imagine tegra_get_chip() will be the way code gets 
dispatched between multiple chips in the future, so removing it now 
shouldn't hurt any later conversion to runtime multi-chip support.

In practice in a DT-driven world, I'd expect:

- The code in enable_scu() to be part of some Tegra20-specific "SoC 
driver" or similar, and hence not need any runtime support restored.

- The code in cache.c to be part of some specific cache drivers, which 
would only be instantiated on Tegra20, and hence not need any runtime 
support restored.

- The code in cpu.c to be moved into a clock driver, and base on some 
per-SoC table in the clock driver, and hence not need any runtime 
special-casing.

As such, I don't see reverting any of this patch being reverted later, 
and I don't believe leaving in these runtime calls would make it any 
easier to refactor the code into drivers later.

>> In your commit message you say:
>>
>> "While there's
>> certainly an argument for making the code support different SoCs at
>> run-time, the Tegra code is so far from that possible ideal that the
>> existing runtime code is an anomaly. If this changes in the future, all
>> runtime decisions should likely be based on DT anyway."
>>
>> Or even build time.... That statement  seems like saying that
>> everything is so terrible that we might as well give up.

I'm just being practical. Please note in particular the comment about 
basing such decisions on DT; that and refactoring the code into 
DT-instantiated drivers would leave it so different that the tiny number 
of current runtime switches doesn't help anything.

>> What's your plan to move code into drivers? I am happy to help move
>> things over and get towards the goal rather than further away. But
>> really that should happen first.

I don't have a plan for anything besides the clock and reset drivers at 
the moment. I /think/ that most of the rest of the code in 
arch/arm/mach-tegra simply won't be needed on Tegra186. We'll see; I 
only have UART and GPIO working right now, well and a very hacked-up MMC 
to avoid clock/reset access. There is a large amount of work left that I 
haven't started looking at yet.

>> Also, the model that seems to be emerging is that SPL detects the
>> platform and passes the correct DT to U-Boot proper.

There is no SPL on Tegra210 or later. It would be a pity to have to 
introduce one just to do runtime DT selection when there's no need to 
have runtime DT selection.

>> Specifically I think the end state should be:
>> - Most SoC code is in drivers using driver model

That is fine in many cases. There's plenty of low-level bootstrap code 
where I'm not sure that it's worth it. Equally, given that you have 
stated DM==DT, I worry about the implications of that statement if 
universally applied, rather than selectively/pragmatically applied.

>> - It is possible to build most of the tegra code without building each
>> SoC (just by having a 'tegra' board which enables all drivers)

I'm not convinced this is worth it universally.

For the purposes of actually running a binary on a device, I believe 
there is zero need for this.

For compile coverage it might be nice, especially for driver code, 
although running buildman on one Tegra board for each SoC generation 
doesn't take much time.

Even for drivers that solely use generic (non-SoC-version-specific) 
APIs, this would be difficult in some cases. This plays back into my 
earlier comments elsewhere about structs-vs-defines for register address 
calculations. Register layouts of some devices vary incompatibly between 
Tegra SoC generations. With a define-based driver, this can all be 
handled at run-time. With a struct-based driver, one must compile the 
code once per register layout. Rather than invest in making a "compile 
test" build that does this, which would require various build system 
work, it's much simpler to just compile the driver multiple times as 
part of a set of board builds, which already works today. The result is 
still compiling the code n times, so there wouldn't be much time saving 
wrapping everything into one build.

>> - If someone wanted to support multiple SoCs it would not be
>> impossible to do so (even if mainline doesn't make it)

I don't think it's a good idea to support features that mainline doesn't 
use. They'll bit-rot and not work anyway. I also can't see any use-case 
for such a build.

>> - New SoCs are supported mostly by adding new drivers (although there
>> is always of course some core/start-up code)

Yes, it certainly makes sense to use drivers for functionality which 
other pieces of the code must interact with in a generic way. For 
example, calls from I2C/MMC drivers to clock/reset APIs.

I expect some debate over what code is core/start-up code though. For 
example, static pinmux setup fits that category for me, since there's no 
generic code that needs to interface with it.
Simon Glass May 1, 2016, 7:16 p.m. UTC | #10
Hi Stephen,

On 29 April 2016 at 13:21, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 04/29/2016 11:42 AM, Simon Glass wrote:
>>
>> Hi Stephen,
>>
>> On 29 April 2016 at 10:53, Simon Glass <sjg@chromium.org> wrote:
>>>
>>> Hi Stephen,
>>>
>>> On 29 April 2016 at 10:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>>
>>>> On 04/29/2016 08:02 AM, Simon Glass wrote:
>>>>>
>>>>>
>>>>> Hi Stephen,
>>>>>
>>>>> On 27 April 2016 at 10:13, Stephen Warren <swarren@wwwdotorg.org>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> On 04/27/2016 08:50 AM, Simon Glass wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Hi Stephen,
>>>>>>>
>>>>>>> On 25 April 2016 at 13:25, Stephen Warren <swarren@wwwdotorg.org>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 04/23/2016 11:14 AM, Simon Glass wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Hi Stephen,
>>>>>>>>>
>>>>>>>>> On 19 April 2016 at 14:59, Stephen Warren <swarren@wwwdotorg.org>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>>>>>
>>>>>>>>>> U-Boot is compiled for a single board, which in turn uses a
>>>>>>>>>> specific
>>>>>>>>>> SoC.
>>>>>>>>>> There's no need to make runtime decisions based on SoC ID. While
>>>>>>>>>> there's
>>>>>>>>>> certainly an argument for making the code support different SoCs
>>>>>>>>>> at
>>>>>>>>>> run-time, the Tegra code is so far from that possible ideal that
>>>>>>>>>> the
>>>>>>>>>> existing runtime code is an anomaly. If this changes in the
>>>>>>>>>> future,
>>>>>>>>>> all
>>>>>>>>>> runtime decisions should likely be based on DT anyway.
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>>>>>>> ---
>>>>>>>>>>      arch/arm/mach-tegra/ap.c               | 106
>>>>>>>>>> ++++++++++-----------------------
>>>>>>>>>>      arch/arm/mach-tegra/cache.c            |  20 +++----
>>>>>>>>>>      arch/arm/mach-tegra/cpu.c              |  16 ++---
>>>>>>>>>>      arch/arm/mach-tegra/cpu.h              |   6 --
>>>>>>>>>>      arch/arm/mach-tegra/tegra20/warmboot.c |  20 ++-----
>>>>>>>>>>      5 files changed, 51 insertions(+), 117 deletions(-)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> What exactly is missing to prevent multi-arch support?
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> In a word: everything:-)
>>>>>>>>
>>>>>>>> Pretty much all decisions in core architecture code, core Tegra
>>>>>>>> code,
>>>>>>>> drivers, and even board files are currently made at compile time.
>>>>>>>> For
>>>>>>>> example, consider drivers where the register layouts are different
>>>>>>>> between
>>>>>>>> different SoCs; not just new fields added, but existing fields moved
>>>>>>>> to
>>>>>>>> different offsets. Right now, we handle this by changing the
>>>>>>>> register
>>>>>>>> struct
>>>>>>>> definition at compile time. To support multiple chips, we'd have to
>>>>>>>> either
>>>>>>>> (a) link in n copies of the driver, one per register layout, or (b)
>>>>>>>> rework
>>>>>>>> the driver to use #defines and runtime calculations for register
>>>>>>>> offsets,
>>>>>>>> like the Linux kernel drivers do. Tegra USB is one example. The
>>>>>>>> pinmux
>>>>>>>> and
>>>>>>>> clock drivers have a significantly different sets of
>>>>>>>> pins/clocks/resets/...
>>>>>>>> per SoC, and enums/tables describing those sets are currently
>>>>>>>> configured at
>>>>>>>> compile time. Some PMIC constants (e.g. vdd_cpu voltage) are
>>>>>>>> configured
>>>>>>>> at
>>>>>>>> compile-time, and even differ per board.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I wonder how far we would get by converting clock, pinctrl, reset to
>>>>>>> driver model drivers?
>>>>>>
>>>>>>
>>>>>>
>>>>>> Well, I expect we'll find out soon. The next SoC has radically
>>>>>> different
>>>>>> clock/reset mechanisms, so we'll need to switch to standardized APIs
>>>>>> for
>>>>>> clock/reset on Tegra to isolate drivers from those differences, and I
>>>>>> imagine that conversion would also involve conversion to DM since any
>>>>>> standard APIs probably assume use of DM. I haven't investigated this
>>>>>> in
>>>>>> detail yet though.
>>>>>
>>>>>
>>>>>
>>>>> That sounds like a good move.
>>>>
>>>>
>>>> I'm not sure if you still object to this patch for now, or would be
>>>> happy
>>>> giving it an ack?
>>
>>
>> And just to be clear, I'm always keen to move things forward and I can
>> see you have put a lot of work into this series. It would be easier to
>> just apply it as is. What I am looking for is how we might get closer
>> to the goal, perhaps after this series. This series has exposed this
>> which is why I have brought it up.
>
>
> So, just to be clear: TomW can apply this (once I post V2) even if you're
> not giving an ack?

Provided you are OK with using drivers for clock, pinctrl etc. with
your new Tegra work. I'd really like to move away from all this code
in arch/arm, private APIs, etc..

>
>>> Sorry, I still feel this is going in the wrong
>>> direction...CONFIG_TEGRA124 should mean that the code supports it,
>>> rather than the code exclusively supports it.
>
>
> That's certainly not what it means right now, and my intention in this
> series was not to address any short-comings in the current meanings of

> Kconfig.

Well it means that in quite a few places - e.g. this one that you are removing.

>
> No matter what, if we do drive all this core SoC code from DT eventually, I
> don't imagine tegra_get_chip() will be the way code gets dispatched between
> multiple chips in the future, so removing it now shouldn't hurt any later
> conversion to runtime multi-chip support.
>
> In practice in a DT-driven world, I'd expect:
>
> - The code in enable_scu() to be part of some Tegra20-specific "SoC driver"
> or similar, and hence not need any runtime support restored.
>
> - The code in cache.c to be part of some specific cache drivers, which would
> only be instantiated on Tegra20, and hence not need any runtime support
> restored.
>
> - The code in cpu.c to be moved into a clock driver, and base on some
> per-SoC table in the clock driver, and hence not need any runtime
> special-casing.
>
> As such, I don't see reverting any of this patch being reverted later, and I
> don't believe leaving in these runtime calls would make it any easier to
> refactor the code into drivers later.

Sounds reasonable. So long as we are agreed on using drivers then I am
OK with it as a means to an end.

>
>>> In your commit message you say:
>>>
>>> "While there's
>>> certainly an argument for making the code support different SoCs at
>>> run-time, the Tegra code is so far from that possible ideal that the
>>> existing runtime code is an anomaly. If this changes in the future, all
>>> runtime decisions should likely be based on DT anyway."
>>>
>>> Or even build time.... That statement  seems like saying that
>>> everything is so terrible that we might as well give up.
>
>
> I'm just being practical. Please note in particular the comment about basing
> such decisions on DT; that and refactoring the code into DT-instantiated
> drivers would leave it so different that the tiny number of current runtime
> switches doesn't help anything.

Right, but you are actually removing functions that detect the SoC.
That is surely heading the wrong way.

>
>>> What's your plan to move code into drivers? I am happy to help move
>>> things over and get towards the goal rather than further away. But
>>> really that should happen first.
>
>
> I don't have a plan for anything besides the clock and reset drivers at the
> moment. I /think/ that most of the rest of the code in arch/arm/mach-tegra
> simply won't be needed on Tegra186. We'll see; I only have UART and GPIO
> working right now, well and a very hacked-up MMC to avoid clock/reset
> access. There is a large amount of work left that I haven't started looking
> at yet.

OK good.

>
>>> Also, the model that seems to be emerging is that SPL detects the
>>> platform and passes the correct DT to U-Boot proper.
>
>
> There is no SPL on Tegra210 or later. It would be a pity to have to
> introduce one just to do runtime DT selection when there's no need to have
> runtime DT selection.

How does the platform start up? Does it use BCT and then jump straight
into U-Boot?

>
>>> Specifically I think the end state should be:
>>> - Most SoC code is in drivers using driver model
>
>
> That is fine in many cases. There's plenty of low-level bootstrap code where
> I'm not sure that it's worth it. Equally, given that you have stated DM==DT,
> I worry about the implications of that statement if universally applied,
> rather than selectively/pragmatically applied.

I have not stated that DM==DT. Where there are reasons to use platform
data we can do that. See this comment in the driver-model README:

*** Note: platform data is the old way of doing things. It is
*** basically a C structure which is passed to drivers to tell them about
*** platform-specific settings like the address of its registers, bus
*** speed, etc. Device tree is now the preferred way of handling this.
*** Unless you have a good reason not to use device tree (the main one
*** being you need serial support in SPL and don't have enough SRAM for
*** the cut-down device tree and libfdt libraries) you should stay away
*** from platform data.

This is a boot loader. We need to be pragmatic. This is why I push
back on core driver-model code bloat.

>
>>> - It is possible to build most of the tegra code without building each
>>> SoC (just by having a 'tegra' board which enables all drivers)
>
>
> I'm not convinced this is worth it universally.
>
> For the purposes of actually running a binary on a device, I believe there
> is zero need for this.
>
> For compile coverage it might be nice, especially for driver code, although
> running buildman on one Tegra board for each SoC generation doesn't take
> much time.
>
> Even for drivers that solely use generic (non-SoC-version-specific) APIs,
> this would be difficult in some cases. This plays back into my earlier
> comments elsewhere about structs-vs-defines for register address
> calculations. Register layouts of some devices vary incompatibly between
> Tegra SoC generations. With a define-based driver, this can all be handled
> at run-time. With a struct-based driver, one must compile the code once per
> register layout. Rather than invest in making a "compile test" build that
> does this, which would require various build system work, it's much simpler
> to just compile the driver multiple times as part of a set of board builds,
> which already works today. The result is still compiling the code n times,
> so there wouldn't be much time saving wrapping everything into one build.

Well your hardware guys really should make up their mind. Is there any
code review? And s/w people should have a system (with serial driver)
running before tape-out and catch this stuff.

But in any case, struct-based stuff is not a requirement now. I
believe a lot of people prefer it (including me) but in the case you
raise it isn't practical. See ns16550 for how this can be done badly.

>
>>> - If someone wanted to support multiple SoCs it would not be
>>> impossible to do so (even if mainline doesn't make it)
>
>
> I don't think it's a good idea to support features that mainline doesn't
> use. They'll bit-rot and not work anyway. I also can't see any use-case for
> such a build.

While SoC vendors think of the SoC as a the most important factor in
the platform, we are starting to see similar devices using different
SoCs, or at least different variants. From a user point of view I'd
rather not worry about which Raspberry Pi I have, for example, so long
as I can build something that boots.

>
>>> - New SoCs are supported mostly by adding new drivers (although there
>>> is always of course some core/start-up code)
>
>
> Yes, it certainly makes sense to use drivers for functionality which other
> pieces of the code must interact with in a generic way. For example, calls
> from I2C/MMC drivers to clock/reset APIs.
>
> I expect some debate over what code is core/start-up code though. For
> example, static pinmux setup fits that category for me, since there's no
> generic code that needs to interface with it.

So please put your pinmux code in a pinctrl driver, even it is just in
the probe() method.

Also I have a Tegra124 platform now. Once the smoke has cleared with
your work I'd like to take a look at how to improve things.

Regards,
Simon
diff mbox

Patch

diff --git a/arch/arm/mach-tegra/ap.c b/arch/arm/mach-tegra/ap.c
index a200010e2937..a8e3e8b7dfcb 100644
--- a/arch/arm/mach-tegra/ap.c
+++ b/arch/arm/mach-tegra/ap.c
@@ -10,7 +10,6 @@ 
 #include <common.h>
 #include <linux/bug.h>
 #include <asm/io.h>
-#include <asm/arch/gp_padctrl.h>
 #include <asm/arch-tegra/clock.h>
 #include <asm/arch-tegra/tegra.h>
 #include <soc/mc.h>
@@ -19,23 +18,6 @@ 
 #include "pmc.h"
 #include "scu.h"
 
-int tegra_get_chip(void)
-{
-	int rev;
-	struct apb_misc_gp_ctlr *gp =
-		(struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
-
-	/*
-	 * This is undocumented, Chip ID is bits 15:8 of the register
-	 * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for
-	 * Tegra30, 0x35 for T114, and 0x40 for Tegra124.
-	 */
-	rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
-	debug("%s: CHIPID is 0x%02X\n", __func__, rev);
-
-	return rev;
-}
-
 int tegra_get_sku_info(void)
 {
 	int sku_id;
@@ -49,74 +31,47 @@  int tegra_get_sku_info(void)
 
 int tegra_get_chip_sku(void)
 {
-	uint sku_id, chip_id;
+#ifdef CONFIG_TEGRA20
+	uint sku_id;
 
-	chip_id = tegra_get_chip();
 	sku_id = tegra_get_sku_info();
-
-	switch (chip_id) {
-	case CHIPID_TEGRA20:
-		switch (sku_id) {
-		case SKU_ID_T20_7:
-		case SKU_ID_T20:
-			return TEGRA_SOC_T20;
-		case SKU_ID_T25SE:
-		case SKU_ID_AP25:
-		case SKU_ID_T25:
-		case SKU_ID_AP25E:
-		case SKU_ID_T25E:
-			return TEGRA_SOC_T25;
-		}
-		break;
-	case CHIPID_TEGRA30:
-		switch (sku_id) {
-		case SKU_ID_T33:
-		case SKU_ID_T30:
-		case SKU_ID_TM30MQS_P_A3:
-		default:
-			return TEGRA_SOC_T30;
-		}
-		break;
-	case CHIPID_TEGRA114:
-		switch (sku_id) {
-		case SKU_ID_T114_ENG:
-		case SKU_ID_T114_1:
-		default:
-			return TEGRA_SOC_T114;
-		}
-		break;
-	case CHIPID_TEGRA124:
-		switch (sku_id) {
-		case SKU_ID_T124_ENG:
-		default:
-			return TEGRA_SOC_T124;
-		}
-		break;
-	case CHIPID_TEGRA210:
-		switch (sku_id) {
-		case SKU_ID_T210_ENG:
-		default:
-			return TEGRA_SOC_T210;
-		}
-		break;
+	switch (sku_id) {
+	case SKU_ID_T20_7:
+	case SKU_ID_T20:
+		return TEGRA_SOC_T20;
+	case SKU_ID_T25SE:
+	case SKU_ID_AP25:
+	case SKU_ID_T25:
+	case SKU_ID_AP25E:
+	case SKU_ID_T25E:
+		return TEGRA_SOC_T25;
+	default:
+		/* unknown chip/sku id */
+		printf("ERROR: UNKNOWN SKU ID 0x%02X\n", sku_id);
+		return TEGRA_SOC_UNKNOWN;
 	}
-
-	/* unknown chip/sku id */
-	printf("%s: ERROR: UNKNOWN CHIP/SKU ID COMBO (0x%02X/0x%02X)\n",
-		__func__, chip_id, sku_id);
-	return TEGRA_SOC_UNKNOWN;
+#endif
+#ifdef CONFIG_TEGRA30
+	return TEGRA_SOC_T30;
+#endif
+#ifdef CONFIG_TEGRA114
+	return TEGRA_SOC_T114;
+#endif
+#ifdef CONFIG_TEGRA124
+	return TEGRA_SOC_T124;
+#endif
+#ifdef CONFIG_TEGRA210
+	return TEGRA_SOC_T210;
+#endif
 }
 
 #ifndef CONFIG_ARM64
 static void enable_scu(void)
 {
+#ifdef CONFIG_TEGRA20
 	struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE;
 	u32 reg;
 
-	/* Only enable the SCU on T20/T25 */
-	if (tegra_get_chip() != CHIPID_TEGRA20)
-		return;
-
 	/* If SCU already setup/enabled, return */
 	if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE)
 		return;
@@ -128,6 +83,7 @@  static void enable_scu(void)
 	reg = readl(&scu->scu_ctrl);
 	reg |= SCU_CTRL_ENABLE;
 	writel(reg, &scu->scu_ctrl);
+#endif
 }
 
 static u32 get_odmdata(void)
diff --git a/arch/arm/mach-tegra/cache.c b/arch/arm/mach-tegra/cache.c
index b93814fcb96b..a41a7b9e2868 100644
--- a/arch/arm/mach-tegra/cache.c
+++ b/arch/arm/mach-tegra/cache.c
@@ -8,31 +8,29 @@ 
 
 #include <common.h>
 #include <asm/io.h>
-#include <asm/arch/gp_padctrl.h>
 #include "cpu.h"
 
 #ifndef CONFIG_ARM64
 void config_cache(void)
 {
-	u32 reg = 0;
-
 	/* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */
 	asm volatile(
 		"mrc p15, 0, r0, c1, c0, 1\n"
 		"orr r0, r0, #0x41\n"
 		"mcr p15, 0, r0, c1, c0, 1\n");
 
-	/* Currently, only Tegra114+ needs this L2 cache change to boot Linux */
-	if (tegra_get_chip() < CHIPID_TEGRA114)
-		return;
-
+#if defined(CONFIG_TEGRA114) || defined(CONFIG_TEGRA124)
 	/*
 	 * Systems with an architectural L2 cache must not use the PL310.
 	 * Config L2CTLR here for a data RAM latency of 3 cycles.
 	 */
-	asm("mrc p15, 1, %0, c9, c0, 2" : : "r" (reg));
-	reg &= ~7;
-	reg |= 2;
-	asm("mcr p15, 1, %0, c9, c0, 2" : : "r" (reg));
+	{
+		u32 reg;
+		asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (reg));
+		reg &= ~7;
+		reg |= 2;
+		asm("mcr p15, 1, %0, c9, c0, 2" : : "r" (reg));
+	}
+#endif
 }
 #endif
diff --git a/arch/arm/mach-tegra/cpu.c b/arch/arm/mach-tegra/cpu.c
index 3562a2d2188a..cc60908677a1 100644
--- a/arch/arm/mach-tegra/cpu.c
+++ b/arch/arm/mach-tegra/cpu.c
@@ -172,7 +172,6 @@  int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
 		u32 divp, u32 cpcon)
 {
 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU];
-	int chip = tegra_get_chip();
 	u32 reg;
 	debug("%s entry\n", __func__);
 
@@ -189,11 +188,12 @@  int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
 	reg |= (divn << pllinfo->n_shift) | (divp << pllinfo->p_shift);
 	writel(reg, &pll->pll_base);
 
+	reg = 0;
+
+#if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30)
 	/* Set cpcon to PLLX_MISC */
-	if (chip == CHIPID_TEGRA20 || chip == CHIPID_TEGRA30)
-		reg = (cpcon << pllinfo->kcp_shift);
-	else
-		reg = 0;
+	reg |= (cpcon << pllinfo->kcp_shift);
+#endif
 
 	/*
 	 * TODO(twarren@nvidia.com) Check which SoCs use DCCON
@@ -230,15 +230,11 @@  void init_pllx(void)
 {
 	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
 	struct clk_pll_simple *pll = &clkrst->crc_pll_simple[SIMPLE_PLLX];
-	int soc_type, sku_info, chip_sku;
+	int sku_info, chip_sku;
 	enum clock_osc_freq osc;
 	struct clk_pll_table *sel;
 	debug("%s entry\n", __func__);
 
-	/* get SOC (chip) type */
-	soc_type = tegra_get_chip();
-	debug("%s: SoC = 0x%02X\n", __func__, soc_type);
-
 	/* get SKU info */
 	sku_info = tegra_get_sku_info();
 	debug("%s: SKU info byte = 0x%02X\n", __func__, sku_info);
diff --git a/arch/arm/mach-tegra/cpu.h b/arch/arm/mach-tegra/cpu.h
index f1f5b179c198..ee4f7868baf7 100644
--- a/arch/arm/mach-tegra/cpu.h
+++ b/arch/arm/mach-tegra/cpu.h
@@ -64,12 +64,6 @@  void powerup_cpu(void);
 void reset_A9_cpu(int reset);
 void start_cpu(u32 reset_vector);
 /**
- * Returns the pure SOC (chip ID) from the HIDREV register
- *
- * @return	SOC ID - see CHIPID_TEGRAxx...
- */
-int tegra_get_chip(void);
-/**
  * Returns the SKU ID from the sku_info register
  *
  * @return	SKU ID - see SKU_ID_Txx...
diff --git a/arch/arm/mach-tegra/tegra20/warmboot.c b/arch/arm/mach-tegra/tegra20/warmboot.c
index 9d67bdef494a..1159f05a5dc3 100644
--- a/arch/arm/mach-tegra/tegra20/warmboot.c
+++ b/arch/arm/mach-tegra/tegra20/warmboot.c
@@ -242,22 +242,12 @@  static int ap20_is_production_mode(void)
 
 static enum fuse_operating_mode fuse_get_operation_mode(void)
 {
-	u32 chip_id;
-	struct apb_misc_gp_ctlr *gp =
-		(struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
-
-	chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >>
-			HIDREV_CHIPID_SHIFT;
-	if (chip_id == CHIPID_TEGRA20) {
-		if (ap20_is_odm_production_mode()) {
-			printf("!! odm_production_mode is not supported !!\n");
-			return MODE_UNDEFINED;
-		} else
-			if (ap20_is_production_mode())
-				return MODE_PRODUCTION;
-			else
-				return MODE_UNDEFINED;
+	if (ap20_is_odm_production_mode()) {
+		printf("!! odm_production_mode is not supported !!\n");
+		return MODE_UNDEFINED;
 	}
+	if (ap20_is_production_mode())
+		return MODE_PRODUCTION;
 	return MODE_UNDEFINED;
 }