From a3b02a1d49269c769d1890ee05b74dc067538ed7 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 12 Apr 2017 20:28:36 +0200 Subject: arm: dts: update Meson GXBB / Odroid-C2 DT with recent Linux version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a prerequisite for adding a Meson GX MMC driver update the Meson GXBB / Odroid-C2 device tree in Uboot with the latest version from Linux. Signed-off-by: Neil Armstrong Signed-off-by: Carlo Caione Signed-off-by: Andreas Färber Signed-off-by: Heiner Kallweit diff --git a/arch/arm/dts/meson-gx.dtsi b/arch/arm/dts/meson-gx.dtsi new file mode 100644 index 0000000..c129100 --- /dev/null +++ b/arch/arm/dts/meson-gx.dtsi @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2016 Andreas Färber + * + * Copyright (c) 2016 BayLibre, SAS. + * Author: Neil Armstrong + * + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione + * + * 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 +#include +#include + +/ { + 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 = , + , + , + ; + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + 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 = ; + clocks = <&xtal>; + status = "disabled"; + }; + + uart_B: serial@84dc { + compatible = "amlogic,meson-uart"; + reg = <0x0 0x84dc 0x0 0x14>; + interrupts = ; + clocks = <&xtal>; + status = "disabled"; + }; + + i2c_A: i2c@8500 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x08500 0x0 0x20>; + interrupts = ; + #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 = ; + clocks = <&xtal>; + status = "disabled"; + }; + + i2c_B: i2c@87c0 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x087c0 0x0 0x20>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c_C: i2c@87e0 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x087e0 0x0 0x20>; + interrupts = ; + #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 = ; + #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 = ; + clocks = <&xtal>; + status = "disabled"; + }; + + uart_AO_B: serial@4e0 { + compatible = "amlogic,meson-uart"; + reg = <0x0 0x004e0 0x0 0x14>; + interrupts = ; + clocks = <&xtal>; + status = "disabled"; + }; + + ir: ir@580 { + compatible = "amlogic,meson-gxbb-ir"; + reg = <0x0 0x00580 0x0 0x40>; + interrupts = ; + 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 = ; + status = "disabled"; + }; + + sd_emmc_b: mmc@72000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x72000 0x0 0x2000>; + interrupts = ; + status = "disabled"; + }; + + sd_emmc_c: mmc@74000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x74000 0x0 0x2000>; + interrupts = ; + 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 = ; + #address-cells = <1>; + #size-cells = <0>; + + /* CVBS VDAC output port */ + cvbs_vdac_port: port@0 { + reg = <0>; + }; + }; + }; +}; diff --git a/arch/arm/dts/meson-gxbb-odroidc2.dts b/arch/arm/dts/meson-gxbb-odroidc2.dts index 79bee64..c737183 100644 --- a/arch/arm/dts/meson-gxbb-odroidc2.dts +++ b/arch/arm/dts/meson-gxbb-odroidc2.dts @@ -64,6 +64,18 @@ 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 { compatible = "gpio-leds"; blue { @@ -73,6 +85,60 @@ 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 { @@ -83,6 +149,85 @@ ðmac { 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"; }; + +&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>; +}; diff --git a/arch/arm/dts/meson-gxbb.dtsi b/arch/arm/dts/meson-gxbb.dtsi index e502c24..39a774a 100644 --- a/arch/arm/dts/meson-gxbb.dtsi +++ b/arch/arm/dts/meson-gxbb.dtsi @@ -40,307 +40,477 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include -#include +#include "meson-gx.dtsi" #include #include +#include +#include +#include / { 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"; + soc { + usb0_phy: phy@c0000000 { + compatible = "amlogic,meson-gxbb-usb2-phy"; + #phy-cells = <0>; + reg = <0x0 0xc0000000 0x0 0x20>; + resets = <&reset RESET_USB_OTG>; + clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>; + clock-names = "usb_general", "usb"; + status = "disabled"; }; - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x1>; - enable-method = "psci"; + usb1_phy: phy@c0000020 { + compatible = "amlogic,meson-gxbb-usb2-phy"; + #phy-cells = <0>; + reg = <0x0 0xc0000020 0x0 0x20>; + resets = <&reset RESET_USB_OTG>; + clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1>; + clock-names = "usb_general", "usb"; + status = "disabled"; }; - cpu2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x2>; - enable-method = "psci"; + usb0: usb@c9000000 { + compatible = "amlogic,meson-gxbb-usb", "snps,dwc2"; + reg = <0x0 0xc9000000 0x0 0x40000>; + interrupts = ; + clocks = <&clkc CLKID_USB0_DDR_BRIDGE>; + clock-names = "otg"; + phys = <&usb0_phy>; + phy-names = "usb2-phy"; + dr_mode = "host"; + status = "disabled"; }; - cpu3: cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x3>; - enable-method = "psci"; + usb1: usb@c9100000 { + compatible = "amlogic,meson-gxbb-usb", "snps,dwc2"; + reg = <0x0 0xc9100000 0x0 0x40000>; + interrupts = ; + clocks = <&clkc CLKID_USB1_DDR_BRIDGE>; + clock-names = "otg"; + phys = <&usb1_phy>; + phy-names = "usb2-phy"; + dr_mode = "host"; + status = "disabled"; }; }; +}; - arm-pmu { - compatible = "arm,cortex-a53-pmu"; - interrupts = , - , - , - ; - interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; +&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"; + }; + }; - psci { - compatible = "arm,psci-0.2"; - method = "smc"; + 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"; + }; + }; }; - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; + clkc_AO: clock-controller@040 { + compatible = "amlogic,gxbb-aoclkc"; + reg = <0x0 0x00040 0x0 0x4>; + #clock-cells = <1>; + #reset-cells = <1>; }; - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; + pwm_ab_AO: pwm@550 { + compatible = "amlogic,meson-gxbb-pwm"; + reg = <0x0 0x0550 0x0 0x10>; + #pwm-cells = <3>; + status = "disabled"; }; - soc { - compatible = "simple-bus"; + i2c_AO: i2c@500 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x500 0x0 0x20>; + interrupts = ; + 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; - 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-gxbb-reset"; - reg = <0x0 0x04404 0x0 0x20>; - #reset-cells = <1>; - }; - - uart_A: serial@84c0 { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x84c0 0x0 0x14>; - interrupts = ; - clocks = <&xtal>; - status = "disabled"; - }; - - uart_B: serial@84dc { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x84dc 0x0 0x14>; - interrupts = ; - clocks = <&xtal>; - status = "disabled"; - }; - - uart_C: serial@8700 { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x8700 0x0 0x14>; - interrupts = ; - clocks = <&xtal>; - status = "disabled"; - }; - }; - - 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 = ; - #interrupt-cells = <3>; - #address-cells = <0>; - }; - - aobus: aobus@c8100000 { - compatible = "simple-bus"; - reg = <0x0 0xc8100000 0x0 0x100000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>; - - 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: serial@4c0 { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x004c0 0x0 0x14>; - interrupts = ; - clocks = <&xtal>; - 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>; - }; - - 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"; + 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"; +}; diff --git a/include/dt-bindings/clock/gxbb-aoclkc.h b/include/dt-bindings/clock/gxbb-aoclkc.h new file mode 100644 index 0000000..3175148 --- /dev/null +++ b/include/dt-bindings/clock/gxbb-aoclkc.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 + * + * 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 . + * 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 + * + * 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 diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h new file mode 100644 index 0000000..692846c --- /dev/null +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -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 */ diff --git a/include/dt-bindings/reset/gxbb-aoclkc.h b/include/dt-bindings/reset/gxbb-aoclkc.h new file mode 100644 index 0000000..9e3fd60 --- /dev/null +++ b/include/dt-bindings/reset/gxbb-aoclkc.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 + * + * 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 . + * 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 + * + * 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 -- cgit v0.10.2 From 937386204dab93bc8362230aa5fa899e302177af Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Wed, 12 Apr 2017 20:30:42 +0200 Subject: mmc: meson: add MMC driver for Meson GX (S905) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver implements MMC support on Meson GX (S905) based systems. It's based on Carlo Caione's work, changes: - BLK support added - general refactoring Signed-off-by: Carlo Caione Signed-off-by: Andreas Färber Signed-off-by: Heiner Kallweit Tested-by: Vagrant Cascadian diff --git a/arch/arm/include/asm/arch-meson/sd_emmc.h b/arch/arm/include/asm/arch-meson/sd_emmc.h new file mode 100644 index 0000000..a09e034 --- /dev/null +++ b/arch/arm/include/asm/arch-meson/sd_emmc.h @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2016 Carlo Caione + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __SD_EMMC_H__ +#define __SD_EMMC_H__ + +#include + +#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 diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 560391f..077b184 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -105,6 +105,12 @@ config MMC_DW_SOCFPGA Synopsys DesignWare Memory Card Interface driver. Select this option 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 bool "Freescale i.MX21/27/31 or MPC512x Multimedia Card support" help diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 6a26a52..a61a9e9 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -29,6 +29,7 @@ ifdef CONFIG_SUPPORT_EMMC_BOOT obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o endif 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_MVEBU_MMC) += mvebu_mmc.o obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c new file mode 100644 index 0000000..8e28ab7 --- /dev/null +++ b/drivers/mmc/meson_gx_mmc.c @@ -0,0 +1,291 @@ +/* + * (C) Copyright 2016 Carlo Caione + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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), +}; -- cgit v0.10.2 From d0c5c8d529f16fa88ab52a3b5dd2d4fc03664f19 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 12 Apr 2017 20:32:06 +0200 Subject: odroid-c2: enable new Meson GX MMC driver in board defconfig Enable new Meson GX MMC driver in Odroid C2 defconfig. Signed-off-by: Heiner Kallweit diff --git a/configs/odroid-c2_defconfig b/configs/odroid-c2_defconfig index 2cf5011..00da76e 100644 --- a/configs/odroid-c2_defconfig +++ b/configs/odroid-c2_defconfig @@ -14,7 +14,10 @@ CONFIG_DEFAULT_DEVICE_TREE="meson-gxbb-odroidc2" # CONFIG_CMD_SETEXPR is not set CONFIG_OF_CONTROL=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_ETH_DESIGNWARE=y CONFIG_PINCTRL=y -- cgit v0.10.2 From c86c0155dcfbb02ce92c4d7245ffdf6fa904fbee Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Thu, 13 Apr 2017 10:29:22 +0800 Subject: mmc: gen_atmel_mci: add driver model support for mci Add the driver model support for Atmel mci while retaining the existing legacy code. This allows the driver to support boards that have converted to driver model as well as those that have not. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 077b184..6ac26dd 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -371,6 +371,15 @@ config MMC_SUNXI This selects support for the SD/MMC Host Controller on 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 config TEGRA124_MMC_DISABLE_EXT_LOOPBACK diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index 7dc4a5d..c25d9ed 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -18,8 +19,11 @@ #include #include #include +#include #include "atmel_mci.h" +DECLARE_GLOBAL_DATA_PTR; + #ifndef CONFIG_SYS_MMC_CLK_OD # define CONFIG_SYS_MMC_CLK_OD 150000 #endif @@ -37,6 +41,10 @@ struct atmel_mci_priv { struct atmel_mci *mci; unsigned int initialized:1; unsigned int curr_clk; +#ifdef CONFIG_DM_MMC + struct mmc mmc; + ulong bus_clk_rate; +#endif }; /* 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 */ +#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) { struct atmel_mci_priv *priv = mmc->priv; - atmel_mci_t *mci = priv->mci; u32 bus_hz = get_mci_clk_rate(); +#endif + + atmel_mci_t *mci = priv->mci; u32 clkdiv = 255; unsigned int version = atmel_mci_get_version(mci); u32 clkodd = 0; @@ -202,10 +218,18 @@ io_fail: * 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. */ +#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 mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct atmel_mci_priv *priv = mmc->priv; +#endif atmel_mci_t *mci = priv->mci; u32 cmdr; u32 error_flags = 0; @@ -335,17 +359,28 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) 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 */ static int mci_set_ios(struct mmc *mmc) { struct atmel_mci_priv *priv = mmc->priv; +#endif atmel_mci_t *mci = priv->mci; int bus_width = mmc->bus_width; unsigned int version = atmel_mci_get_version(mci); int busw; /* 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); +#endif /* * set the bus width and select slot for this interface @@ -374,10 +409,15 @@ static int mci_set_ios(struct mmc *mmc) 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 */ static int mci_init(struct mmc *mmc) { struct atmel_mci_priv *priv = mmc->priv; +#endif atmel_mci_t *mci = priv->mci; /* Initialize controller */ @@ -392,11 +432,16 @@ static int mci_init(struct mmc *mmc) writel(~0UL, &mci->idr); /* 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); +#endif return 0; } +#ifndef CONFIG_DM_MMC static const struct mmc_ops atmel_mci_ops = { .send_cmd = mci_send_cmd, .set_ios = mci_set_ios, @@ -456,3 +501,114 @@ int atmel_mci_init(void *regs) 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 -- cgit v0.10.2 From 4db2b61fcf206cb45753cd1f988a9b0aad92b561 Mon Sep 17 00:00:00 2001 From: Jocelyn Bohr Date: Sun, 2 Apr 2017 01:24:33 -0700 Subject: mmc: bcm2835_sdhci: Speed up mmc writes. The linux kernel driver for this module does not use a delay when writing to the SDHCI_BUFFER register. This patch mimics that behavior in order to speed up the mmc writes on the Raspberry Pi. Signed-off-by: Alex Deymo Reviewed-by: Simon Glass diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 29c2a85..20079bc 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -44,6 +44,7 @@ /* 400KHz is max freq for card ID etc. Use that as min */ #define MIN_FREQ 400000 +#define SDHCI_BUFFER 0x20 struct bcm2835_sdhci_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 * 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); bcm_host->last_write = timer_get_us(); -- cgit v0.10.2 From 7dde50d70787eb2faeced82d0c025762b12363ea Mon Sep 17 00:00:00 2001 From: Alex Deymo Date: Sun, 2 Apr 2017 01:24:34 -0700 Subject: mmc: sdhci: Wait for SDHCI_INT_DATA_END when transferring. sdhci_transfer_data() function transfers the blocks passed up to the number of blocks defined in mmc_data, but returns immediately once all the blocks are transferred, even if the loop exit condition is not met (bit SDHCI_INT_DATA_END set in the STATUS word). When doing multiple writes to mmc, returning right after the last block is transferred can cause the write to fail when sending the MMC_CMD_STOP_TRANSMISSION command right after the MMC_CMD_WRITE_MULTIPLE_BLOCK command, leaving the mmc driver in an unconsistent state until reboot. This error was observed in the rpi3 board. This patch waits for the SDHCI_INT_DATA_END bit to be set even after sending all the blocks. Test: Reliably wrote 2GiB of data to mmc in a rpi3. Signed-off-by: Alex Deymo Reviewed-by: Simon Glass diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index c94d58d..b745977 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -72,6 +72,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, unsigned int start_addr) { unsigned int stat, rdy, mask, timeout, block = 0; + bool transfer_done = false; #ifdef CONFIG_MMC_SDHCI_SDMA unsigned char ctrl; 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); return -EIO; } - if (stat & rdy) { + if (!transfer_done && (stat & rdy)) { if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)) continue; sdhci_writel(host, rdy, SDHCI_INT_STATUS); sdhci_transfer_pio(host, data); data->dest += data->blocksize; - if (++block >= data->blocks) - break; + if (++block >= data->blocks) { + /* 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 - if (stat & SDHCI_INT_DMA_END) { + if (!transfer_done && (stat & SDHCI_INT_DMA_END)) { sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS); start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1); start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE; -- cgit v0.10.2