uboot/arch/arm/mach-meson/board-g12a.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
   4 * (C) Copyright 2018 Neil Armstrong <narmstrong@baylibre.com>
   5 */
   6
   7#include <common.h>
   8#include <init.h>
   9#include <log.h>
  10#include <net.h>
  11#include <asm/arch/boot.h>
  12#include <asm/arch/eth.h>
  13#include <asm/arch/g12a.h>
  14#include <asm/arch/mem.h>
  15#include <asm/arch/meson-vpu.h>
  16#include <asm/io.h>
  17#include <asm/armv8/mmu.h>
  18#include <linux/sizes.h>
  19#include <usb.h>
  20#include <linux/usb/otg.h>
  21#include <asm/arch/usb.h>
  22#include <usb/dwc2_udc.h>
  23#include <phy.h>
  24#include <clk.h>
  25
  26DECLARE_GLOBAL_DATA_PTR;
  27
  28int meson_get_boot_device(void)
  29{
  30        return readl(G12A_AO_SEC_GP_CFG0) & G12A_AO_BOOT_DEVICE;
  31}
  32
  33/* Configure the reserved memory zones exported by the secure registers
  34 * into EFI and DTB reserved memory entries.
  35 */
  36void meson_init_reserved_memory(void *fdt)
  37{
  38        u64 bl31_size, bl31_start;
  39        u64 bl32_size, bl32_start;
  40        u32 reg;
  41
  42        /*
  43         * Get ARM Trusted Firmware reserved memory zones in :
  44         * - AO_SEC_GP_CFG3: bl32 & bl31 size in KiB, can be 0
  45         * - AO_SEC_GP_CFG5: bl31 physical start address, can be NULL
  46         * - AO_SEC_GP_CFG4: bl32 physical start address, can be NULL
  47         */
  48        reg = readl(G12A_AO_SEC_GP_CFG3);
  49
  50        bl31_size = ((reg & G12A_AO_BL31_RSVMEM_SIZE_MASK)
  51                        >> G12A_AO_BL31_RSVMEM_SIZE_SHIFT) * SZ_1K;
  52        bl32_size = (reg & G12A_AO_BL32_RSVMEM_SIZE_MASK) * SZ_1K;
  53
  54        bl31_start = readl(G12A_AO_SEC_GP_CFG5);
  55        bl32_start = readl(G12A_AO_SEC_GP_CFG4);
  56
  57        /* Add BL31 reserved zone */
  58        if (bl31_start && bl31_size)
  59                meson_board_add_reserved_memory(fdt, bl31_start, bl31_size);
  60
  61        /* Add BL32 reserved zone */
  62        if (bl32_start && bl32_size)
  63                meson_board_add_reserved_memory(fdt, bl32_start, bl32_size);
  64
  65#if defined(CONFIG_VIDEO_MESON)
  66        meson_vpu_rsv_fb(fdt);
  67#endif
  68}
  69
  70phys_size_t get_effective_memsize(void)
  71{
  72        /* Size is reported in MiB, convert it in bytes */
  73        return min(((readl(G12A_AO_SEC_GP_CFG0) & G12A_AO_MEM_SIZE_MASK)
  74                        >> G12A_AO_MEM_SIZE_SHIFT) * SZ_1M, 0xf5000000);
  75}
  76
  77static struct mm_region g12a_mem_map[] = {
  78        {
  79                .virt = 0x0UL,
  80                .phys = 0x0UL,
  81                .size = 0xf5000000UL,
  82                .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
  83                         PTE_BLOCK_INNER_SHARE
  84        }, {
  85                .virt = 0xf5000000UL,
  86                .phys = 0xf5000000UL,
  87                .size = 0x0b000000UL,
  88                .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
  89                         PTE_BLOCK_NON_SHARE |
  90                         PTE_BLOCK_PXN | PTE_BLOCK_UXN
  91        }, {
  92                /* List terminator */
  93                0,
  94        }
  95};
  96
  97struct mm_region *mem_map = g12a_mem_map;
  98
  99static void g12a_enable_external_mdio(void)
 100{
 101        writel(0x0, ETH_PHY_CNTL2);
 102}
 103
 104static void g12a_enable_internal_mdio(void)
 105{
 106        /* Fire up the PHY PLL */
 107        writel(0x29c0040a, ETH_PLL_CNTL0);
 108        writel(0x927e0000, ETH_PLL_CNTL1);
 109        writel(0xac5f49e5, ETH_PLL_CNTL2);
 110        writel(0x00000000, ETH_PLL_CNTL3);
 111        writel(0x00000000, ETH_PLL_CNTL4);
 112        writel(0x20200000, ETH_PLL_CNTL5);
 113        writel(0x0000c002, ETH_PLL_CNTL6);
 114        writel(0x00000023, ETH_PLL_CNTL7);
 115        writel(0x39c0040a, ETH_PLL_CNTL0);
 116        writel(0x19c0040a, ETH_PLL_CNTL0);
 117
 118        /* Select the internal MDIO */
 119        writel(0x33000180, ETH_PHY_CNTL0);
 120        writel(0x00074043, ETH_PHY_CNTL1);
 121        writel(0x00000260, ETH_PHY_CNTL2);
 122}
 123
 124/* Configure the Ethernet MAC with the requested interface mode
 125 * with some optional flags.
 126 */
 127void meson_eth_init(phy_interface_t mode, unsigned int flags)
 128{
 129        switch (mode) {
 130        case PHY_INTERFACE_MODE_RGMII:
 131        case PHY_INTERFACE_MODE_RGMII_ID:
 132        case PHY_INTERFACE_MODE_RGMII_RXID:
 133        case PHY_INTERFACE_MODE_RGMII_TXID:
 134                /* Set RGMII mode */
 135                setbits_le32(G12A_ETH_REG_0, G12A_ETH_REG_0_PHY_INTF_RGMII |
 136                             G12A_ETH_REG_0_TX_PHASE(1) |
 137                             G12A_ETH_REG_0_TX_RATIO(4) |
 138                             G12A_ETH_REG_0_PHY_CLK_EN |
 139                             G12A_ETH_REG_0_CLK_EN);
 140                g12a_enable_external_mdio();
 141                break;
 142
 143        case PHY_INTERFACE_MODE_RMII:
 144                /* Set RMII mode */
 145                out_le32(G12A_ETH_REG_0, G12A_ETH_REG_0_PHY_INTF_RMII |
 146                                        G12A_ETH_REG_0_INVERT_RMII_CLK |
 147                                        G12A_ETH_REG_0_CLK_EN);
 148
 149                /* Use G12A RMII Internal PHY */
 150                if (flags & MESON_USE_INTERNAL_RMII_PHY)
 151                        g12a_enable_internal_mdio();
 152                else
 153                        g12a_enable_external_mdio();
 154
 155                break;
 156
 157        default:
 158                printf("Invalid Ethernet interface mode\n");
 159                return;
 160        }
 161
 162        /* Enable power gate */
 163        clrbits_le32(G12A_MEM_PD_REG_0, G12A_MEM_PD_REG_0_ETH_MASK);
 164}
 165
 166#if CONFIG_IS_ENABLED(USB_DWC3_MESON_G12A) && \
 167        CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
 168static struct dwc2_plat_otg_data meson_g12a_dwc2_data;
 169
 170int board_usb_init(int index, enum usb_init_type init)
 171{
 172        struct fdtdec_phandle_args args;
 173        const void *blob = gd->fdt_blob;
 174        int node, dwc2_node;
 175        struct udevice *dev, *clk_dev;
 176        struct clk clk;
 177        int ret;
 178
 179        /* find the usb glue node */
 180        node = fdt_node_offset_by_compatible(blob, -1,
 181                                             "amlogic,meson-g12a-usb-ctrl");
 182        if (node < 0) {
 183                debug("Not found usb-control node\n");
 184                return -ENODEV;
 185        }
 186
 187        if (!fdtdec_get_is_enabled(blob, node)) {
 188                debug("usb is disabled in the device tree\n");
 189                return -ENODEV;
 190        }
 191
 192        ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
 193        if (ret) {
 194                debug("Not found usb-control device\n");
 195                return ret;
 196        }
 197
 198        /* find the dwc2 node */
 199        dwc2_node = fdt_node_offset_by_compatible(blob, node,
 200                                                  "amlogic,meson-g12a-usb");
 201        if (dwc2_node < 0) {
 202                debug("Not found dwc2 node\n");
 203                return -ENODEV;
 204        }
 205
 206        if (!fdtdec_get_is_enabled(blob, dwc2_node)) {
 207                debug("dwc2 is disabled in the device tree\n");
 208                return -ENODEV;
 209        }
 210
 211        meson_g12a_dwc2_data.regs_otg = fdtdec_get_addr(blob, dwc2_node, "reg");
 212        if (meson_g12a_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
 213                debug("usbotg: can't get base address\n");
 214                return -ENODATA;
 215        }
 216
 217        /* Enable clock */
 218        ret = fdtdec_parse_phandle_with_args(blob, dwc2_node, "clocks",
 219                                             "#clock-cells", 0, 0, &args);
 220        if (ret) {
 221                debug("usbotg has no clocks defined in the device tree\n");
 222                return ret;
 223        }
 224
 225        ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &clk_dev);
 226        if (ret)
 227                return ret;
 228
 229        if (args.args_count != 1) {
 230                debug("Can't find clock ID in the device tree\n");
 231                return -ENODATA;
 232        }
 233
 234        clk.dev = clk_dev;
 235        clk.id = args.args[0];
 236
 237        ret = clk_enable(&clk);
 238        if (ret) {
 239                debug("Failed to enable usbotg clock\n");
 240                return ret;
 241        }
 242
 243        meson_g12a_dwc2_data.rx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
 244                                                     "g-rx-fifo-size", 0);
 245        meson_g12a_dwc2_data.np_tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
 246                                                        "g-np-tx-fifo-size", 0);
 247        meson_g12a_dwc2_data.tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
 248                                                     "g-tx-fifo-size", 0);
 249
 250        /* Switch to peripheral mode */
 251        ret = dwc3_meson_g12a_force_mode(dev, USB_DR_MODE_PERIPHERAL);
 252        if (ret)
 253                return ret;
 254
 255        return dwc2_udc_probe(&meson_g12a_dwc2_data);
 256}
 257
 258int board_usb_cleanup(int index, enum usb_init_type init)
 259{
 260        const void *blob = gd->fdt_blob;
 261        struct udevice *dev;
 262        int node;
 263        int ret;
 264
 265        /* find the usb glue node */
 266        node = fdt_node_offset_by_compatible(blob, -1,
 267                                             "amlogic,meson-g12a-usb-ctrl");
 268        if (node < 0)
 269                return -ENODEV;
 270
 271        if (!fdtdec_get_is_enabled(blob, node))
 272                return -ENODEV;
 273
 274        ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
 275        if (ret)
 276                return ret;
 277
 278        /* Switch to OTG mode */
 279        ret = dwc3_meson_g12a_force_mode(dev, USB_DR_MODE_HOST);
 280        if (ret)
 281                return ret;
 282
 283        return 0;
 284}
 285#endif
 286