[U-Boot] [PATCH v3 2/2] arm: add initial support for Amlogic Meson and ODROID-C2

Marek Vasut
2016-04-11T00:08:56Z

On 04/10/2016 05:30 PM, Beniamino Galvani wrote:
> This adds platform code for the Amlogic Meson GXBaby (S905) SoC and a
> board definition for ODROID-C2. This initial submission only supports
> UART and Ethernet (through the existing Designware driver). DTS files
> are the ones submitted to Linux arm-soc for 4.7 [1].
>
> [1] https://patchwork.ozlabs.org/patch/603583/
>
> Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>

[...]

> diff --git a/arch/arm/include/asm/arch-meson/gxbb.h b/arch/arm/include/asm/arch-meson/gxbb.h
> new file mode 100644
> index 0000000..cec06d7
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-meson/gxbb.h
> @@ -0,0 +1,77 @@
> +/*
> + * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#ifndef __GXBB_H__
> +#define __GXBB_H__
> +
> +#define GXBB_PERIPHS_BASE 0xc8834400
> +#define GXBB_PERIPHS_ADDR(off) (GXBB_PERIPHS_BASE + ((off) << 2))
> +
> +#define GXBB_GPIO_0_EN GXBB_PERIPHS_ADDR(0x0c)
> +#define GXBB_GPIO_0_OUT GXBB_PERIPHS_ADDR(0x0d)
> +#define GXBB_GPIO_0_IN GXBB_PERIPHS_ADDR(0x0e)

You can also define this as
GXBB_GPIO_EN(n) (0xc + 3 * (n) + 0)
GXBB_GPIO_OUT(n) (0xc + 3 * (n) + 1)
GXBB_GPIO_IN(n) (0xc + 3 * (n) + 2)

> +#define GXBB_GPIO_1_EN GXBB_PERIPHS_ADDR(0x0f)
> +#define GXBB_GPIO_1_OUT GXBB_PERIPHS_ADDR(0x10)
> +#define GXBB_GPIO_1_IN GXBB_PERIPHS_ADDR(0x11)
> +#define GXBB_GPIO_2_EN GXBB_PERIPHS_ADDR(0x12)
> +#define GXBB_GPIO_2_OUT GXBB_PERIPHS_ADDR(0x13)
> +#define GXBB_GPIO_2_IN GXBB_PERIPHS_ADDR(0x14)
> +#define GXBB_GPIO_3_EN GXBB_PERIPHS_ADDR(0x15)
> +#define GXBB_GPIO_3_OUT GXBB_PERIPHS_ADDR(0x16)
> +#define GXBB_GPIO_3_IN GXBB_PERIPHS_ADDR(0x17)
> +#define GXBB_GPIO_4_EN GXBB_PERIPHS_ADDR(0x18)
> +#define GXBB_GPIO_4_OUT GXBB_PERIPHS_ADDR(0x19)
> +#define GXBB_GPIO_4_IN GXBB_PERIPHS_ADDR(0x1a)
> +#define GXBB_GPIO_5_EN GXBB_PERIPHS_ADDR(0x1b)
> +#define GXBB_GPIO_5_OUT GXBB_PERIPHS_ADDR(0x1c)
> +#define GXBB_GPIO_5_IN GXBB_PERIPHS_ADDR(0x1d)
> +#define GXBB_GPIO_6_EN GXBB_PERIPHS_ADDR(0x08)
> +#define GXBB_GPIO_6_OUT GXBB_PERIPHS_ADDR(0x09)
> +#define GXBB_GPIO_6_IN GXBB_PERIPHS_ADDR(0x0a)
> +
> +#define GXBB_PINMUX_0 GXBB_PERIPHS_ADDR(0x2c)

DTTO, #define ... (0x2c + (n)) here

> +#define GXBB_PINMUX_1 GXBB_PERIPHS_ADDR(0x2d)
> +#define GXBB_PINMUX_2 GXBB_PERIPHS_ADDR(0x2e)
> +#define GXBB_PINMUX_3 GXBB_PERIPHS_ADDR(0x2f)
> +#define GXBB_PINMUX_4 GXBB_PERIPHS_ADDR(0x30)
> +#define GXBB_PINMUX_5 GXBB_PERIPHS_ADDR(0x31)
> +#define GXBB_PINMUX_6 GXBB_PERIPHS_ADDR(0x32)
> +#define GXBB_PINMUX_7 GXBB_PERIPHS_ADDR(0x33)
> +#define GXBB_PINMUX_8 GXBB_PERIPHS_ADDR(0x34)
> +#define GXBB_PINMUX_9 GXBB_PERIPHS_ADDR(0x35)
> +#define GXBB_PINMUX_10 GXBB_PERIPHS_ADDR(0x36)
> +#define GXBB_PINMUX_11 GXBB_PERIPHS_ADDR(0x37)
> +#define GXBB_PINMUX_12 GXBB_PERIPHS_ADDR(0x38)
> +
> +#define GXBB_ETH_REG_0 GXBB_PERIPHS_ADDR(0x50)
> +#define GXBB_ETH_REG_1 GXBB_PERIPHS_ADDR(0x51)
> +
> +#define GXBB_ETH_REG_0_PHY_INTF BIT(0)
> +#define GXBB_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5)
> +#define GXBB_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7)
> +#define GXBB_ETH_REG_0_PHY_CLK_EN BIT(10)
> +#define GXBB_ETH_REG_0_CLK_EN BIT(12)
> +
> +#define GXBB_HIU_BASE 0xc883c000

It'd be nice to have base addresses somewhere at the beginning instead
of having them mixed with the bit macros, but that's a matter of taste.

> +#define GXBB_HIU_ADDR(off) (GXBB_HIU_BASE + ((off) << 2))
> +
> +#define GXBB_MEM_PD_REG_0 GXBB_HIU_ADDR(0x40)
> +
> +/* Ethernet memory power domain */
> +#define GXBB_MEM_PD_REG_0_ETH_MASK (BIT(2) | BIT(3))
> +
> +/* Clock gates */
> +#define GXBB_GCLK_MPEG_0 GXBB_HIU_ADDR(0x50)
> +#define GXBB_GCLK_MPEG_1 GXBB_HIU_ADDR(0x51)
> +#define GXBB_GCLK_MPEG_2 GXBB_HIU_ADDR(0x52)
> +#define GXBB_GCLK_MPEG_OTHER GXBB_HIU_ADDR(0x53)
> +#define GXBB_GCLK_MPEG_AO GXBB_HIU_ADDR(0x54)
> +
> +#define GXBB_GCLK_MPEG_1_ETH BIT(3)
> +
> +#define GXBB_ETH_BASE 0xc9410000
> +
> +#endif /* __GXBB_H__ */

[...]

> diff --git a/arch/arm/mach-meson/board.c b/arch/arm/mach-meson/board.c
> new file mode 100644
> index 0000000..1d4d32e
> --- /dev/null
> +++ b/arch/arm/mach-meson/board.c
> @@ -0,0 +1,65 @@
> +/*
> + * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <libfdt.h>
> +#include <linux/err.h>
> +#include <asm/arch/gxbb.h>
> +#include <asm/armv8/mmu.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int dram_init(void)
> +{
> + const fdt32_t *val;
> + int offset;
> + int len;
> +
> + offset = fdt_path_offset(gd->fdt_blob, "/memory");
> + if (offset < 0)
> + return -EINVAL;
> +
> + val = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
> + if (len < sizeof(*val) * 4)
> + return -EINVAL;
> +
> + /* Don't use fdt64_t to avoid unaligned access */

This looks iffy, can you elaborate on this issue ?

> + gd->ram_size = (uint64_t)fdt32_to_cpu(val[2]) << 32;
> + gd->ram_size |= fdt32_to_cpu(val[3]);
> +
> + return 0;
> +}
> +
> +void dram_init_banksize(void)
> +{
> + /* Reserve first 16 MiB of RAM */

Why ?

> + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE + (16 * 1024 * 1024);
> + gd->bd->bi_dram[0].size = gd->ram_size - (16 * 1024 * 1024);
> +}
> +
> +void reset_cpu(ulong addr)
> +{

How does the system reboot then ?

> +}
> +
> +static struct mm_region gxbb_mem_map[] = {
> + {
> + .base = 0x0UL,
> + .size = 0x80000000UL,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> + PTE_BLOCK_INNER_SHARE
> + }, {
> + .base = 0x80000000UL,
> + .size = 0x80000000UL,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_NON_SHARE |
> + PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* List terminator */
> + 0,
> + }
> +};
> +
> +struct mm_region *mem_map = gxbb_mem_map;

This looks super-iffy, I wouldn't be surprised if this started being
optimized away at some point.

[...]

> diff --git a/board/hardkernel/odroid-c2/odroid-c2.c b/board/hardkernel/odroid-c2/odroid-c2.c
> new file mode 100644
> index 0000000..405ccf5
> --- /dev/null
> +++ b/board/hardkernel/odroid-c2/odroid-c2.c
> @@ -0,0 +1,53 @@
> +/*
> + * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/gxbb.h>
> +#include <dm/platdata.h>
> +#include <phy.h>
> +
> +int board_init(void)
> +{
> + return 0;
> +}
> +
> +static const struct eth_pdata gxbb_eth_pdata = {
> + .iobase = GXBB_ETH_BASE,
> + .phy_interface = PHY_INTERFACE_MODE_RGMII,
> +};
> +
> +U_BOOT_DEVICE(meson_eth) = {
> + .name = "eth_designware",
> + .platdata = &gxbb_eth_pdata,
> +};
> +
> +#ifdef CONFIG_MISC_INIT_R
> +int misc_init_r(void)
> +{
> + /* Select Ethernet function */
> + setbits_le32(GXBB_PINMUX_6, 0x3fff);
> +
> + /* Set RGMII mode */
> + setbits_le32(GXBB_ETH_REG_0, GXBB_ETH_REG_0_PHY_INTF |
> + GXBB_ETH_REG_0_TX_PHASE(1) |
> + GXBB_ETH_REG_0_TX_RATIO(4) |
> + GXBB_ETH_REG_0_PHY_CLK_EN |
> + GXBB_ETH_REG_0_CLK_EN);
> +
> + /* Enable power and clock gate */
> + setbits_le32(GXBB_GCLK_MPEG_1, GXBB_GCLK_MPEG_1_ETH);
> + clrbits_le32(GXBB_MEM_PD_REG_0, GXBB_MEM_PD_REG_0_ETH_MASK);
> +
> + /* Reset PHY on GPIOZ_14 */
> + clrbits_le32(GXBB_GPIO_3_EN, BIT(14));
> + clrbits_le32(GXBB_GPIO_3_OUT, BIT(14));
> + udelay(100000);

mdelay(100); , though that is quite some wait.

> + setbits_le32(GXBB_GPIO_3_OUT, BIT(14));
> +
> + return 0;
> +}
> +#endif /* CONFIG_MISC_INIT_R */

[...]

> diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c

This should go in a separate patch.

> new file mode 100644
> index 0000000..140b2d4
> --- /dev/null
> +++ b/drivers/serial/serial_meson.c
> @@ -0,0 +1,162 @@
> +/*
> + * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <fdtdec.h>
> +#include <linux/compiler.h>
> +#include <serial.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct meson_uart {
> + uint32_t wfifo;
> + uint32_t rfifo;
> + uint32_t control;
> + uint32_t status;
> + uint32_t misc;

u32, but you can just use #define FOO for registers.

> +};
> +
> +struct meson_serial_platdata {
> + struct meson_uart *reg;
> +};
> +
> +/* AML_UART_STATUS bits */
> +#define AML_UART_PARITY_ERR BIT(16)
> +#define AML_UART_FRAME_ERR BIT(17)
> +#define AML_UART_TX_FIFO_WERR BIT(18)
> +#define AML_UART_RX_EMPTY BIT(20)
> +#define AML_UART_TX_FULL BIT(21)
> +#define AML_UART_TX_EMPTY BIT(22)
> +#define AML_UART_XMIT_BUSY BIT(25)
> +#define AML_UART_ERR (AML_UART_PARITY_ERR | \
> + AML_UART_FRAME_ERR | \
> + AML_UART_TX_FIFO_WERR)
> +
> +/* AML_UART_CONTROL bits */
> +#define AML_UART_TX_EN BIT(12)
> +#define AML_UART_RX_EN BIT(13)
> +#define AML_UART_TX_RST BIT(22)
> +#define AML_UART_RX_RST BIT(23)
> +#define AML_UART_CLR_ERR BIT(24)

[...]

--
Best regards,
Marek Vasut