[U-Boot] [PATCH 1/7] Tegra30: Add AVP (arm720t) files

Simon Glass sjg at chromium.org
Thu Oct 4 03:11:00 CEST 2012


Hi Stephen,

On Wed, Oct 3, 2012 at 11:23 AM, Stephen Warren <swarren at wwwdotorg.org> wrote:
> On 10/02/2012 04:45 PM, Tom Warren wrote:
>> This provides SPL support for T30 boards - AVP early init, plus
>> CPU (A9) init/jump to main U-Boot.
>
>> diff --git a/arch/arm/cpu/arm720t/tegra30/cpu.c b/arch/arm/cpu/arm720t/tegra30/cpu.c

>> +static int get_chip_type(void)
>> +{
>> +     /*
>> +      * T30 has two options. We will return TEGRA_SOC_T30 until
>> +      * we have the fdt set up when it may change to
>> +      * TEGRA_SOC_T30_408MHZ depending on what we set PLLP to.
>> +      */
>
> I'm not sure what the FDT has to do with it? Certainly at this point in
> the series, I doubt that comment is accurate. Do we actually reprogram
> the PLLs based on FDT later?

Yes, and that changes the SOC here. It's a bit odd but the AVP
couldn't know what speed we wanted so we updated it later when the
Cortex-A9 was running.

>
>> +     if (clock_get_rate(CLOCK_ID_PERIPH) == 408000000)
>> +             return TEGRA_SOC_T30_408MHZ;
>> +     else
>> +             return TEGRA_SOC_T30;
>
> I thought we'd decided not to support one of those options, but perhaps
> it's used somewhere...

Yes, in fact we started using 408MHz exclusively. Not sure if that is
possible upstream - unless anyone knows for sure I suggest we leave it
as is and remove it later if no one needs it.

>
>> +static void adjust_pllp_out_freqs(void)
>> +{
>> +     struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
>> +     struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_PERIPH];
>> +     u32 reg;
>> +
>> +     /* Set T30 PLLP_OUT1, 2, 3 & 4 freqs to 9.6, 48, 102 & 204MHz */
>> +     reg = readl(&pll->pll_out[0]);     /* OUTA, contains OUT2 / OUT1 */
>> +     reg |= (IN_408_OUT_48_DIVISOR << PLLP_OUT2_RATIO) | PLLP_OUT2_OVR
>> +             | (IN_408_OUT_9_6_DIVISOR << PLLP_OUT1_RATIO) | PLLP_OUT1_OVR;
>> +     writel(reg, &pll->pll_out[0]);
>> +
>> +     reg = readl(&pll->pll_out[1]);   /* OUTB, contains OUT4 / OUT3 */
>> +     reg |= (IN_408_OUT_204_DIVISOR << PLLP_OUT4_RATIO) | PLLP_OUT4_OVR
>> +             | (IN_408_OUT_102_DIVISOR << PLLP_OUT3_RATIO) | PLLP_OUT3_OVR;
>> +     writel(reg, &pll->pll_out[1]);
>> +}
>
> I don't think that code is ever used, since init_pllx() below is only
> ever called with slow==1, so never calls it.

This probably came from this function that we had in
arch/arm/cpu/armv7/tegra-common/board.c:

void arch_full_speed(void)
{
	ap20_init_pllx(0);
	debug("CPU at %d\n", clock_get_rate(CLOCK_ID_XCPU));
	debug("Memory at %d\n", clock_get_rate(CLOCK_ID_MEMORY));
	debug("Periph at %d\n", clock_get_rate(CLOCK_ID_PERIPH));
}

It was called from board/nvidia/common/board.

If you like, take a look at the chromeos-v2011.06 branch of U-Boot for
anything about this.

>
>> +void tegra_i2c_ll_write_addr(uint addr, uint config)
>> +{
>> +     struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
>> +
>> +     writel(addr, &reg->cmd_addr0);
>> +     writel(config, &reg->cnfg);
>> +}
>> +
>> +void tegra_i2c_ll_write_data(uint data, uint config)
>> +{
>> +     struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
>> +
>> +     writel(data, &reg->cmd_data1);
>> +     writel(config, &reg->cnfg);
>> +}

Well this is a lot better than the ugliness I had. I don't think you
can put this into the i2c driver since the AVP doesn't have it, right?

>> +
>> +static void enable_cpu_power_rail(void)
>> +{
>> +     struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
>> +     u32 reg;
>> +
>> +     debug("enable_cpu_power_rail entry\n");
>> +     reg = readl(&pmc->pmc_cntrl);
>> +     reg |= CPUPWRREQ_OE;
>> +     writel(reg, &pmc->pmc_cntrl);
>> +
>> +     /*
>> +      * Pulse PWRREQ via I2C.  We need to find out what this is
>> +      * doing, tidy up the code and maybe find a better place for it.
>> +      */
>> +     tegra_i2c_ll_write_addr(0x005a, 0x0002);
>> +     tegra_i2c_ll_write_data(0x2328, 0x0a02);
>
> With a TPS65911x attached to the DVC I2C bus, that sets VDD to 1.4V (I
> assume that's both the VDD1 and VDD2 outputs, but the PMIC datasheet
> isn't too clear on that at a quick glance), and:
>
>> +     udelay(1000);
>> +     tegra_i2c_ll_write_data(0x0127, 0x0a02);
>
> ... and this enables the VDD regulator.
>
> So, this is:
> a) Entirely specific to a TPS65911x regulator. I think this warrants a
> very large FIXME comment.
> b) Nothing to do with pulsing PWRREQ via I2C.
> c) Really should be done via programming the EEPROM on the PMIC so that
> SW doesn't have to do this, but I guess that didn't happen.
>
>> +static void reset_A9_cpu(int reset)
>> +{
>> +     /*
>> +     * NOTE:  Regardless of whether the request is to hold the CPU in reset
>> +     *        or take it out of reset, every processor in the CPU complex
>> +     *        except the master (CPU 0) will be held in reset because the
>> +     *        AVP only talks to the master. The AVP does not know that there
>> +     *        are multiple processors in the CPU complex.
>> +     */
>
> At least the last sentence there is false; this code is running on the
> AVP and there's explicit code above that determines the number of CPUs
> in the main CPU complex (get_num_cpus) and sets separate reset bits for
> each of them (enable_cpu_clock). Oh, and ~7 lines below, there's a loop
> over num_cpus:
>
>> +     int mask = crc_rst_cpu | crc_rst_de | crc_rst_debug;
>> +     int num_cpus = get_num_cpus();
>> +     int cpu;
>> +
>> +     debug("reset_a9_cpu entry\n");
>> +     /* Hold CPUs 1 onwards in reset, and CPU 0 if asked */
>> +     for (cpu = 1; cpu < num_cpus; cpu++)
>> +             reset_cmplx_set_enable(cpu, mask, 1);
>> +     reset_cmplx_set_enable(0, mask, reset);
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

Regards,
Simon


More information about the U-Boot mailing list