commit
af1b7286d8
@ -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>; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
@ -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 |
@ -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), |
||||
}; |
@ -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 |
@ -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 */ |
@ -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…
Reference in new issue