mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-mmc
This commit is contained in:
commit
af1b7286d8
14 changed files with 1790 additions and 296 deletions
447
arch/arm/dts/meson-gx.dtsi
Normal file
447
arch/arm/dts/meson-gx.dtsi
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Andreas Färber
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 BayLibre, SAS.
|
||||||
|
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Endless Computers, Inc.
|
||||||
|
* Author: Carlo Caione <carlo@endlessm.com>
|
||||||
|
*
|
||||||
|
* This file is dual-licensed: you can use it either under the terms
|
||||||
|
* of the GPL or the X11 license, at your option. Note that this dual
|
||||||
|
* licensing only applies to this file, and not this project as a
|
||||||
|
* whole.
|
||||||
|
*
|
||||||
|
* a) This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* Or, alternatively,
|
||||||
|
*
|
||||||
|
* b) Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following
|
||||||
|
* conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
interrupt-parent = <&gic>;
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
|
||||||
|
reserved-memory {
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
/* 16 MiB reserved for Hardware ROM Firmware */
|
||||||
|
hwrom_reserved: hwrom@0 {
|
||||||
|
reg = <0x0 0x0 0x0 0x1000000>;
|
||||||
|
no-map;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 2 MiB reserved for ARM Trusted Firmware (BL31) */
|
||||||
|
secmon_reserved: secmon@10000000 {
|
||||||
|
reg = <0x0 0x10000000 0x0 0x200000>;
|
||||||
|
no-map;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cpus {
|
||||||
|
#address-cells = <0x2>;
|
||||||
|
#size-cells = <0x0>;
|
||||||
|
|
||||||
|
cpu0: cpu@0 {
|
||||||
|
device_type = "cpu";
|
||||||
|
compatible = "arm,cortex-a53", "arm,armv8";
|
||||||
|
reg = <0x0 0x0>;
|
||||||
|
enable-method = "psci";
|
||||||
|
next-level-cache = <&l2>;
|
||||||
|
clocks = <&scpi_dvfs 0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu1: cpu@1 {
|
||||||
|
device_type = "cpu";
|
||||||
|
compatible = "arm,cortex-a53", "arm,armv8";
|
||||||
|
reg = <0x0 0x1>;
|
||||||
|
enable-method = "psci";
|
||||||
|
next-level-cache = <&l2>;
|
||||||
|
clocks = <&scpi_dvfs 0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu2: cpu@2 {
|
||||||
|
device_type = "cpu";
|
||||||
|
compatible = "arm,cortex-a53", "arm,armv8";
|
||||||
|
reg = <0x0 0x2>;
|
||||||
|
enable-method = "psci";
|
||||||
|
next-level-cache = <&l2>;
|
||||||
|
clocks = <&scpi_dvfs 0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu3: cpu@3 {
|
||||||
|
device_type = "cpu";
|
||||||
|
compatible = "arm,cortex-a53", "arm,armv8";
|
||||||
|
reg = <0x0 0x3>;
|
||||||
|
enable-method = "psci";
|
||||||
|
next-level-cache = <&l2>;
|
||||||
|
clocks = <&scpi_dvfs 0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
l2: l2-cache0 {
|
||||||
|
compatible = "cache";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
arm-pmu {
|
||||||
|
compatible = "arm,cortex-a53-pmu";
|
||||||
|
interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
<GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
<GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
<GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
psci {
|
||||||
|
compatible = "arm,psci-0.2";
|
||||||
|
method = "smc";
|
||||||
|
};
|
||||||
|
|
||||||
|
timer {
|
||||||
|
compatible = "arm,armv8-timer";
|
||||||
|
interrupts = <GIC_PPI 13
|
||||||
|
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
|
||||||
|
<GIC_PPI 14
|
||||||
|
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
|
||||||
|
<GIC_PPI 11
|
||||||
|
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
|
||||||
|
<GIC_PPI 10
|
||||||
|
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
|
||||||
|
};
|
||||||
|
|
||||||
|
xtal: xtal-clk {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
clock-frequency = <24000000>;
|
||||||
|
clock-output-names = "xtal";
|
||||||
|
#clock-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
firmware {
|
||||||
|
sm: secure-monitor {
|
||||||
|
compatible = "amlogic,meson-gx-sm", "amlogic,meson-gxbb-sm";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
efuse: efuse {
|
||||||
|
compatible = "amlogic,meson-gx-efuse", "amlogic,meson-gxbb-efuse";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
sn: sn@14 {
|
||||||
|
reg = <0x14 0x10>;
|
||||||
|
};
|
||||||
|
|
||||||
|
eth_mac: eth_mac@34 {
|
||||||
|
reg = <0x34 0x10>;
|
||||||
|
};
|
||||||
|
|
||||||
|
bid: bid@46 {
|
||||||
|
reg = <0x46 0x30>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
scpi {
|
||||||
|
compatible = "amlogic,meson-gxbb-scpi", "arm,scpi-pre-1.0";
|
||||||
|
mboxes = <&mailbox 1 &mailbox 2>;
|
||||||
|
shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
|
||||||
|
|
||||||
|
scpi_clocks: clocks {
|
||||||
|
compatible = "arm,scpi-clocks";
|
||||||
|
|
||||||
|
scpi_dvfs: scpi_clocks@0 {
|
||||||
|
compatible = "arm,scpi-dvfs-clocks";
|
||||||
|
#clock-cells = <1>;
|
||||||
|
clock-indices = <0>;
|
||||||
|
clock-output-names = "vcpu";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
scpi_sensors: sensors {
|
||||||
|
compatible = "arm,scpi-sensors";
|
||||||
|
#thermal-sensor-cells = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
soc {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
cbus: cbus@c1100000 {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
reg = <0x0 0xc1100000 0x0 0x100000>;
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
|
||||||
|
|
||||||
|
reset: reset-controller@4404 {
|
||||||
|
compatible = "amlogic,meson-gx-reset", "amlogic,meson-gxbb-reset";
|
||||||
|
reg = <0x0 0x04404 0x0 0x20>;
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_A: serial@84c0 {
|
||||||
|
compatible = "amlogic,meson-uart";
|
||||||
|
reg = <0x0 0x84c0 0x0 0x14>;
|
||||||
|
interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
clocks = <&xtal>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_B: serial@84dc {
|
||||||
|
compatible = "amlogic,meson-uart";
|
||||||
|
reg = <0x0 0x84dc 0x0 0x14>;
|
||||||
|
interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
clocks = <&xtal>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_A: i2c@8500 {
|
||||||
|
compatible = "amlogic,meson-gxbb-i2c";
|
||||||
|
reg = <0x0 0x08500 0x0 0x20>;
|
||||||
|
interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ab: pwm@8550 {
|
||||||
|
compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
|
||||||
|
reg = <0x0 0x08550 0x0 0x10>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_cd: pwm@8650 {
|
||||||
|
compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
|
||||||
|
reg = <0x0 0x08650 0x0 0x10>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ef: pwm@86c0 {
|
||||||
|
compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
|
||||||
|
reg = <0x0 0x086c0 0x0 0x10>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_C: serial@8700 {
|
||||||
|
compatible = "amlogic,meson-uart";
|
||||||
|
reg = <0x0 0x8700 0x0 0x14>;
|
||||||
|
interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
clocks = <&xtal>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_B: i2c@87c0 {
|
||||||
|
compatible = "amlogic,meson-gxbb-i2c";
|
||||||
|
reg = <0x0 0x087c0 0x0 0x20>;
|
||||||
|
interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_C: i2c@87e0 {
|
||||||
|
compatible = "amlogic,meson-gxbb-i2c";
|
||||||
|
reg = <0x0 0x087e0 0x0 0x20>;
|
||||||
|
interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
watchdog@98d0 {
|
||||||
|
compatible = "amlogic,meson-gx-wdt", "amlogic,meson-gxbb-wdt";
|
||||||
|
reg = <0x0 0x098d0 0x0 0x10>;
|
||||||
|
clocks = <&xtal>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gic: interrupt-controller@c4301000 {
|
||||||
|
compatible = "arm,gic-400";
|
||||||
|
reg = <0x0 0xc4301000 0 0x1000>,
|
||||||
|
<0x0 0xc4302000 0 0x2000>,
|
||||||
|
<0x0 0xc4304000 0 0x2000>,
|
||||||
|
<0x0 0xc4306000 0 0x2000>;
|
||||||
|
interrupt-controller;
|
||||||
|
interrupts = <GIC_PPI 9
|
||||||
|
(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
|
||||||
|
#interrupt-cells = <3>;
|
||||||
|
#address-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
sram: sram@c8000000 {
|
||||||
|
compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
|
||||||
|
reg = <0x0 0xc8000000 0x0 0x14000>;
|
||||||
|
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges = <0 0x0 0xc8000000 0x14000>;
|
||||||
|
|
||||||
|
cpu_scp_lpri: scp-shmem@0 {
|
||||||
|
compatible = "amlogic,meson-gxbb-scp-shmem";
|
||||||
|
reg = <0x13000 0x400>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu_scp_hpri: scp-shmem@200 {
|
||||||
|
compatible = "amlogic,meson-gxbb-scp-shmem";
|
||||||
|
reg = <0x13400 0x400>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
aobus: aobus@c8100000 {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
reg = <0x0 0xc8100000 0x0 0x100000>;
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
|
||||||
|
|
||||||
|
uart_AO: serial@4c0 {
|
||||||
|
compatible = "amlogic,meson-uart";
|
||||||
|
reg = <0x0 0x004c0 0x0 0x14>;
|
||||||
|
interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
clocks = <&xtal>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_AO_B: serial@4e0 {
|
||||||
|
compatible = "amlogic,meson-uart";
|
||||||
|
reg = <0x0 0x004e0 0x0 0x14>;
|
||||||
|
interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
clocks = <&xtal>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
ir: ir@580 {
|
||||||
|
compatible = "amlogic,meson-gxbb-ir";
|
||||||
|
reg = <0x0 0x00580 0x0 0x40>;
|
||||||
|
interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
periphs: periphs@c8834000 {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
reg = <0x0 0xc8834000 0x0 0x2000>;
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
|
||||||
|
|
||||||
|
rng {
|
||||||
|
compatible = "amlogic,meson-rng";
|
||||||
|
reg = <0x0 0x0 0x0 0x4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
hiubus: hiubus@c883c000 {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
reg = <0x0 0xc883c000 0x0 0x2000>;
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
|
||||||
|
|
||||||
|
mailbox: mailbox@404 {
|
||||||
|
compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
|
||||||
|
reg = <0 0x404 0 0x4c>;
|
||||||
|
interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
<0 209 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
<0 210 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
#mbox-cells = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ethmac: ethernet@c9410000 {
|
||||||
|
compatible = "amlogic,meson-gx-dwmac", "amlogic,meson-gxbb-dwmac", "snps,dwmac";
|
||||||
|
reg = <0x0 0xc9410000 0x0 0x10000
|
||||||
|
0x0 0xc8834540 0x0 0x4>;
|
||||||
|
interrupts = <0 8 1>;
|
||||||
|
interrupt-names = "macirq";
|
||||||
|
phy-mode = "rgmii";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
apb: apb@d0000000 {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
reg = <0x0 0xd0000000 0x0 0x200000>;
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
|
||||||
|
|
||||||
|
sd_emmc_a: mmc@70000 {
|
||||||
|
compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
|
||||||
|
reg = <0x0 0x70000 0x0 0x2000>;
|
||||||
|
interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
sd_emmc_b: mmc@72000 {
|
||||||
|
compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
|
||||||
|
reg = <0x0 0x72000 0x0 0x2000>;
|
||||||
|
interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
sd_emmc_c: mmc@74000 {
|
||||||
|
compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
|
||||||
|
reg = <0x0 0x74000 0x0 0x2000>;
|
||||||
|
interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
vpu: vpu@d0100000 {
|
||||||
|
compatible = "amlogic,meson-gx-vpu";
|
||||||
|
reg = <0x0 0xd0100000 0x0 0x100000>,
|
||||||
|
<0x0 0xc883c000 0x0 0x1000>,
|
||||||
|
<0x0 0xc8838000 0x0 0x1000>;
|
||||||
|
reg-names = "vpu", "hhi", "dmc";
|
||||||
|
interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
/* CVBS VDAC output port */
|
||||||
|
cvbs_vdac_port: port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -64,6 +64,18 @@
|
||||||
reg = <0x0 0x0 0x0 0x80000000>;
|
reg = <0x0 0x0 0x0 0x80000000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
usb_otg_pwr: regulator-usb-pwrs {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
|
||||||
|
regulator-name = "USB_OTG_PWR";
|
||||||
|
|
||||||
|
regulator-min-microvolt = <5000000>;
|
||||||
|
regulator-max-microvolt = <5000000>;
|
||||||
|
|
||||||
|
gpio = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
|
||||||
|
enable-active-high;
|
||||||
|
};
|
||||||
|
|
||||||
leds {
|
leds {
|
||||||
compatible = "gpio-leds";
|
compatible = "gpio-leds";
|
||||||
blue {
|
blue {
|
||||||
|
@ -73,6 +85,60 @@
|
||||||
default-state = "off";
|
default-state = "off";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tflash_vdd: regulator-tflash_vdd {
|
||||||
|
/*
|
||||||
|
* signal name from schematics: TFLASH_VDD_EN
|
||||||
|
*/
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
|
||||||
|
regulator-name = "TFLASH_VDD";
|
||||||
|
regulator-min-microvolt = <3300000>;
|
||||||
|
regulator-max-microvolt = <3300000>;
|
||||||
|
|
||||||
|
gpio = <&gpio_ao GPIOAO_12 GPIO_ACTIVE_HIGH>;
|
||||||
|
enable-active-high;
|
||||||
|
};
|
||||||
|
|
||||||
|
tf_io: gpio-regulator-tf_io {
|
||||||
|
compatible = "regulator-gpio";
|
||||||
|
|
||||||
|
regulator-name = "TF_IO";
|
||||||
|
regulator-min-microvolt = <1800000>;
|
||||||
|
regulator-max-microvolt = <3300000>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* signal name from schematics: TF_3V3N_1V8_EN
|
||||||
|
*/
|
||||||
|
gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
|
||||||
|
gpios-states = <0>;
|
||||||
|
|
||||||
|
states = <3300000 0
|
||||||
|
1800000 1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
vcc1v8: regulator-vcc1v8 {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "VCC1V8";
|
||||||
|
regulator-min-microvolt = <1800000>;
|
||||||
|
regulator-max-microvolt = <1800000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
vcc3v3: regulator-vcc3v3 {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "VCC3V3";
|
||||||
|
regulator-min-microvolt = <3300000>;
|
||||||
|
regulator-max-microvolt = <3300000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
emmc_pwrseq: emmc-pwrseq {
|
||||||
|
compatible = "mmc-pwrseq-emmc";
|
||||||
|
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&scpi_clocks {
|
||||||
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
&uart_AO {
|
&uart_AO {
|
||||||
|
@ -83,6 +149,85 @@
|
||||||
|
|
||||||
ðmac {
|
ðmac {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
pinctrl-0 = <ð_pins>;
|
pinctrl-0 = <ð_rgmii_pins>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
phy-handle = <ð_phy0>;
|
||||||
|
|
||||||
|
mdio {
|
||||||
|
compatible = "snps,dwmac-mdio";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
eth_phy0: ethernet-phy@0 {
|
||||||
|
reg = <0>;
|
||||||
|
eee-broken-1000t;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&ir {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&remote_input_ao_pins>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&i2c_A {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&i2c_a_pins>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
};
|
||||||
|
|
||||||
|
&usb0_phy {
|
||||||
|
status = "okay";
|
||||||
|
phy-supply = <&usb_otg_pwr>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&usb1_phy {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&usb0 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&usb1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SD */
|
||||||
|
&sd_emmc_b {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&sdcard_pins>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
|
||||||
|
bus-width = <4>;
|
||||||
|
cap-sd-highspeed;
|
||||||
|
max-frequency = <100000000>;
|
||||||
|
disable-wp;
|
||||||
|
|
||||||
|
cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
|
||||||
|
cd-inverted;
|
||||||
|
|
||||||
|
vmmc-supply = <&tflash_vdd>;
|
||||||
|
vqmmc-supply = <&tf_io>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* eMMC */
|
||||||
|
&sd_emmc_c {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&emmc_pins>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
|
||||||
|
bus-width = <8>;
|
||||||
|
cap-sd-highspeed;
|
||||||
|
max-frequency = <200000000>;
|
||||||
|
non-removable;
|
||||||
|
disable-wp;
|
||||||
|
cap-mmc-highspeed;
|
||||||
|
mmc-ddr-1_8v;
|
||||||
|
mmc-hs200-1_8v;
|
||||||
|
|
||||||
|
mmc-pwrseq = <&emmc_pwrseq>;
|
||||||
|
vmmc-supply = <&vcc3v3>;
|
||||||
|
vqmmc-supply = <&vcc1v8>;
|
||||||
|
};
|
||||||
|
|
|
@ -40,307 +40,477 @@
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include "meson-gx.dtsi"
|
||||||
#include <dt-bindings/interrupt-controller/irq.h>
|
|
||||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
|
||||||
#include <dt-bindings/gpio/meson-gxbb-gpio.h>
|
#include <dt-bindings/gpio/meson-gxbb-gpio.h>
|
||||||
#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
|
#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
|
||||||
|
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||||
|
#include <dt-bindings/clock/gxbb-aoclkc.h>
|
||||||
|
#include <dt-bindings/reset/gxbb-aoclkc.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "amlogic,meson-gxbb";
|
compatible = "amlogic,meson-gxbb";
|
||||||
interrupt-parent = <&gic>;
|
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
|
|
||||||
cpus {
|
|
||||||
#address-cells = <0x2>;
|
|
||||||
#size-cells = <0x0>;
|
|
||||||
|
|
||||||
cpu0: cpu@0 {
|
|
||||||
device_type = "cpu";
|
|
||||||
compatible = "arm,cortex-a53", "arm,armv8";
|
|
||||||
reg = <0x0 0x0>;
|
|
||||||
enable-method = "psci";
|
|
||||||
};
|
|
||||||
|
|
||||||
cpu1: cpu@1 {
|
|
||||||
device_type = "cpu";
|
|
||||||
compatible = "arm,cortex-a53", "arm,armv8";
|
|
||||||
reg = <0x0 0x1>;
|
|
||||||
enable-method = "psci";
|
|
||||||
};
|
|
||||||
|
|
||||||
cpu2: cpu@2 {
|
|
||||||
device_type = "cpu";
|
|
||||||
compatible = "arm,cortex-a53", "arm,armv8";
|
|
||||||
reg = <0x0 0x2>;
|
|
||||||
enable-method = "psci";
|
|
||||||
};
|
|
||||||
|
|
||||||
cpu3: cpu@3 {
|
|
||||||
device_type = "cpu";
|
|
||||||
compatible = "arm,cortex-a53", "arm,armv8";
|
|
||||||
reg = <0x0 0x3>;
|
|
||||||
enable-method = "psci";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
arm-pmu {
|
|
||||||
compatible = "arm,cortex-a53-pmu";
|
|
||||||
interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
<GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
<GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
<GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
psci {
|
|
||||||
compatible = "arm,psci-0.2";
|
|
||||||
method = "smc";
|
|
||||||
};
|
|
||||||
|
|
||||||
timer {
|
|
||||||
compatible = "arm,armv8-timer";
|
|
||||||
interrupts = <GIC_PPI 13
|
|
||||||
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
|
|
||||||
<GIC_PPI 14
|
|
||||||
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
|
|
||||||
<GIC_PPI 11
|
|
||||||
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>,
|
|
||||||
<GIC_PPI 10
|
|
||||||
(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_EDGE_RISING)>;
|
|
||||||
};
|
|
||||||
|
|
||||||
xtal: xtal-clk {
|
|
||||||
compatible = "fixed-clock";
|
|
||||||
clock-frequency = <24000000>;
|
|
||||||
clock-output-names = "xtal";
|
|
||||||
#clock-cells = <0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
soc {
|
soc {
|
||||||
compatible = "simple-bus";
|
usb0_phy: phy@c0000000 {
|
||||||
#address-cells = <2>;
|
compatible = "amlogic,meson-gxbb-usb2-phy";
|
||||||
#size-cells = <2>;
|
#phy-cells = <0>;
|
||||||
ranges;
|
reg = <0x0 0xc0000000 0x0 0x20>;
|
||||||
|
resets = <&reset RESET_USB_OTG>;
|
||||||
cbus: cbus@c1100000 {
|
clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
|
||||||
compatible = "simple-bus";
|
clock-names = "usb_general", "usb";
|
||||||
reg = <0x0 0xc1100000 0x0 0x100000>;
|
status = "disabled";
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
|
|
||||||
|
|
||||||
reset: reset-controller@4404 {
|
|
||||||
compatible = "amlogic,meson-gxbb-reset";
|
|
||||||
reg = <0x0 0x04404 0x0 0x20>;
|
|
||||||
#reset-cells = <1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_A: serial@84c0 {
|
|
||||||
compatible = "amlogic,meson-uart";
|
|
||||||
reg = <0x0 0x84c0 0x0 0x14>;
|
|
||||||
interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
|
|
||||||
clocks = <&xtal>;
|
|
||||||
status = "disabled";
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_B: serial@84dc {
|
|
||||||
compatible = "amlogic,meson-uart";
|
|
||||||
reg = <0x0 0x84dc 0x0 0x14>;
|
|
||||||
interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
|
|
||||||
clocks = <&xtal>;
|
|
||||||
status = "disabled";
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_C: serial@8700 {
|
|
||||||
compatible = "amlogic,meson-uart";
|
|
||||||
reg = <0x0 0x8700 0x0 0x14>;
|
|
||||||
interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
|
|
||||||
clocks = <&xtal>;
|
|
||||||
status = "disabled";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
gic: interrupt-controller@c4301000 {
|
usb1_phy: phy@c0000020 {
|
||||||
compatible = "arm,gic-400";
|
compatible = "amlogic,meson-gxbb-usb2-phy";
|
||||||
reg = <0x0 0xc4301000 0 0x1000>,
|
#phy-cells = <0>;
|
||||||
<0x0 0xc4302000 0 0x2000>,
|
reg = <0x0 0xc0000020 0x0 0x20>;
|
||||||
<0x0 0xc4304000 0 0x2000>,
|
resets = <&reset RESET_USB_OTG>;
|
||||||
<0x0 0xc4306000 0 0x2000>;
|
clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1>;
|
||||||
interrupt-controller;
|
clock-names = "usb_general", "usb";
|
||||||
interrupts = <GIC_PPI 9
|
status = "disabled";
|
||||||
(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
|
|
||||||
#interrupt-cells = <3>;
|
|
||||||
#address-cells = <0>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
aobus: aobus@c8100000 {
|
usb0: usb@c9000000 {
|
||||||
compatible = "simple-bus";
|
compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
|
||||||
reg = <0x0 0xc8100000 0x0 0x100000>;
|
reg = <0x0 0xc9000000 0x0 0x40000>;
|
||||||
#address-cells = <2>;
|
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
#size-cells = <2>;
|
clocks = <&clkc CLKID_USB0_DDR_BRIDGE>;
|
||||||
ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
|
clock-names = "otg";
|
||||||
|
phys = <&usb0_phy>;
|
||||||
pinctrl_aobus: pinctrl@14 {
|
phy-names = "usb2-phy";
|
||||||
compatible = "amlogic,meson-gxbb-aobus-pinctrl";
|
dr_mode = "host";
|
||||||
#address-cells = <2>;
|
status = "disabled";
|
||||||
#size-cells = <2>;
|
|
||||||
ranges;
|
|
||||||
|
|
||||||
gpio_ao: bank@14 {
|
|
||||||
reg = <0x0 0x00014 0x0 0x8>,
|
|
||||||
<0x0 0x0002c 0x0 0x4>,
|
|
||||||
<0x0 0x00024 0x0 0x8>;
|
|
||||||
reg-names = "mux", "pull", "gpio";
|
|
||||||
gpio-controller;
|
|
||||||
#gpio-cells = <2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_ao_a_pins: uart_ao_a {
|
|
||||||
mux {
|
|
||||||
groups = "uart_tx_ao_a", "uart_rx_ao_a";
|
|
||||||
function = "uart_ao";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_AO: serial@4c0 {
|
|
||||||
compatible = "amlogic,meson-uart";
|
|
||||||
reg = <0x0 0x004c0 0x0 0x14>;
|
|
||||||
interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
|
|
||||||
clocks = <&xtal>;
|
|
||||||
status = "disabled";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
periphs: periphs@c8834000 {
|
usb1: usb@c9100000 {
|
||||||
compatible = "simple-bus";
|
compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
|
||||||
reg = <0x0 0xc8834000 0x0 0x2000>;
|
reg = <0x0 0xc9100000 0x0 0x40000>;
|
||||||
#address-cells = <2>;
|
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
#size-cells = <2>;
|
clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
|
||||||
ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
|
clock-names = "otg";
|
||||||
|
phys = <&usb1_phy>;
|
||||||
rng {
|
phy-names = "usb2-phy";
|
||||||
compatible = "amlogic,meson-rng";
|
dr_mode = "host";
|
||||||
reg = <0x0 0x0 0x0 0x4>;
|
|
||||||
};
|
|
||||||
|
|
||||||
pinctrl_periphs: pinctrl@4b0 {
|
|
||||||
compatible = "amlogic,meson-gxbb-periphs-pinctrl";
|
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
ranges;
|
|
||||||
|
|
||||||
gpio: bank@4b0 {
|
|
||||||
reg = <0x0 0x004b0 0x0 0x28>,
|
|
||||||
<0x0 0x004e8 0x0 0x14>,
|
|
||||||
<0x0 0x00120 0x0 0x14>,
|
|
||||||
<0x0 0x00430 0x0 0x40>;
|
|
||||||
reg-names = "mux", "pull", "pull-enable", "gpio";
|
|
||||||
gpio-controller;
|
|
||||||
#gpio-cells = <2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
emmc_pins: emmc {
|
|
||||||
mux {
|
|
||||||
groups = "emmc_nand_d07",
|
|
||||||
"emmc_cmd",
|
|
||||||
"emmc_clk";
|
|
||||||
function = "emmc";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sdcard_pins: sdcard {
|
|
||||||
mux {
|
|
||||||
groups = "sdcard_d0",
|
|
||||||
"sdcard_d1",
|
|
||||||
"sdcard_d2",
|
|
||||||
"sdcard_d3",
|
|
||||||
"sdcard_cmd",
|
|
||||||
"sdcard_clk";
|
|
||||||
function = "sdcard";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_a_pins: uart_a {
|
|
||||||
mux {
|
|
||||||
groups = "uart_tx_a",
|
|
||||||
"uart_rx_a";
|
|
||||||
function = "uart_a";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_b_pins: uart_b {
|
|
||||||
mux {
|
|
||||||
groups = "uart_tx_b",
|
|
||||||
"uart_rx_b";
|
|
||||||
function = "uart_b";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_c_pins: uart_c {
|
|
||||||
mux {
|
|
||||||
groups = "uart_tx_c",
|
|
||||||
"uart_rx_c";
|
|
||||||
function = "uart_c";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
eth_pins: eth_c {
|
|
||||||
mux {
|
|
||||||
groups = "eth_mdio",
|
|
||||||
"eth_mdc",
|
|
||||||
"eth_clk_rx_clk",
|
|
||||||
"eth_rx_dv",
|
|
||||||
"eth_rxd0",
|
|
||||||
"eth_rxd1",
|
|
||||||
"eth_rxd2",
|
|
||||||
"eth_rxd3",
|
|
||||||
"eth_rgmii_tx_clk",
|
|
||||||
"eth_tx_en",
|
|
||||||
"eth_txd0",
|
|
||||||
"eth_txd1",
|
|
||||||
"eth_txd2",
|
|
||||||
"eth_txd3";
|
|
||||||
function = "eth";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
hiubus: hiubus@c883c000 {
|
|
||||||
compatible = "simple-bus";
|
|
||||||
reg = <0x0 0xc883c000 0x0 0x2000>;
|
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
|
|
||||||
|
|
||||||
clkc: clock-controller@0 {
|
|
||||||
compatible = "amlogic,gxbb-clkc";
|
|
||||||
#clock-cells = <1>;
|
|
||||||
reg = <0x0 0x0 0x0 0x3db>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
apb: apb@d0000000 {
|
|
||||||
compatible = "simple-bus";
|
|
||||||
reg = <0x0 0xd0000000 0x0 0x200000>;
|
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
ethmac: ethernet@c9410000 {
|
|
||||||
compatible = "amlogic,meson6-dwmac", "snps,dwmac";
|
|
||||||
reg = <0x0 0xc9410000 0x0 0x10000
|
|
||||||
0x0 0xc8834540 0x0 0x4>;
|
|
||||||
interrupts = <0 8 1>;
|
|
||||||
interrupt-names = "macirq";
|
|
||||||
clocks = <&xtal>;
|
|
||||||
clock-names = "stmmaceth";
|
|
||||||
phy-mode = "rgmii";
|
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&cbus {
|
||||||
|
spifc: spi@8c80 {
|
||||||
|
compatible = "amlogic,meson-gxbb-spifc";
|
||||||
|
reg = <0x0 0x08c80 0x0 0x80>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
clocks = <&clkc CLKID_SPI>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ðmac {
|
||||||
|
clocks = <&clkc CLKID_ETH>,
|
||||||
|
<&clkc CLKID_FCLK_DIV2>,
|
||||||
|
<&clkc CLKID_MPLL2>;
|
||||||
|
clock-names = "stmmaceth", "clkin0", "clkin1";
|
||||||
|
};
|
||||||
|
|
||||||
|
&aobus {
|
||||||
|
pinctrl_aobus: pinctrl@14 {
|
||||||
|
compatible = "amlogic,meson-gxbb-aobus-pinctrl";
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
gpio_ao: bank@14 {
|
||||||
|
reg = <0x0 0x00014 0x0 0x8>,
|
||||||
|
<0x0 0x0002c 0x0 0x4>,
|
||||||
|
<0x0 0x00024 0x0 0x8>;
|
||||||
|
reg-names = "mux", "pull", "gpio";
|
||||||
|
gpio-controller;
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_ao_a_pins: uart_ao_a {
|
||||||
|
mux {
|
||||||
|
groups = "uart_tx_ao_a", "uart_rx_ao_a";
|
||||||
|
function = "uart_ao";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_ao_a_cts_rts_pins: uart_ao_a_cts_rts {
|
||||||
|
mux {
|
||||||
|
groups = "uart_cts_ao_a",
|
||||||
|
"uart_rts_ao_a";
|
||||||
|
function = "uart_ao";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_ao_b_pins: uart_ao_b {
|
||||||
|
mux {
|
||||||
|
groups = "uart_tx_ao_b", "uart_rx_ao_b";
|
||||||
|
function = "uart_ao_b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_ao_b_cts_rts_pins: uart_ao_b_cts_rts {
|
||||||
|
mux {
|
||||||
|
groups = "uart_cts_ao_b",
|
||||||
|
"uart_rts_ao_b";
|
||||||
|
function = "uart_ao_b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
remote_input_ao_pins: remote_input_ao {
|
||||||
|
mux {
|
||||||
|
groups = "remote_input_ao";
|
||||||
|
function = "remote_input_ao";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_ao_pins: i2c_ao {
|
||||||
|
mux {
|
||||||
|
groups = "i2c_sck_ao",
|
||||||
|
"i2c_sda_ao";
|
||||||
|
function = "i2c_ao";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ao_a_3_pins: pwm_ao_a_3 {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_ao_a_3";
|
||||||
|
function = "pwm_ao_a_3";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ao_a_6_pins: pwm_ao_a_6 {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_ao_a_6";
|
||||||
|
function = "pwm_ao_a_6";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ao_a_12_pins: pwm_ao_a_12 {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_ao_a_12";
|
||||||
|
function = "pwm_ao_a_12";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ao_b_pins: pwm_ao_b {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_ao_b";
|
||||||
|
function = "pwm_ao_b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
clkc_AO: clock-controller@040 {
|
||||||
|
compatible = "amlogic,gxbb-aoclkc";
|
||||||
|
reg = <0x0 0x00040 0x0 0x4>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ab_AO: pwm@550 {
|
||||||
|
compatible = "amlogic,meson-gxbb-pwm";
|
||||||
|
reg = <0x0 0x0550 0x0 0x10>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_AO: i2c@500 {
|
||||||
|
compatible = "amlogic,meson-gxbb-i2c";
|
||||||
|
reg = <0x0 0x500 0x0 0x20>;
|
||||||
|
interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
clocks = <&clkc CLKID_AO_I2C>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&periphs {
|
||||||
|
pinctrl_periphs: pinctrl@4b0 {
|
||||||
|
compatible = "amlogic,meson-gxbb-periphs-pinctrl";
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
gpio: bank@4b0 {
|
||||||
|
reg = <0x0 0x004b0 0x0 0x28>,
|
||||||
|
<0x0 0x004e8 0x0 0x14>,
|
||||||
|
<0x0 0x00120 0x0 0x14>,
|
||||||
|
<0x0 0x00430 0x0 0x40>;
|
||||||
|
reg-names = "mux", "pull", "pull-enable", "gpio";
|
||||||
|
gpio-controller;
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
emmc_pins: emmc {
|
||||||
|
mux {
|
||||||
|
groups = "emmc_nand_d07",
|
||||||
|
"emmc_cmd",
|
||||||
|
"emmc_clk",
|
||||||
|
"emmc_ds";
|
||||||
|
function = "emmc";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nor_pins: nor {
|
||||||
|
mux {
|
||||||
|
groups = "nor_d",
|
||||||
|
"nor_q",
|
||||||
|
"nor_c",
|
||||||
|
"nor_cs";
|
||||||
|
function = "nor";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sdcard_pins: sdcard {
|
||||||
|
mux {
|
||||||
|
groups = "sdcard_d0",
|
||||||
|
"sdcard_d1",
|
||||||
|
"sdcard_d2",
|
||||||
|
"sdcard_d3",
|
||||||
|
"sdcard_cmd",
|
||||||
|
"sdcard_clk";
|
||||||
|
function = "sdcard";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sdio_pins: sdio {
|
||||||
|
mux {
|
||||||
|
groups = "sdio_d0",
|
||||||
|
"sdio_d1",
|
||||||
|
"sdio_d2",
|
||||||
|
"sdio_d3",
|
||||||
|
"sdio_cmd",
|
||||||
|
"sdio_clk";
|
||||||
|
function = "sdio";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sdio_irq_pins: sdio_irq {
|
||||||
|
mux {
|
||||||
|
groups = "sdio_irq";
|
||||||
|
function = "sdio";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_a_pins: uart_a {
|
||||||
|
mux {
|
||||||
|
groups = "uart_tx_a",
|
||||||
|
"uart_rx_a";
|
||||||
|
function = "uart_a";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_a_cts_rts_pins: uart_a_cts_rts {
|
||||||
|
mux {
|
||||||
|
groups = "uart_cts_a",
|
||||||
|
"uart_rts_a";
|
||||||
|
function = "uart_a";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_b_pins: uart_b {
|
||||||
|
mux {
|
||||||
|
groups = "uart_tx_b",
|
||||||
|
"uart_rx_b";
|
||||||
|
function = "uart_b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_b_cts_rts_pins: uart_b_cts_rts {
|
||||||
|
mux {
|
||||||
|
groups = "uart_cts_b",
|
||||||
|
"uart_rts_b";
|
||||||
|
function = "uart_b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_c_pins: uart_c {
|
||||||
|
mux {
|
||||||
|
groups = "uart_tx_c",
|
||||||
|
"uart_rx_c";
|
||||||
|
function = "uart_c";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart_c_cts_rts_pins: uart_c_cts_rts {
|
||||||
|
mux {
|
||||||
|
groups = "uart_cts_c",
|
||||||
|
"uart_rts_c";
|
||||||
|
function = "uart_c";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_a_pins: i2c_a {
|
||||||
|
mux {
|
||||||
|
groups = "i2c_sck_a",
|
||||||
|
"i2c_sda_a";
|
||||||
|
function = "i2c_a";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_b_pins: i2c_b {
|
||||||
|
mux {
|
||||||
|
groups = "i2c_sck_b",
|
||||||
|
"i2c_sda_b";
|
||||||
|
function = "i2c_b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_c_pins: i2c_c {
|
||||||
|
mux {
|
||||||
|
groups = "i2c_sck_c",
|
||||||
|
"i2c_sda_c";
|
||||||
|
function = "i2c_c";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
eth_rgmii_pins: eth-rgmii {
|
||||||
|
mux {
|
||||||
|
groups = "eth_mdio",
|
||||||
|
"eth_mdc",
|
||||||
|
"eth_clk_rx_clk",
|
||||||
|
"eth_rx_dv",
|
||||||
|
"eth_rxd0",
|
||||||
|
"eth_rxd1",
|
||||||
|
"eth_rxd2",
|
||||||
|
"eth_rxd3",
|
||||||
|
"eth_rgmii_tx_clk",
|
||||||
|
"eth_tx_en",
|
||||||
|
"eth_txd0",
|
||||||
|
"eth_txd1",
|
||||||
|
"eth_txd2",
|
||||||
|
"eth_txd3";
|
||||||
|
function = "eth";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
eth_rmii_pins: eth-rmii {
|
||||||
|
mux {
|
||||||
|
groups = "eth_mdio",
|
||||||
|
"eth_mdc",
|
||||||
|
"eth_clk_rx_clk",
|
||||||
|
"eth_rx_dv",
|
||||||
|
"eth_rxd0",
|
||||||
|
"eth_rxd1",
|
||||||
|
"eth_tx_en",
|
||||||
|
"eth_txd0",
|
||||||
|
"eth_txd1";
|
||||||
|
function = "eth";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_a_x_pins: pwm_a_x {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_a_x";
|
||||||
|
function = "pwm_a_x";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_a_y_pins: pwm_a_y {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_a_y";
|
||||||
|
function = "pwm_a_y";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_b_pins: pwm_b {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_b";
|
||||||
|
function = "pwm_b";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_d_pins: pwm_d {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_d";
|
||||||
|
function = "pwm_d";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_e_pins: pwm_e {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_e";
|
||||||
|
function = "pwm_e";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_f_x_pins: pwm_f_x {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_f_x";
|
||||||
|
function = "pwm_f_x";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_f_y_pins: pwm_f_y {
|
||||||
|
mux {
|
||||||
|
groups = "pwm_f_y";
|
||||||
|
function = "pwm_f_y";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hdmi_hpd_pins: hdmi_hpd {
|
||||||
|
mux {
|
||||||
|
groups = "hdmi_hpd";
|
||||||
|
function = "hdmi_hpd";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hdmi_i2c_pins: hdmi_i2c {
|
||||||
|
mux {
|
||||||
|
groups = "hdmi_sda", "hdmi_scl";
|
||||||
|
function = "hdmi_i2c";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&hiubus {
|
||||||
|
clkc: clock-controller@0 {
|
||||||
|
compatible = "amlogic,gxbb-clkc";
|
||||||
|
#clock-cells = <1>;
|
||||||
|
reg = <0x0 0x0 0x0 0x3db>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2c_A {
|
||||||
|
clocks = <&clkc CLKID_I2C>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2c_B {
|
||||||
|
clocks = <&clkc CLKID_I2C>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2c_C {
|
||||||
|
clocks = <&clkc CLKID_I2C>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&sd_emmc_a {
|
||||||
|
clocks = <&clkc CLKID_SD_EMMC_A>,
|
||||||
|
<&xtal>,
|
||||||
|
<&clkc CLKID_FCLK_DIV2>;
|
||||||
|
clock-names = "core", "clkin0", "clkin1";
|
||||||
|
};
|
||||||
|
|
||||||
|
&sd_emmc_b {
|
||||||
|
clocks = <&clkc CLKID_SD_EMMC_B>,
|
||||||
|
<&xtal>,
|
||||||
|
<&clkc CLKID_FCLK_DIV2>;
|
||||||
|
clock-names = "core", "clkin0", "clkin1";
|
||||||
|
};
|
||||||
|
|
||||||
|
&sd_emmc_c {
|
||||||
|
clocks = <&clkc CLKID_SD_EMMC_C>,
|
||||||
|
<&xtal>,
|
||||||
|
<&clkc CLKID_FCLK_DIV2>;
|
||||||
|
clock-names = "core", "clkin0", "clkin1";
|
||||||
|
};
|
||||||
|
|
||||||
|
&vpu {
|
||||||
|
compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
|
||||||
|
};
|
||||||
|
|
89
arch/arm/include/asm/arch-meson/sd_emmc.h
Normal file
89
arch/arm/include/asm/arch-meson/sd_emmc.h
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2016 Carlo Caione <carlo@caione.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SD_EMMC_H__
|
||||||
|
#define __SD_EMMC_H__
|
||||||
|
|
||||||
|
#include <mmc.h>
|
||||||
|
|
||||||
|
#define SDIO_PORT_A 0
|
||||||
|
#define SDIO_PORT_B 1
|
||||||
|
#define SDIO_PORT_C 2
|
||||||
|
|
||||||
|
#define SD_EMMC_CLKSRC_24M 24000000 /* 24 MHz */
|
||||||
|
#define SD_EMMC_CLKSRC_DIV2 1000000000 /* 1 GHz */
|
||||||
|
|
||||||
|
#define MESON_SD_EMMC_CLOCK 0x00
|
||||||
|
#define CLK_MAX_DIV 63
|
||||||
|
#define CLK_SRC_24M (0 << 6)
|
||||||
|
#define CLK_SRC_DIV2 (1 << 6)
|
||||||
|
#define CLK_CO_PHASE_000 (0 << 8)
|
||||||
|
#define CLK_CO_PHASE_090 (1 << 8)
|
||||||
|
#define CLK_CO_PHASE_180 (2 << 8)
|
||||||
|
#define CLK_CO_PHASE_270 (3 << 8)
|
||||||
|
#define CLK_TX_PHASE_000 (0 << 10)
|
||||||
|
#define CLK_TX_PHASE_090 (1 << 10)
|
||||||
|
#define CLK_TX_PHASE_180 (2 << 10)
|
||||||
|
#define CLK_TX_PHASE_270 (3 << 10)
|
||||||
|
#define CLK_ALWAYS_ON BIT(24)
|
||||||
|
|
||||||
|
#define MESON_SD_EMMC_CFG 0x44
|
||||||
|
#define CFG_BUS_WIDTH_MASK GENMASK(1, 0)
|
||||||
|
#define CFG_BUS_WIDTH_1 0
|
||||||
|
#define CFG_BUS_WIDTH_4 1
|
||||||
|
#define CFG_BUS_WIDTH_8 2
|
||||||
|
#define CFG_BL_LEN_MASK GENMASK(7, 4)
|
||||||
|
#define CFG_BL_LEN_SHIFT 4
|
||||||
|
#define CFG_BL_LEN_512 (9 << 4)
|
||||||
|
#define CFG_RESP_TIMEOUT_MASK GENMASK(11, 8)
|
||||||
|
#define CFG_RESP_TIMEOUT_256 (8 << 8)
|
||||||
|
#define CFG_RC_CC_MASK GENMASK(15, 12)
|
||||||
|
#define CFG_RC_CC_16 (4 << 12)
|
||||||
|
#define CFG_SDCLK_ALWAYS_ON BIT(18)
|
||||||
|
#define CFG_AUTO_CLK BIT(23)
|
||||||
|
|
||||||
|
#define MESON_SD_EMMC_STATUS 0x48
|
||||||
|
#define STATUS_MASK GENMASK(15, 0)
|
||||||
|
#define STATUS_ERR_MASK GENMASK(12, 0)
|
||||||
|
#define STATUS_RXD_ERR_MASK GENMASK(7, 0)
|
||||||
|
#define STATUS_TXD_ERR BIT(8)
|
||||||
|
#define STATUS_DESC_ERR BIT(9)
|
||||||
|
#define STATUS_RESP_ERR BIT(10)
|
||||||
|
#define STATUS_RESP_TIMEOUT BIT(11)
|
||||||
|
#define STATUS_DESC_TIMEOUT BIT(12)
|
||||||
|
#define STATUS_END_OF_CHAIN BIT(13)
|
||||||
|
|
||||||
|
#define MESON_SD_EMMC_IRQ_EN 0x4c
|
||||||
|
|
||||||
|
#define MESON_SD_EMMC_CMD_CFG 0x50
|
||||||
|
#define CMD_CFG_LENGTH_MASK GENMASK(8, 0)
|
||||||
|
#define CMD_CFG_BLOCK_MODE BIT(9)
|
||||||
|
#define CMD_CFG_R1B BIT(10)
|
||||||
|
#define CMD_CFG_END_OF_CHAIN BIT(11)
|
||||||
|
#define CMD_CFG_TIMEOUT_4S (12 << 12)
|
||||||
|
#define CMD_CFG_NO_RESP BIT(16)
|
||||||
|
#define CMD_CFG_DATA_IO BIT(18)
|
||||||
|
#define CMD_CFG_DATA_WR BIT(19)
|
||||||
|
#define CMD_CFG_RESP_NOCRC BIT(20)
|
||||||
|
#define CMD_CFG_RESP_128 BIT(21)
|
||||||
|
#define CMD_CFG_CMD_INDEX_SHIFT 24
|
||||||
|
#define CMD_CFG_OWNER BIT(31)
|
||||||
|
|
||||||
|
#define MESON_SD_EMMC_CMD_ARG 0x54
|
||||||
|
#define MESON_SD_EMMC_CMD_DAT 0x58
|
||||||
|
#define MESON_SD_EMMC_CMD_RSP 0x5c
|
||||||
|
#define MESON_SD_EMMC_CMD_RSP1 0x60
|
||||||
|
#define MESON_SD_EMMC_CMD_RSP2 0x64
|
||||||
|
#define MESON_SD_EMMC_CMD_RSP3 0x68
|
||||||
|
|
||||||
|
struct meson_mmc_platdata {
|
||||||
|
struct mmc_config cfg;
|
||||||
|
struct mmc mmc;
|
||||||
|
void *regbase;
|
||||||
|
void *w_buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,7 +14,10 @@ CONFIG_DEFAULT_DEVICE_TREE="meson-gxbb-odroidc2"
|
||||||
# CONFIG_CMD_SETEXPR is not set
|
# CONFIG_CMD_SETEXPR is not set
|
||||||
CONFIG_OF_CONTROL=y
|
CONFIG_OF_CONTROL=y
|
||||||
CONFIG_NET_RANDOM_ETHADDR=y
|
CONFIG_NET_RANDOM_ETHADDR=y
|
||||||
# CONFIG_MMC is not set
|
CONFIG_MMC=y
|
||||||
|
CONFIG_DM_MMC=y
|
||||||
|
CONFIG_MMC_MESON_GX=y
|
||||||
|
CONFIG_CMD_MMC=y
|
||||||
CONFIG_DM_ETH=y
|
CONFIG_DM_ETH=y
|
||||||
CONFIG_ETH_DESIGNWARE=y
|
CONFIG_ETH_DESIGNWARE=y
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
|
|
|
@ -105,6 +105,12 @@ config MMC_DW_SOCFPGA
|
||||||
Synopsys DesignWare Memory Card Interface driver. Select this option
|
Synopsys DesignWare Memory Card Interface driver. Select this option
|
||||||
for platforms based on Altera SOCFPGA.
|
for platforms based on Altera SOCFPGA.
|
||||||
|
|
||||||
|
config MMC_MESON_GX
|
||||||
|
bool "Meson GX EMMC controller support"
|
||||||
|
depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_MESON
|
||||||
|
help
|
||||||
|
Support for EMMC host controller on Meson GX ARM SoCs platform (S905)
|
||||||
|
|
||||||
config MMC_MXC
|
config MMC_MXC
|
||||||
bool "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
|
bool "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
|
||||||
help
|
help
|
||||||
|
@ -365,6 +371,15 @@ config MMC_SUNXI
|
||||||
This selects support for the SD/MMC Host Controller on
|
This selects support for the SD/MMC Host Controller on
|
||||||
Allwinner sunxi SoCs.
|
Allwinner sunxi SoCs.
|
||||||
|
|
||||||
|
config GENERIC_ATMEL_MCI
|
||||||
|
bool "Atmel Multimedia Card Interface support"
|
||||||
|
depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
|
||||||
|
help
|
||||||
|
This enables support for Atmel High Speed Multimedia Card Interface
|
||||||
|
(HSMCI), which supports the MultiMedia Card (MMC) Specification V4.3,
|
||||||
|
the SD Memory Card Specification V2.0, the SDIO V2.0 specification
|
||||||
|
and CE-ATA V1.1.
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
|
config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
|
||||||
|
|
|
@ -29,6 +29,7 @@ ifdef CONFIG_SUPPORT_EMMC_BOOT
|
||||||
obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
|
obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
|
||||||
endif
|
endif
|
||||||
obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
|
obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
|
||||||
|
obj-$(CONFIG_MMC_MESON_GX) += meson_gx_mmc.o
|
||||||
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
|
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
|
||||||
obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
|
obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
|
||||||
obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
|
obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
/* 400KHz is max freq for card ID etc. Use that as min */
|
/* 400KHz is max freq for card ID etc. Use that as min */
|
||||||
#define MIN_FREQ 400000
|
#define MIN_FREQ 400000
|
||||||
|
#define SDHCI_BUFFER 0x20
|
||||||
|
|
||||||
struct bcm2835_sdhci_host {
|
struct bcm2835_sdhci_host {
|
||||||
struct sdhci_host host;
|
struct sdhci_host host;
|
||||||
|
@ -69,8 +70,11 @@ static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val,
|
||||||
* (Which is just as well - otherwise we'd have to nobble the DMA engine
|
* (Which is just as well - otherwise we'd have to nobble the DMA engine
|
||||||
* too)
|
* too)
|
||||||
*/
|
*/
|
||||||
while (timer_get_us() - bcm_host->last_write < bcm_host->twoticks_delay)
|
if (reg != SDHCI_BUFFER) {
|
||||||
;
|
while (timer_get_us() - bcm_host->last_write <
|
||||||
|
bcm_host->twoticks_delay)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
writel(val, host->ioaddr + reg);
|
writel(val, host->ioaddr + reg);
|
||||||
bcm_host->last_write = timer_get_us();
|
bcm_host->last_write = timer_get_us();
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <clk.h>
|
||||||
#include <mmc.h>
|
#include <mmc.h>
|
||||||
#include <part.h>
|
#include <part.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
@ -18,8 +19,11 @@
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
#include <asm/arch/clk.h>
|
#include <asm/arch/clk.h>
|
||||||
#include <asm/arch/hardware.h>
|
#include <asm/arch/hardware.h>
|
||||||
|
#include <dm/device.h>
|
||||||
#include "atmel_mci.h"
|
#include "atmel_mci.h"
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
#ifndef CONFIG_SYS_MMC_CLK_OD
|
#ifndef CONFIG_SYS_MMC_CLK_OD
|
||||||
# define CONFIG_SYS_MMC_CLK_OD 150000
|
# define CONFIG_SYS_MMC_CLK_OD 150000
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,6 +41,10 @@ struct atmel_mci_priv {
|
||||||
struct atmel_mci *mci;
|
struct atmel_mci *mci;
|
||||||
unsigned int initialized:1;
|
unsigned int initialized:1;
|
||||||
unsigned int curr_clk;
|
unsigned int curr_clk;
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
struct mmc mmc;
|
||||||
|
ulong bus_clk_rate;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Read Atmel MCI IP version */
|
/* Read Atmel MCI IP version */
|
||||||
|
@ -58,11 +66,19 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup for MCI Clock and Block Size */
|
/* Setup for MCI Clock and Block Size */
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
static void mci_set_mode(struct atmel_mci_priv *priv, u32 hz, u32 blklen)
|
||||||
|
{
|
||||||
|
struct mmc *mmc = &priv->mmc;
|
||||||
|
u32 bus_hz = priv->bus_clk_rate;
|
||||||
|
#else
|
||||||
static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
|
static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
|
||||||
{
|
{
|
||||||
struct atmel_mci_priv *priv = mmc->priv;
|
struct atmel_mci_priv *priv = mmc->priv;
|
||||||
atmel_mci_t *mci = priv->mci;
|
|
||||||
u32 bus_hz = get_mci_clk_rate();
|
u32 bus_hz = get_mci_clk_rate();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
atmel_mci_t *mci = priv->mci;
|
||||||
u32 clkdiv = 255;
|
u32 clkdiv = 255;
|
||||||
unsigned int version = atmel_mci_get_version(mci);
|
unsigned int version = atmel_mci_get_version(mci);
|
||||||
u32 clkodd = 0;
|
u32 clkodd = 0;
|
||||||
|
@ -202,10 +218,18 @@ io_fail:
|
||||||
* Sends a command out on the bus and deals with the block data.
|
* Sends a command out on the bus and deals with the block data.
|
||||||
* Takes the mmc pointer, a command pointer, and an optional data pointer.
|
* Takes the mmc pointer, a command pointer, and an optional data pointer.
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||||
|
struct mmc_data *data)
|
||||||
|
{
|
||||||
|
struct atmel_mci_priv *priv = dev_get_priv(dev);
|
||||||
|
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||||
|
#else
|
||||||
static int
|
static int
|
||||||
mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct atmel_mci_priv *priv = mmc->priv;
|
struct atmel_mci_priv *priv = mmc->priv;
|
||||||
|
#endif
|
||||||
atmel_mci_t *mci = priv->mci;
|
atmel_mci_t *mci = priv->mci;
|
||||||
u32 cmdr;
|
u32 cmdr;
|
||||||
u32 error_flags = 0;
|
u32 error_flags = 0;
|
||||||
|
@ -335,17 +359,28 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
static int atmel_mci_set_ios(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct atmel_mci_priv *priv = dev_get_priv(dev);
|
||||||
|
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||||
|
#else
|
||||||
/* Entered into mmc structure during driver init */
|
/* Entered into mmc structure during driver init */
|
||||||
static int mci_set_ios(struct mmc *mmc)
|
static int mci_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct atmel_mci_priv *priv = mmc->priv;
|
struct atmel_mci_priv *priv = mmc->priv;
|
||||||
|
#endif
|
||||||
atmel_mci_t *mci = priv->mci;
|
atmel_mci_t *mci = priv->mci;
|
||||||
int bus_width = mmc->bus_width;
|
int bus_width = mmc->bus_width;
|
||||||
unsigned int version = atmel_mci_get_version(mci);
|
unsigned int version = atmel_mci_get_version(mci);
|
||||||
int busw;
|
int busw;
|
||||||
|
|
||||||
/* Set the clock speed */
|
/* Set the clock speed */
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
mci_set_mode(priv, mmc->clock, MMC_DEFAULT_BLKLEN);
|
||||||
|
#else
|
||||||
mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
|
mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set the bus width and select slot for this interface
|
* set the bus width and select slot for this interface
|
||||||
|
@ -374,10 +409,15 @@ static int mci_set_ios(struct mmc *mmc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
static int atmel_mci_hw_init(struct atmel_mci_priv *priv)
|
||||||
|
{
|
||||||
|
#else
|
||||||
/* Entered into mmc structure during driver init */
|
/* Entered into mmc structure during driver init */
|
||||||
static int mci_init(struct mmc *mmc)
|
static int mci_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct atmel_mci_priv *priv = mmc->priv;
|
struct atmel_mci_priv *priv = mmc->priv;
|
||||||
|
#endif
|
||||||
atmel_mci_t *mci = priv->mci;
|
atmel_mci_t *mci = priv->mci;
|
||||||
|
|
||||||
/* Initialize controller */
|
/* Initialize controller */
|
||||||
|
@ -392,11 +432,16 @@ static int mci_init(struct mmc *mmc)
|
||||||
writel(~0UL, &mci->idr);
|
writel(~0UL, &mci->idr);
|
||||||
|
|
||||||
/* Set default clocks and blocklen */
|
/* Set default clocks and blocklen */
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
mci_set_mode(priv, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
|
||||||
|
#else
|
||||||
mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
|
mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_DM_MMC
|
||||||
static const struct mmc_ops atmel_mci_ops = {
|
static const struct mmc_ops atmel_mci_ops = {
|
||||||
.send_cmd = mci_send_cmd,
|
.send_cmd = mci_send_cmd,
|
||||||
.set_ios = mci_set_ios,
|
.set_ios = mci_set_ios,
|
||||||
|
@ -456,3 +501,114 @@ int atmel_mci_init(void *regs)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
static const struct dm_mmc_ops atmel_mci_mmc_ops = {
|
||||||
|
.send_cmd = atmel_mci_send_cmd,
|
||||||
|
.set_ios = atmel_mci_set_ios,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv)
|
||||||
|
{
|
||||||
|
struct mmc_config *cfg;
|
||||||
|
u32 version;
|
||||||
|
|
||||||
|
cfg = &priv->cfg;
|
||||||
|
cfg->name = "Atmel mci";
|
||||||
|
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the version is above 3.0, the capabilities of the 8-bit
|
||||||
|
* bus width and high speed are supported.
|
||||||
|
*/
|
||||||
|
version = atmel_mci_get_version(priv->mci);
|
||||||
|
if ((version & 0xf00) >= 0x300) {
|
||||||
|
cfg->host_caps = MMC_MODE_8BIT |
|
||||||
|
MMC_MODE_HS | MMC_MODE_HS_52MHz;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg->host_caps |= MMC_MODE_4BIT;
|
||||||
|
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
cfg->f_min = priv->bus_clk_rate / (2 * 256);
|
||||||
|
cfg->f_max = priv->bus_clk_rate / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atmel_mci_enable_clk(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct atmel_mci_priv *priv = dev_get_priv(dev);
|
||||||
|
struct clk clk;
|
||||||
|
ulong clk_rate;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = clk_get_by_index(dev, 0, &clk);
|
||||||
|
if (ret) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_enable(&clk);
|
||||||
|
if (ret)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
clk_rate = clk_get_rate(&clk);
|
||||||
|
if (!clk_rate) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->bus_clk_rate = clk_rate;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
clk_free(&clk);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atmel_mci_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||||
|
struct atmel_mci_priv *priv = dev_get_priv(dev);
|
||||||
|
struct mmc *mmc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = atmel_mci_enable_clk(dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
priv->mci = (struct atmel_mci *)dev_get_addr_ptr(dev);
|
||||||
|
|
||||||
|
atmel_mci_setup_cfg(priv);
|
||||||
|
|
||||||
|
mmc = &priv->mmc;
|
||||||
|
mmc->cfg = &priv->cfg;
|
||||||
|
mmc->dev = dev;
|
||||||
|
upriv->mmc = mmc;
|
||||||
|
|
||||||
|
atmel_mci_hw_init(priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atmel_mci_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct atmel_mci_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
return mmc_bind(dev, &priv->mmc, &priv->cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct udevice_id atmel_mci_ids[] = {
|
||||||
|
{ .compatible = "atmel,hsmci" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(atmel_mci) = {
|
||||||
|
.name = "atmel-mci",
|
||||||
|
.id = UCLASS_MMC,
|
||||||
|
.of_match = atmel_mci_ids,
|
||||||
|
.bind = atmel_mci_bind,
|
||||||
|
.probe = atmel_mci_probe,
|
||||||
|
.priv_auto_alloc_size = sizeof(struct atmel_mci_priv),
|
||||||
|
.ops = &atmel_mci_mmc_ops,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
291
drivers/mmc/meson_gx_mmc.c
Normal file
291
drivers/mmc/meson_gx_mmc.c
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2016 Carlo Caione <carlo@caione.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <fdtdec.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <mmc.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/arch/sd_emmc.h>
|
||||||
|
#include <dm/device.h>
|
||||||
|
#include <linux/log2.h>
|
||||||
|
|
||||||
|
static inline void *get_regbase(const struct mmc *mmc)
|
||||||
|
{
|
||||||
|
struct meson_mmc_platdata *pdata = mmc->priv;
|
||||||
|
|
||||||
|
return pdata->regbase;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t meson_read(struct mmc *mmc, int offset)
|
||||||
|
{
|
||||||
|
return readl(get_regbase(mmc) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void meson_write(struct mmc *mmc, uint32_t val, int offset)
|
||||||
|
{
|
||||||
|
writel(val, get_regbase(mmc) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void meson_mmc_config_clock(struct mmc *mmc)
|
||||||
|
{
|
||||||
|
uint32_t meson_mmc_clk = 0;
|
||||||
|
unsigned int clk, clk_src, clk_div;
|
||||||
|
|
||||||
|
/* 1GHz / CLK_MAX_DIV = 15,9 MHz */
|
||||||
|
if (mmc->clock > 16000000) {
|
||||||
|
clk = SD_EMMC_CLKSRC_DIV2;
|
||||||
|
clk_src = CLK_SRC_DIV2;
|
||||||
|
} else {
|
||||||
|
clk = SD_EMMC_CLKSRC_24M;
|
||||||
|
clk_src = CLK_SRC_24M;
|
||||||
|
}
|
||||||
|
clk_div = DIV_ROUND_UP(clk, mmc->clock);
|
||||||
|
|
||||||
|
/* 180 phase core clock */
|
||||||
|
meson_mmc_clk |= CLK_CO_PHASE_180;
|
||||||
|
|
||||||
|
/* 180 phase tx clock */
|
||||||
|
meson_mmc_clk |= CLK_TX_PHASE_000;
|
||||||
|
|
||||||
|
/* clock settings */
|
||||||
|
meson_mmc_clk |= clk_src;
|
||||||
|
meson_mmc_clk |= clk_div;
|
||||||
|
|
||||||
|
meson_write(mmc, meson_mmc_clk, MESON_SD_EMMC_CLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int meson_dm_mmc_set_ios(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||||
|
uint32_t meson_mmc_cfg;
|
||||||
|
|
||||||
|
meson_mmc_config_clock(mmc);
|
||||||
|
|
||||||
|
meson_mmc_cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
|
||||||
|
|
||||||
|
meson_mmc_cfg &= ~CFG_BUS_WIDTH_MASK;
|
||||||
|
if (mmc->bus_width == 1)
|
||||||
|
meson_mmc_cfg |= CFG_BUS_WIDTH_1;
|
||||||
|
else if (mmc->bus_width == 4)
|
||||||
|
meson_mmc_cfg |= CFG_BUS_WIDTH_4;
|
||||||
|
else if (mmc->bus_width == 8)
|
||||||
|
meson_mmc_cfg |= CFG_BUS_WIDTH_8;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* 512 bytes block length */
|
||||||
|
meson_mmc_cfg &= ~CFG_BL_LEN_MASK;
|
||||||
|
meson_mmc_cfg |= CFG_BL_LEN_512;
|
||||||
|
|
||||||
|
/* Response timeout 256 clk */
|
||||||
|
meson_mmc_cfg &= ~CFG_RESP_TIMEOUT_MASK;
|
||||||
|
meson_mmc_cfg |= CFG_RESP_TIMEOUT_256;
|
||||||
|
|
||||||
|
/* Command-command gap 16 clk */
|
||||||
|
meson_mmc_cfg &= ~CFG_RC_CC_MASK;
|
||||||
|
meson_mmc_cfg |= CFG_RC_CC_16;
|
||||||
|
|
||||||
|
meson_write(mmc, meson_mmc_cfg, MESON_SD_EMMC_CFG);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void meson_mmc_setup_cmd(struct mmc *mmc, struct mmc_data *data,
|
||||||
|
struct mmc_cmd *cmd)
|
||||||
|
{
|
||||||
|
uint32_t meson_mmc_cmd = 0, cfg;
|
||||||
|
|
||||||
|
meson_mmc_cmd |= cmd->cmdidx << CMD_CFG_CMD_INDEX_SHIFT;
|
||||||
|
|
||||||
|
if (cmd->resp_type & MMC_RSP_PRESENT) {
|
||||||
|
if (cmd->resp_type & MMC_RSP_136)
|
||||||
|
meson_mmc_cmd |= CMD_CFG_RESP_128;
|
||||||
|
|
||||||
|
if (cmd->resp_type & MMC_RSP_BUSY)
|
||||||
|
meson_mmc_cmd |= CMD_CFG_R1B;
|
||||||
|
|
||||||
|
if (!(cmd->resp_type & MMC_RSP_CRC))
|
||||||
|
meson_mmc_cmd |= CMD_CFG_RESP_NOCRC;
|
||||||
|
} else {
|
||||||
|
meson_mmc_cmd |= CMD_CFG_NO_RESP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
|
||||||
|
cfg &= ~CFG_BL_LEN_MASK;
|
||||||
|
cfg |= ilog2(data->blocksize) << CFG_BL_LEN_SHIFT;
|
||||||
|
meson_write(mmc, cfg, MESON_SD_EMMC_CFG);
|
||||||
|
|
||||||
|
if (data->flags == MMC_DATA_WRITE)
|
||||||
|
meson_mmc_cmd |= CMD_CFG_DATA_WR;
|
||||||
|
|
||||||
|
meson_mmc_cmd |= CMD_CFG_DATA_IO | CMD_CFG_BLOCK_MODE |
|
||||||
|
data->blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
meson_mmc_cmd |= CMD_CFG_TIMEOUT_4S | CMD_CFG_OWNER |
|
||||||
|
CMD_CFG_END_OF_CHAIN;
|
||||||
|
|
||||||
|
meson_write(mmc, meson_mmc_cmd, MESON_SD_EMMC_CMD_CFG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void meson_mmc_setup_addr(struct mmc *mmc, struct mmc_data *data)
|
||||||
|
{
|
||||||
|
struct meson_mmc_platdata *pdata = mmc->priv;
|
||||||
|
unsigned int data_size;
|
||||||
|
uint32_t data_addr = 0;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
data_size = data->blocks * data->blocksize;
|
||||||
|
|
||||||
|
if (data->flags == MMC_DATA_READ) {
|
||||||
|
data_addr = (ulong) data->dest;
|
||||||
|
invalidate_dcache_range(data_addr,
|
||||||
|
data_addr + data_size);
|
||||||
|
} else {
|
||||||
|
pdata->w_buf = calloc(data_size, sizeof(char));
|
||||||
|
data_addr = (ulong) pdata->w_buf;
|
||||||
|
memcpy(pdata->w_buf, data->src, data_size);
|
||||||
|
flush_dcache_range(data_addr, data_addr + data_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meson_write(mmc, data_addr, MESON_SD_EMMC_CMD_DAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void meson_mmc_read_response(struct mmc *mmc, struct mmc_cmd *cmd)
|
||||||
|
{
|
||||||
|
if (cmd->resp_type & MMC_RSP_136) {
|
||||||
|
cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP3);
|
||||||
|
cmd->response[1] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP2);
|
||||||
|
cmd->response[2] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP1);
|
||||||
|
cmd->response[3] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
|
||||||
|
} else {
|
||||||
|
cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int meson_dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||||
|
struct mmc_data *data)
|
||||||
|
{
|
||||||
|
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||||
|
struct meson_mmc_platdata *pdata = mmc->priv;
|
||||||
|
uint32_t status;
|
||||||
|
ulong start;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* max block size supported by chip is 512 byte */
|
||||||
|
if (data && data->blocksize > 512)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
meson_mmc_setup_cmd(mmc, data, cmd);
|
||||||
|
meson_mmc_setup_addr(mmc, data);
|
||||||
|
|
||||||
|
meson_write(mmc, cmd->cmdarg, MESON_SD_EMMC_CMD_ARG);
|
||||||
|
|
||||||
|
/* use 10s timeout */
|
||||||
|
start = get_timer(0);
|
||||||
|
do {
|
||||||
|
status = meson_read(mmc, MESON_SD_EMMC_STATUS);
|
||||||
|
} while(!(status & STATUS_END_OF_CHAIN) && get_timer(start) < 10000);
|
||||||
|
|
||||||
|
if (!(status & STATUS_END_OF_CHAIN))
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
else if (status & STATUS_RESP_TIMEOUT)
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
else if (status & STATUS_ERR_MASK)
|
||||||
|
ret = -EIO;
|
||||||
|
|
||||||
|
meson_mmc_read_response(mmc, cmd);
|
||||||
|
|
||||||
|
if (data && data->flags == MMC_DATA_WRITE)
|
||||||
|
free(pdata->w_buf);
|
||||||
|
|
||||||
|
/* reset status bits */
|
||||||
|
meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dm_mmc_ops meson_dm_mmc_ops = {
|
||||||
|
.send_cmd = meson_dm_mmc_send_cmd,
|
||||||
|
.set_ios = meson_dm_mmc_set_ios,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int meson_mmc_ofdata_to_platdata(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
|
||||||
|
fdt_addr_t addr;
|
||||||
|
|
||||||
|
addr = dev_get_addr(dev);
|
||||||
|
if (addr == FDT_ADDR_T_NONE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pdata->regbase = (void *)addr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int meson_mmc_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
|
||||||
|
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||||
|
struct mmc *mmc = &pdata->mmc;
|
||||||
|
struct mmc_config *cfg = &pdata->cfg;
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
cfg->voltages = MMC_VDD_33_34 | MMC_VDD_32_33 |
|
||||||
|
MMC_VDD_31_32 | MMC_VDD_165_195;
|
||||||
|
cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
|
||||||
|
MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
||||||
|
cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
|
||||||
|
cfg->f_max = 100000000; /* 100 MHz */
|
||||||
|
cfg->b_max = 256; /* max 256 blocks */
|
||||||
|
cfg->name = dev->name;
|
||||||
|
|
||||||
|
mmc->priv = pdata;
|
||||||
|
upriv->mmc = mmc;
|
||||||
|
|
||||||
|
mmc_set_clock(mmc, cfg->f_min);
|
||||||
|
|
||||||
|
/* reset all status bits */
|
||||||
|
meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
|
||||||
|
|
||||||
|
/* disable interrupts */
|
||||||
|
meson_write(mmc, 0, MESON_SD_EMMC_IRQ_EN);
|
||||||
|
|
||||||
|
/* enable auto clock mode */
|
||||||
|
val = meson_read(mmc, MESON_SD_EMMC_CFG);
|
||||||
|
val &= ~CFG_SDCLK_ALWAYS_ON;
|
||||||
|
val |= CFG_AUTO_CLK;
|
||||||
|
meson_write(mmc, val, MESON_SD_EMMC_CFG);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int meson_mmc_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
return mmc_bind(dev, &pdata->mmc, &pdata->cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct udevice_id meson_mmc_match[] = {
|
||||||
|
{ .compatible = "amlogic,meson-gx-mmc" },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(meson_mmc) = {
|
||||||
|
.name = "meson_gx_mmc",
|
||||||
|
.id = UCLASS_MMC,
|
||||||
|
.of_match = meson_mmc_match,
|
||||||
|
.ops = &meson_dm_mmc_ops,
|
||||||
|
.probe = meson_mmc_probe,
|
||||||
|
.bind = meson_mmc_bind,
|
||||||
|
.ofdata_to_platdata = meson_mmc_ofdata_to_platdata,
|
||||||
|
.platdata_auto_alloc_size = sizeof(struct meson_mmc_platdata),
|
||||||
|
};
|
|
@ -72,6 +72,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
|
||||||
unsigned int start_addr)
|
unsigned int start_addr)
|
||||||
{
|
{
|
||||||
unsigned int stat, rdy, mask, timeout, block = 0;
|
unsigned int stat, rdy, mask, timeout, block = 0;
|
||||||
|
bool transfer_done = false;
|
||||||
#ifdef CONFIG_MMC_SDHCI_SDMA
|
#ifdef CONFIG_MMC_SDHCI_SDMA
|
||||||
unsigned char ctrl;
|
unsigned char ctrl;
|
||||||
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
||||||
|
@ -89,17 +90,23 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
|
||||||
__func__, stat);
|
__func__, stat);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if (stat & rdy) {
|
if (!transfer_done && (stat & rdy)) {
|
||||||
if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
|
if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
|
||||||
continue;
|
continue;
|
||||||
sdhci_writel(host, rdy, SDHCI_INT_STATUS);
|
sdhci_writel(host, rdy, SDHCI_INT_STATUS);
|
||||||
sdhci_transfer_pio(host, data);
|
sdhci_transfer_pio(host, data);
|
||||||
data->dest += data->blocksize;
|
data->dest += data->blocksize;
|
||||||
if (++block >= data->blocks)
|
if (++block >= data->blocks) {
|
||||||
break;
|
/* Keep looping until the SDHCI_INT_DATA_END is
|
||||||
|
* cleared, even if we finished sending all the
|
||||||
|
* blocks.
|
||||||
|
*/
|
||||||
|
transfer_done = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_MMC_SDHCI_SDMA
|
#ifdef CONFIG_MMC_SDHCI_SDMA
|
||||||
if (stat & SDHCI_INT_DMA_END) {
|
if (!transfer_done && (stat & SDHCI_INT_DMA_END)) {
|
||||||
sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
|
sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
|
||||||
start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
|
start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
|
||||||
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
|
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
|
||||||
|
|
66
include/dt-bindings/clock/gxbb-aoclkc.h
Normal file
66
include/dt-bindings/clock/gxbb-aoclkc.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
|
* redistributing this file, you may do so under either license.
|
||||||
|
*
|
||||||
|
* GPL LICENSE SUMMARY
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 BayLibre, SAS.
|
||||||
|
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* The full GNU General Public License is included in this distribution
|
||||||
|
* in the file called COPYING.
|
||||||
|
*
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 BayLibre, SAS.
|
||||||
|
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
|
||||||
|
#define DT_BINDINGS_CLOCK_AMLOGIC_MESON_GXBB_AOCLK
|
||||||
|
|
||||||
|
#define CLKID_AO_REMOTE 0
|
||||||
|
#define CLKID_AO_I2C_MASTER 1
|
||||||
|
#define CLKID_AO_I2C_SLAVE 2
|
||||||
|
#define CLKID_AO_UART1 3
|
||||||
|
#define CLKID_AO_UART2 4
|
||||||
|
#define CLKID_AO_IR_BLASTER 5
|
||||||
|
|
||||||
|
#endif
|
34
include/dt-bindings/clock/gxbb-clkc.h
Normal file
34
include/dt-bindings/clock/gxbb-clkc.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* GXBB clock tree IDs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GXBB_CLKC_H
|
||||||
|
#define __GXBB_CLKC_H
|
||||||
|
|
||||||
|
#define CLKID_CPUCLK 1
|
||||||
|
#define CLKID_HDMI_PLL 2
|
||||||
|
#define CLKID_FCLK_DIV2 4
|
||||||
|
#define CLKID_FCLK_DIV3 5
|
||||||
|
#define CLKID_FCLK_DIV4 6
|
||||||
|
#define CLKID_CLK81 12
|
||||||
|
#define CLKID_MPLL2 15
|
||||||
|
#define CLKID_SPI 34
|
||||||
|
#define CLKID_I2C 22
|
||||||
|
#define CLKID_SAR_ADC 23
|
||||||
|
#define CLKID_ETH 36
|
||||||
|
#define CLKID_USB0 50
|
||||||
|
#define CLKID_USB1 51
|
||||||
|
#define CLKID_USB 55
|
||||||
|
#define CLKID_HDMI_PCLK 63
|
||||||
|
#define CLKID_USB1_DDR_BRIDGE 64
|
||||||
|
#define CLKID_USB0_DDR_BRIDGE 65
|
||||||
|
#define CLKID_SANA 69
|
||||||
|
#define CLKID_GCLK_VENCI_INT0 77
|
||||||
|
#define CLKID_AO_I2C 93
|
||||||
|
#define CLKID_SD_EMMC_A 94
|
||||||
|
#define CLKID_SD_EMMC_B 95
|
||||||
|
#define CLKID_SD_EMMC_C 96
|
||||||
|
#define CLKID_SAR_ADC_CLK 97
|
||||||
|
#define CLKID_SAR_ADC_SEL 98
|
||||||
|
|
||||||
|
#endif /* __GXBB_CLKC_H */
|
66
include/dt-bindings/reset/gxbb-aoclkc.h
Normal file
66
include/dt-bindings/reset/gxbb-aoclkc.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
|
* redistributing this file, you may do so under either license.
|
||||||
|
*
|
||||||
|
* GPL LICENSE SUMMARY
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 BayLibre, SAS.
|
||||||
|
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* The full GNU General Public License is included in this distribution
|
||||||
|
* in the file called COPYING.
|
||||||
|
*
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 BayLibre, SAS.
|
||||||
|
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
|
||||||
|
#define DT_BINDINGS_RESET_AMLOGIC_MESON_GXBB_AOCLK
|
||||||
|
|
||||||
|
#define RESET_AO_REMOTE 0
|
||||||
|
#define RESET_AO_I2C_MASTER 1
|
||||||
|
#define RESET_AO_I2C_SLAVE 2
|
||||||
|
#define RESET_AO_UART1 3
|
||||||
|
#define RESET_AO_UART2 4
|
||||||
|
#define RESET_AO_IR_BLASTER 5
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue