[U-Boot] [PATCH 3/6] tegra: Add a function mux feature
Simon Glass
sjg at chromium.org
Mon Nov 28 23:57:31 CET 2011
Hi Stephen,
On Mon, Nov 28, 2011 at 11:42 AM, Stephen Warren <swarren at nvidia.com> wrote:
> On 11/28/2011 12:19 PM, Simon Glass wrote:
>> Hi Stephen,
>>
>> On Mon, Nov 28, 2011 at 10:17 AM, Stephen Warren <swarren at nvidia.com> wrote:
>>> On 11/23/2011 03:59 PM, Simon Glass wrote:
>>>> funcmux permits selection of config options for particular peripherals,
>>>> such as the pins that are used for that peripheral, if there are several
>>>> options.
>>
>> Thanks for looking at this.
>>
>>>>
>>>> Add UART selection to start with.
>>>
>>>> +static void enable_uart(enum periph_id pid)
>>>> +{
>>>> + /* Assert UART reset and enable clock */
>>>> + reset_set_enable(pid, 1);
>>>> + clock_enable(pid);
>>>> + clock_ll_set_source(pid, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
>>>> +
>>>> + /* wait for 2us */
>>>> + udelay(2);
>>>> +
>>>> + /* De-assert reset to UART */
>>>> + reset_set_enable(pid, 0);
>>>> +}
>>>
>>> That doesn't seem like anything to do with function muxing.
>>
>> My thoughts initially were that funcmux_enable_f() might support other
>> devices. Really the correct thing to do is call
>> clock_start_periph_pll() but this can't be used prior to relocation.
>> We are trying to provide a simple function to enable a UART which is
>> why I thought funcmux might be a good place (since its aim is to
>> enable things to make functions work).
>>
>> One option is to move this function into clock.c and call it
>> clock_ll_start_periph_pll() perhaps:
>>
>> void clock_ll_start_periph_pll(enum periph_id periph_id, int source)
>>
>> where source is a plain number (in this case always 0). But it's a bit
>> uglier in that callers must pass 0, otherwise the UART won't work. So
>> I am leaning towards something like:
>>
>> void clock_ll_start_uart(enum periph_id periph_id)
>
> Yes, clock.c and that prototype seem reasonable.
OK, I will update it, I agree it makes more sense particularly as UART
pre-reloc is a special case.
>
> ...
>>>> +{
>>>> + switch (id) {
>>>> + case PERIPH_ID_UART1:
>>>> + pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
>>>> + pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
>>>> + pinmux_tristate_disable(PINGRP_IRRX);
>>>> + pinmux_tristate_disable(PINGRP_IRTX);
>>>> + break;
>>>> +
>>>> + case PERIPH_ID_UART2:
>>>> + pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
>>>> + pinmux_tristate_disable(PINGRP_UAD);
>>>> + break;
>>>> +
>>>> + case PERIPH_ID_UART4:
>>>> + pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
>>>> + pinmux_tristate_disable(PINGRP_GMC);
>>>> + break;
>>>> +
>>>> + default:
>>>> + debug("%s: invalid periph_id %d", __func__, id);
>>>> + break;
>>>> + }
>>>> +}
>>>
>>> I'm not entirely convinced that centralizing this in a function rather
>>> than putting the board-specific muxing into the per-board files is the
>>> right way to go. What's wrong with the kernel's approach of a single
>>> table describing each board's complete pinmux settings? Eventually, all
>>> this will come from DT anyway, won't it?
>>
>> I agree what you seem to be implying (that all Tegra boards will use DT).
>>
>> I would like to reduce code duplication. Yes, when the DT supports
>> pinmux we can call a function to set it up. But even then the code
>> will not be in the board files - only the function call to some sort
>> of pinmux library will be there.
>>
>> At present we have code like this in the boards:
>>
>> /* SDMMC4: config 3, x8 on 2nd set of pins */
>> pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
>> pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
>> pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
>>
>> pinmux_tristate_disable(PINGRP_ATB);
>> pinmux_tristate_disable(PINGRP_GMA);
>> pinmux_tristate_disable(PINGRP_GME);
>>
>> which I want to move into funcmux. The only parameters are the
>> peripheral ID and the function option. When we have pinmux in the DT
>> then these functions can look up the DT to get their info.
>
> The values for "func" can't come from DT; it's a U-Boot specific SW
> concept, not a HW concept. I expect DT will have a table (possibly per
> device or for the whole board; not really clear yet) that for each pin
> group lists function, tristate, pullup/down, ... parameters directly; no
> indirection through a "selected configuration"
Since the DT pinmux operates with individual pins or pin groups, it
means that a function like MMC needs to adjust several pinmux
settings. This means that several DT properties or nodes need to
change depending on the setting that the board uses.
I really don't want to get into this discussion as it is too early.
Let's see how things turn out in the kernel.
>
> So yes you're right these functions should be elided once we switch to
> device tree. I guess this is OK to remove some cut/paste code. I just
> don't want to see the "func" value definitions become some kind of
> long-term concept.
Well arguably it has value (board vendors just select from a number of
SOC-provided options for each function), but I would rather just
follow what the kernel does as you say.
>
>> Also with U-Boot we don't necessarily want to enable everything at
>> start of day in U-Boot. So it may still be required that we init
>> (e.g.) the MMC only when an mmc command is executed.
>
> If the DT pinmux bindings end up being per device, then yes this is
> possible. But really, writing the whole pinmux setup is not many
> register writes, and strictly within a bus within the SoC, so probably
> isn't worth losing any sleep over skipping those that aren't strictly
> necessary for U-boot to operate minimally.
This doesn't quite fit with U-Boot philosophy (init what you need) but
I agree we might get away with it.
>
>> Obviously this needs to be in review. As things change with the kernel
>> we can react. But in any case we want the affected code to be in once
>> place, hence funcmux.
>
> --
> nvpublic
>
Regards,
Simon
More information about the U-Boot
mailing list