mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
Merge git://git.denx.de/u-boot-dm
This commit is contained in:
commit
68e80fdda1
145 changed files with 7919 additions and 2273 deletions
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/sromc.h>
|
||||
|
||||
|
@ -172,6 +172,9 @@ static int exynos5420_mmc_config(int peripheral, int flags)
|
|||
* this same assumption.
|
||||
*/
|
||||
if ((peripheral == PERIPH_ID_SDMMC0) && (i == (start + 2))) {
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
gpio_request(i, "sdmmc0_vdden");
|
||||
#endif
|
||||
gpio_set_value(i, 1);
|
||||
gpio_cfg_pin(i, S5P_GPIO_OUTPUT);
|
||||
} else {
|
||||
|
|
|
@ -7,9 +7,16 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/include/ "skeleton.dtsi"
|
||||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
combiner: interrupt-controller@10440000 {
|
||||
compatible = "samsung,exynos4210-combiner";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0x10440000 0x1000>;
|
||||
};
|
||||
|
||||
serial@13800000 {
|
||||
compatible = "samsung,exynos4210-uart";
|
||||
reg = <0x13800000 0x3c>;
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "skeleton.dtsi"
|
||||
/include/ "exynos4.dtsi"
|
||||
#include "skeleton.dtsi"
|
||||
#include "exynos4210.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Insignal Origen evaluation board based on Exynos4210";
|
||||
|
|
27
arch/arm/dts/exynos4210-pinctrl-uboot.dtsi
Normal file
27
arch/arm/dts/exynos4210-pinctrl-uboot.dtsi
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* U-Boot additions to enable a generic Exynos GPIO driver
|
||||
*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*/
|
||||
|
||||
/{
|
||||
pinctrl_0: pinctrl@11400000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "samsung,exynos4210-pinctrl";
|
||||
};
|
||||
|
||||
pinctrl_1: pinctrl@11000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
gpy0: gpy0 {
|
||||
reg = <0xc00>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_2: pinctrl@03860000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
};
|
304
arch/arm/dts/exynos4210-pinctrl.dtsi
Normal file
304
arch/arm/dts/exynos4210-pinctrl.dtsi
Normal file
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* Samsung's Exynos4210 SoC pin-mux and pin-config device tree source
|
||||
*
|
||||
* Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
* Copyright (c) 2011-2012 Linaro Ltd.
|
||||
* www.linaro.org
|
||||
*
|
||||
* Samsung's Exynos4210 SoC pin-mux and pin-config optiosn are listed as device
|
||||
* tree nodes are listed in this file.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/ {
|
||||
pinctrl@11400000 {
|
||||
gpa0: gpa0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpa1: gpa1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb: gpb {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc0: gpc0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc1: gpc1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpd0: gpd0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpd1: gpd1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpe0: gpe0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpe1: gpe1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpe2: gpe2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpe3: gpe3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpe4: gpe4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf0: gpf0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf1: gpf1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf2: gpf2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf3: gpf3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@11000000 {
|
||||
gpj0: gpj0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpj1: gpj1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpk0: gpk0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpk1: gpk1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpk2: gpk2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpk3: gpk3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpl0: gpl0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpl1: gpl1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpl2: gpl2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpy0: gpy0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy1: gpy1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy2: gpy2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy3: gpy3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy4: gpy4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy5: gpy5 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy6: gpy6 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpx0: gpx0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
|
||||
<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx1: gpx1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
|
||||
<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx2: gpx2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx3: gpx3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@03860000 {
|
||||
gpz: gpz {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos4.dtsi"
|
||||
#include "exynos4.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Samsung SMDKV310 on Exynos4210";
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos4.dtsi"
|
||||
#include "exynos4210.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Samsung Trats based on Exynos4210";
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos4.dtsi"
|
||||
#include "exynos4210.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Samsung Universal C210 based on Exynos4210 rev0";
|
||||
|
@ -41,6 +41,19 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
soft-spi {
|
||||
compatible = "u-boot,soft-spi";
|
||||
cs-gpio = <&gpio 235 0>; /* Y43 */
|
||||
sclk-gpio = <&gpio 225 0>; /* Y31 */
|
||||
mosi-gpio = <&gpio 227 0>; /* Y33 */
|
||||
miso-gpio = <&gpio 224 0>; /* Y30 */
|
||||
spi-delay-us = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs@0 {
|
||||
};
|
||||
};
|
||||
|
||||
fimd@11c00000 {
|
||||
compatible = "samsung,exynos-fimd";
|
||||
reg = <0x11c00000 0xa4>;
|
||||
|
|
156
arch/arm/dts/exynos4210.dtsi
Normal file
156
arch/arm/dts/exynos4210.dtsi
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Samsung's Exynos4210 SoC device tree source
|
||||
*
|
||||
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
* Copyright (c) 2010-2011 Linaro Ltd.
|
||||
* www.linaro.org
|
||||
*
|
||||
* Samsung's Exynos4210 SoC device nodes are listed in this file. Exynos4210
|
||||
* based board files can include this file and provide values for board specfic
|
||||
* bindings.
|
||||
*
|
||||
* Note: This file does not include device nodes for all the controllers in
|
||||
* Exynos4210 SoC. As device tree coverage for Exynos4210 increases, additional
|
||||
* nodes can be added to this file.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "exynos4.dtsi"
|
||||
#include "exynos4210-pinctrl.dtsi"
|
||||
#include "exynos4210-pinctrl-uboot.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "samsung,exynos4210";
|
||||
|
||||
aliases {
|
||||
pinctrl0 = &pinctrl_0;
|
||||
pinctrl1 = &pinctrl_1;
|
||||
pinctrl2 = &pinctrl_2;
|
||||
};
|
||||
|
||||
pd_lcd1: lcd1-power-domain@10023CA0 {
|
||||
compatible = "samsung,exynos4210-pd";
|
||||
reg = <0x10023CA0 0x20>;
|
||||
};
|
||||
|
||||
gic: interrupt-controller@10490000 {
|
||||
cpu-offset = <0x8000>;
|
||||
};
|
||||
|
||||
combiner: interrupt-controller@10440000 {
|
||||
samsung,combiner-nr = <16>;
|
||||
interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
|
||||
<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
|
||||
<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
|
||||
<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
|
||||
};
|
||||
|
||||
mct@10050000 {
|
||||
compatible = "samsung,exynos4210-mct";
|
||||
reg = <0x10050000 0x800>;
|
||||
interrupt-parent = <&mct_map>;
|
||||
interrupts = <0>, <1>, <2>, <3>, <4>, <5>;
|
||||
clocks = <&clock 3>, <&clock 344>;
|
||||
clock-names = "fin_pll", "mct";
|
||||
|
||||
mct_map: mct-map {
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = <0 &gic 0 57 0>,
|
||||
<1 &gic 0 69 0>,
|
||||
<2 &combiner 12 6>,
|
||||
<3 &combiner 12 7>,
|
||||
<4 &gic 0 42 0>,
|
||||
<5 &gic 0 48 0>;
|
||||
};
|
||||
};
|
||||
|
||||
clock: clock-controller@10030000 {
|
||||
compatible = "samsung,exynos4210-clock";
|
||||
reg = <0x10030000 0x20000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
pmu {
|
||||
compatible = "arm,cortex-a9-pmu";
|
||||
interrupt-parent = <&combiner>;
|
||||
interrupts = <2 2>, <3 2>;
|
||||
};
|
||||
|
||||
pinctrl_0: pinctrl@11400000 {
|
||||
compatible = "samsung,exynos4210-pinctrl";
|
||||
reg = <0x11400000 0x1000>;
|
||||
interrupts = <0 47 0>;
|
||||
};
|
||||
|
||||
pinctrl_1: pinctrl@11000000 {
|
||||
compatible = "samsung,exynos4210-pinctrl";
|
||||
reg = <0x11000000 0x1000>;
|
||||
interrupts = <0 46 0>;
|
||||
|
||||
wakup_eint: wakeup-interrupt-controller {
|
||||
compatible = "samsung,exynos4210-wakeup-eint";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 32 0>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_2: pinctrl@03860000 {
|
||||
compatible = "samsung,exynos4210-pinctrl";
|
||||
reg = <0x03860000 0x1000>;
|
||||
};
|
||||
|
||||
tmu@100C0000 {
|
||||
compatible = "samsung,exynos4210-tmu";
|
||||
interrupt-parent = <&combiner>;
|
||||
reg = <0x100C0000 0x100>;
|
||||
interrupts = <2 4>;
|
||||
clocks = <&clock 383>;
|
||||
clock-names = "tmu_apbif";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
g2d@12800000 {
|
||||
compatible = "samsung,s5pv210-g2d";
|
||||
reg = <0x12800000 0x1000>;
|
||||
interrupts = <0 89 0>;
|
||||
clocks = <&clock 177>, <&clock 277>;
|
||||
clock-names = "sclk_fimg2d", "fimg2d";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
camera {
|
||||
clocks = <&clock 132>, <&clock 133>, <&clock 351>, <&clock 352>;
|
||||
clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0", "pxl_async1";
|
||||
|
||||
fimc_0: fimc@11800000 {
|
||||
samsung,pix-limits = <4224 8192 1920 4224>;
|
||||
samsung,mainscaler-ext;
|
||||
samsung,cam-if;
|
||||
};
|
||||
|
||||
fimc_1: fimc@11810000 {
|
||||
samsung,pix-limits = <4224 8192 1920 4224>;
|
||||
samsung,mainscaler-ext;
|
||||
samsung,cam-if;
|
||||
};
|
||||
|
||||
fimc_2: fimc@11820000 {
|
||||
samsung,pix-limits = <4224 8192 1920 4224>;
|
||||
samsung,mainscaler-ext;
|
||||
samsung,lcd-wb;
|
||||
};
|
||||
|
||||
fimc_3: fimc@11830000 {
|
||||
samsung,pix-limits = <1920 8192 1366 1920>;
|
||||
samsung,rotators = <0>;
|
||||
samsung,mainscaler-ext;
|
||||
samsung,lcd-wb;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos4.dtsi"
|
||||
#include "exynos4.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Odroid based on Exynos4412";
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos4.dtsi"
|
||||
#include "exynos4412.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Samsung Trats2 based on Exynos4412";
|
||||
|
|
38
arch/arm/dts/exynos4412.dtsi
Normal file
38
arch/arm/dts/exynos4412.dtsi
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Samsung's Exynos4412 SoC device tree source
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung's Exynos4412 SoC device nodes are listed in this file. Exynos4412
|
||||
* based board files can include this file and provide values for board specfic
|
||||
* bindings.
|
||||
*
|
||||
* Note: This file does not include device nodes for all the controllers in
|
||||
* Exynos4412 SoC. As device tree coverage for Exynos4412 increases, additional
|
||||
* nodes can be added to this file.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "exynos4x12.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "samsung,exynos4412";
|
||||
|
||||
gic: interrupt-controller@10490000 {
|
||||
cpu-offset = <0x4000>;
|
||||
};
|
||||
|
||||
interrupt-controller@10440000 {
|
||||
samsung,combiner-nr = <20>;
|
||||
interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
|
||||
<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
|
||||
<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
|
||||
<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
|
||||
<0 107 0>, <0 108 0>, <0 48 0>, <0 42 0>;
|
||||
};
|
||||
|
||||
};
|
46
arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi
Normal file
46
arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* U-Boot additions to enable a generic Exynos GPIO driver
|
||||
*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*/
|
||||
|
||||
/{
|
||||
pinctrl_0: pinctrl@11400000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
gpf0: gpf0 {
|
||||
reg = <0xc180>;
|
||||
};
|
||||
gpj0: gpj0 {
|
||||
reg = <0x240>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_1: pinctrl@11000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
gpk0: gpk0 {
|
||||
reg = <0x40>;
|
||||
};
|
||||
gpm0: gpm0 {
|
||||
reg = <0x260>;
|
||||
};
|
||||
gpy0: gpy0 {
|
||||
reg = <0x120>;
|
||||
};
|
||||
gpx0: gpx0 {
|
||||
reg = <0xc00>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_2: pinctrl@03860000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
pinctrl_3: pinctrl@106E0000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
};
|
344
arch/arm/dts/exynos4x12-pinctrl.dtsi
Normal file
344
arch/arm/dts/exynos4x12-pinctrl.dtsi
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* Samsung's Exynos4x12 SoCs pin-mux and pin-config device tree source
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung's Exynos4x12 SoCs pin-mux and pin-config optiosn are listed as device
|
||||
* tree nodes are listed in this file.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/ {
|
||||
pinctrl@11400000 {
|
||||
gpa0: gpa0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpa1: gpa1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb: gpb {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc0: gpc0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc1: gpc1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpd0: gpd0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpd1: gpd1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf0: gpf0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf1: gpf1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf2: gpf2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf3: gpf3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpj0: gpj0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpj1: gpj1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl@11000000 {
|
||||
gpk0: gpk0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpk1: gpk1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpk2: gpk2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpk3: gpk3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpl0: gpl0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpl1: gpl1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpl2: gpl2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpm0: gpm0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpm1: gpm1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpm2: gpm2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpm3: gpm3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpm4: gpm4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpy0: gpy0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy1: gpy1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy2: gpy2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy3: gpy3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy4: gpy4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy5: gpy5 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy6: gpy6 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpx0: gpx0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
|
||||
<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx1: gpx1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
|
||||
<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx2: gpx2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx3: gpx3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl@03860000 {
|
||||
gpz: gpz {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl@106E0000 {
|
||||
gpv0: gpv0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv1: gpv1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv2: gpv2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv3: gpv3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv4: gpv4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
||||
};
|
115
arch/arm/dts/exynos4x12.dtsi
Normal file
115
arch/arm/dts/exynos4x12.dtsi
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Samsung's Exynos4x12 SoCs device tree source
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung's Exynos4x12 SoCs device nodes are listed in this file. Exynos4x12
|
||||
* based board files can include this file and provide values for board specfic
|
||||
* bindings.
|
||||
*
|
||||
* Note: This file does not include device nodes for all the controllers in
|
||||
* Exynos4x12 SoC. As device tree coverage for Exynos4x12 increases, additional
|
||||
* nodes can be added to this file.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
` * published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "exynos4.dtsi"
|
||||
#include "exynos4x12-pinctrl.dtsi"
|
||||
#include "exynos4x12-pinctrl-uboot.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
pinctrl0 = &pinctrl_0;
|
||||
pinctrl1 = &pinctrl_1;
|
||||
pinctrl2 = &pinctrl_2;
|
||||
pinctrl3 = &pinctrl_3;
|
||||
mshc0 = &mshc_0;
|
||||
};
|
||||
|
||||
pd_isp: isp-power-domain@10023CA0 {
|
||||
compatible = "samsung,exynos4210-pd";
|
||||
reg = <0x10023CA0 0x20>;
|
||||
};
|
||||
|
||||
clock: clock-controller@10030000 {
|
||||
compatible = "samsung,exynos4412-clock";
|
||||
reg = <0x10030000 0x20000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
mct@10050000 {
|
||||
compatible = "samsung,exynos4412-mct";
|
||||
reg = <0x10050000 0x800>;
|
||||
interrupt-parent = <&mct_map>;
|
||||
interrupts = <0>, <1>, <2>, <3>, <4>;
|
||||
clocks = <&clock 3>, <&clock 344>;
|
||||
clock-names = "fin_pll", "mct";
|
||||
|
||||
mct_map: mct-map {
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = <0 &gic 0 57 0>,
|
||||
<1 &combiner 12 5>,
|
||||
<2 &combiner 12 6>,
|
||||
<3 &combiner 12 7>,
|
||||
<4 &gic 1 12 0>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_0: pinctrl@11400000 {
|
||||
compatible = "samsung,exynos4x12-pinctrl";
|
||||
reg = <0x11400000 0x1000>;
|
||||
interrupts = <0 47 0>;
|
||||
};
|
||||
|
||||
pinctrl_1: pinctrl@11000000 {
|
||||
compatible = "samsung,exynos4x12-pinctrl";
|
||||
reg = <0x11000000 0x1000>;
|
||||
interrupts = <0 46 0>;
|
||||
|
||||
wakup_eint: wakeup-interrupt-controller {
|
||||
compatible = "samsung,exynos4210-wakeup-eint";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 32 0>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_2: pinctrl@03860000 {
|
||||
compatible = "samsung,exynos4x12-pinctrl";
|
||||
reg = <0x03860000 0x1000>;
|
||||
interrupt-parent = <&combiner>;
|
||||
interrupts = <10 0>;
|
||||
};
|
||||
|
||||
pinctrl_3: pinctrl@106E0000 {
|
||||
compatible = "samsung,exynos4x12-pinctrl";
|
||||
reg = <0x106E0000 0x1000>;
|
||||
interrupts = <0 72 0>;
|
||||
};
|
||||
|
||||
g2d@10800000 {
|
||||
compatible = "samsung,exynos4212-g2d";
|
||||
reg = <0x10800000 0x1000>;
|
||||
interrupts = <0 89 0>;
|
||||
clocks = <&clock 177>, <&clock 277>;
|
||||
clock-names = "sclk_fimg2d", "fimg2d";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
mshc_0: mmc@12550000 {
|
||||
compatible = "samsung,exynos4412-dw-mshc";
|
||||
reg = <0x12550000 0x1000>;
|
||||
interrupts = <0 77 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
fifo-depth = <0x80>;
|
||||
clocks = <&clock 301>, <&clock 149>;
|
||||
clock-names = "biu", "ciu";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
|
@ -5,11 +5,38 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/include/ "skeleton.dtsi"
|
||||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "samsung,exynos5";
|
||||
|
||||
combiner: interrupt-controller@10440000 {
|
||||
compatible = "samsung,exynos4210-combiner";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
samsung,combiner-nr = <32>;
|
||||
reg = <0x10440000 0x1000>;
|
||||
interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
|
||||
<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
|
||||
<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
|
||||
<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
|
||||
<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
|
||||
<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
|
||||
<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
|
||||
<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
|
||||
};
|
||||
|
||||
gic: interrupt-controller@10481000 {
|
||||
compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
|
||||
#interrupt-cells = <3>;
|
||||
interrupt-controller;
|
||||
reg = <0x10481000 0x1000>,
|
||||
<0x10482000 0x1000>,
|
||||
<0x10484000 0x2000>,
|
||||
<0x10486000 0x2000>;
|
||||
interrupts = <1 9 0xf04>;
|
||||
};
|
||||
|
||||
sromc@12250000 {
|
||||
compatible = "samsung,exynos-sromc";
|
||||
reg = <0x12250000 0x20>;
|
||||
|
@ -17,6 +44,33 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
combiner: interrupt-controller@10440000 {
|
||||
compatible = "samsung,exynos4210-combiner";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
samsung,combiner-nr = <32>;
|
||||
reg = <0x10440000 0x1000>;
|
||||
interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
|
||||
<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
|
||||
<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
|
||||
<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
|
||||
<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
|
||||
<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
|
||||
<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
|
||||
<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
|
||||
};
|
||||
|
||||
gic: interrupt-controller@10481000 {
|
||||
compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
|
||||
#interrupt-cells = <3>;
|
||||
interrupt-controller;
|
||||
reg = <0x10481000 0x1000>,
|
||||
<0x10482000 0x1000>,
|
||||
<0x10484000 0x2000>,
|
||||
<0x10486000 0x2000>;
|
||||
interrupts = <1 9 0xf04>;
|
||||
};
|
||||
|
||||
i2c@12c60000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -190,6 +244,7 @@
|
|||
compatible = "samsung,exynos4210-uart";
|
||||
reg = <0x12C30000 0x100>;
|
||||
interrupts = <0 54 0>;
|
||||
u-boot,dm-pre-reloc;
|
||||
id = <3>;
|
||||
};
|
||||
|
||||
|
|
40
arch/arm/dts/exynos5250-pinctrl-uboot.dtsi
Normal file
40
arch/arm/dts/exynos5250-pinctrl-uboot.dtsi
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* U-Boot additions to enable a generic Exynos GPIO driver
|
||||
*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*/
|
||||
|
||||
/{
|
||||
pinctrl_0: pinctrl@11400000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
gpc4: gpc4 {
|
||||
reg = <0x2e0>;
|
||||
};
|
||||
gpx0: gpx0 {
|
||||
reg = <0xc00>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_1: pinctrl@13400000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
pinctrl_2: pinctrl@10d10000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
gpv2: gpv2 {
|
||||
reg = <0x060>;
|
||||
};
|
||||
gpv4: gpv4 {
|
||||
reg = <0xc0>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_3: pinctrl@03860000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
};
|
331
arch/arm/dts/exynos5250-pinctrl.dtsi
Normal file
331
arch/arm/dts/exynos5250-pinctrl.dtsi
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Samsung's Exynos5250 SoC pin-mux and pin-config device tree source
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung's Exynos5250 SoC pin-mux and pin-config optiosn are listed as device
|
||||
* tree nodes are listed in this file.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/ {
|
||||
pinctrl@11400000 {
|
||||
gpa0: gpa0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpa1: gpa1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpa2: gpa2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb0: gpb0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb1: gpb1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb2: gpb2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb3: gpb3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc0: gpc0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc1: gpc1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc2: gpc2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc3: gpc3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpd0: gpd0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpd1: gpd1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpy0: gpy0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy1: gpy1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy2: gpy2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy3: gpy3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy4: gpy4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy5: gpy5 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy6: gpy6 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpc4: gpc4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx0: gpx0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&combiner>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <23 0>, <24 0>, <25 0>, <25 1>,
|
||||
<26 0>, <26 1>, <27 0>, <27 1>;
|
||||
};
|
||||
|
||||
gpx1: gpx1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&combiner>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <28 0>, <28 1>, <29 0>, <29 1>,
|
||||
<30 0>, <30 1>, <31 0>, <31 1>;
|
||||
};
|
||||
|
||||
gpx2: gpx2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx3: gpx3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl@13400000 {
|
||||
gpe0: gpe0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpe1: gpe1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf0: gpf0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf1: gpf1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpg0: gpg0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpg1: gpg1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpg2: gpg2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gph0: gph0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gph1: gph1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@10d10000 {
|
||||
gpv0: gpv0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv1: gpv1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv2: gpv2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv3: gpv3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpv4: gpv4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@03860000 {
|
||||
gpz: gpz {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos5250.dtsi"
|
||||
#include "exynos5250.dtsi"
|
||||
|
||||
/ {
|
||||
model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos5250.dtsi"
|
||||
#include "exynos5250.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Google Snow";
|
||||
|
@ -53,6 +53,14 @@
|
|||
};
|
||||
};
|
||||
|
||||
spi@12d30000 {
|
||||
spi-max-frequency = <50000000>;
|
||||
firmware_storage_spi: flash@0 {
|
||||
compatible = "spi-flash";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
spi@131b0000 {
|
||||
spi-max-frequency = <1000000>;
|
||||
spi-deactivate-delay = <100>;
|
||||
|
|
|
@ -5,9 +5,48 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/include/ "exynos5.dtsi"
|
||||
#include "exynos5.dtsi"
|
||||
#include "exynos5250-pinctrl.dtsi"
|
||||
#include "exynos5250-pinctrl-uboot.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
pinctrl0 = &pinctrl_0;
|
||||
pinctrl1 = &pinctrl_1;
|
||||
pinctrl2 = &pinctrl_2;
|
||||
pinctrl3 = &pinctrl_3;
|
||||
};
|
||||
|
||||
pinctrl_0: pinctrl@11400000 {
|
||||
compatible = "samsung,exynos5250-pinctrl";
|
||||
reg = <0x11400000 0x1000>;
|
||||
interrupts = <0 46 0>;
|
||||
|
||||
wakup_eint: wakeup-interrupt-controller {
|
||||
compatible = "samsung,exynos4210-wakeup-eint";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 32 0>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_1: pinctrl@13400000 {
|
||||
compatible = "samsung,exynos5250-pinctrl";
|
||||
reg = <0x13400000 0x1000>;
|
||||
interrupts = <0 45 0>;
|
||||
};
|
||||
|
||||
pinctrl_2: pinctrl@10d10000 {
|
||||
compatible = "samsung,exynos5250-pinctrl";
|
||||
reg = <0x10d10000 0x1000>;
|
||||
interrupts = <0 50 0>;
|
||||
};
|
||||
|
||||
pinctrl_3: pinctrl@03860000 {
|
||||
compatible = "samsung,exynos5250-pinctrl";
|
||||
reg = <0x03860000 0x1000>;
|
||||
interrupts = <0 47 0>;
|
||||
};
|
||||
|
||||
i2c@12ca0000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos54xx.dtsi"
|
||||
#include "exynos54xx.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Samsung/Google Peach Pit board based on Exynos5420";
|
||||
|
@ -140,6 +140,7 @@
|
|||
spi@12d30000 { /* spi1 */
|
||||
spi-max-frequency = <50000000>;
|
||||
firmware_storage_spi: flash@0 {
|
||||
compatible = "spi-flash";
|
||||
reg = <0>;
|
||||
|
||||
/*
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "exynos54xx.dtsi"
|
||||
#include "exynos54xx.dtsi"
|
||||
|
||||
/ {
|
||||
model = "SAMSUNG SMDK5420 board based on EXYNOS5420";
|
||||
|
|
40
arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi
Normal file
40
arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* U-Boot additions to enable a generic Exynos GPIO driver
|
||||
*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*/
|
||||
|
||||
/{
|
||||
/*
|
||||
* Replicate the ordering of arch/arm/include/asm/arch-exynos/gpio.h
|
||||
* TODO(sjg@chromium.org): This ordering ceases to matter once GPIO
|
||||
* numbers are not needed in U-Boot for exynos.
|
||||
*/
|
||||
pinctrl@14010000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
pinctrl@13400000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
gpy7 {
|
||||
};
|
||||
|
||||
gpx0 {
|
||||
reg = <0xc00>;
|
||||
};
|
||||
};
|
||||
pinctrl@13410000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
pinctrl@14000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
pinctrl@03860000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
};
|
305
arch/arm/dts/exynos54xx-pinctrl.dtsi
Normal file
305
arch/arm/dts/exynos54xx-pinctrl.dtsi
Normal file
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* Samsung's Exynos5420 SoC pin-mux and pin-config device tree source
|
||||
*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung's Exynos5420 SoC pin-mux and pin-config options are listed as device
|
||||
* tree nodes are listed in this file.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "exynos54xx-pinctrl-uboot.dtsi"
|
||||
|
||||
/ {
|
||||
pinctrl@13400000 {
|
||||
gpy7: gpy7 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx0: gpx0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&combiner>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <23 0>, <24 0>, <25 0>, <25 1>,
|
||||
<26 0>, <26 1>, <27 0>, <27 1>;
|
||||
};
|
||||
|
||||
gpx1: gpx1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
interrupt-parent = <&combiner>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <28 0>, <28 1>, <29 0>, <29 1>,
|
||||
<30 0>, <30 1>, <31 0>, <31 1>;
|
||||
};
|
||||
|
||||
gpx2: gpx2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpx3: gpx3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@13410000 {
|
||||
gpc0: gpc0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc1: gpc1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc2: gpc2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc3: gpc3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpc4: gpc4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpd1: gpd1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpy0: gpy0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy1: gpy1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy2: gpy2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy3: gpy3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy4: gpy4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy5: gpy5 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpy6: gpy6 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@14000000 {
|
||||
gpe0: gpe0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpe1: gpe1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf0: gpf0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpf1: gpf1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpg0: gpg0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpg1: gpg1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpg2: gpg2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpj4: gpj4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@14010000 {
|
||||
gpa0: gpa0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpa1: gpa1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpa2: gpa2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb0: gpb0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb1: gpb1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb2: gpb2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb3: gpb3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gpb4: gpb4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gph0: gph0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinctrl@03860000 {
|
||||
gpz: gpz {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
|
@ -5,7 +5,8 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/include/ "exynos5.dtsi"
|
||||
#include "exynos5.dtsi"
|
||||
#include "exynos54xx-pinctrl.dtsi"
|
||||
|
||||
/ {
|
||||
config {
|
||||
|
@ -24,6 +25,11 @@
|
|||
i2c8 = "/i2c@12e00000";
|
||||
i2c9 = "/i2c@12e10000";
|
||||
i2c10 = "/i2c@12e20000";
|
||||
pinctrl0 = &pinctrl_0;
|
||||
pinctrl1 = &pinctrl_1;
|
||||
pinctrl2 = &pinctrl_2;
|
||||
pinctrl3 = &pinctrl_3;
|
||||
pinctrl4 = &pinctrl_4;
|
||||
spi0 = "/spi@12d20000";
|
||||
spi1 = "/spi@12d30000";
|
||||
spi2 = "/spi@12d40000";
|
||||
|
@ -123,6 +129,42 @@
|
|||
reg = <0x14680000 0x100>;
|
||||
};
|
||||
|
||||
pinctrl_0: pinctrl@13400000 {
|
||||
compatible = "samsung,exynos5420-pinctrl";
|
||||
reg = <0x13400000 0x1000>;
|
||||
interrupts = <0 45 0>;
|
||||
|
||||
wakeup-interrupt-controller {
|
||||
compatible = "samsung,exynos4210-wakeup-eint";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 32 0>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_1: pinctrl@13410000 {
|
||||
compatible = "samsung,exynos5420-pinctrl";
|
||||
reg = <0x13410000 0x1000>;
|
||||
interrupts = <0 78 0>;
|
||||
};
|
||||
|
||||
pinctrl_2: pinctrl@14000000 {
|
||||
compatible = "samsung,exynos5420-pinctrl";
|
||||
reg = <0x14000000 0x1000>;
|
||||
interrupts = <0 46 0>;
|
||||
};
|
||||
|
||||
pinctrl_3: pinctrl@14010000 {
|
||||
compatible = "samsung,exynos5420-pinctrl";
|
||||
reg = <0x14010000 0x1000>;
|
||||
interrupts = <0 50 0>;
|
||||
};
|
||||
|
||||
pinctrl_4: pinctrl@03860000 {
|
||||
compatible = "samsung,exynos5420-pinctrl";
|
||||
reg = <0x03860000 0x1000>;
|
||||
interrupts = <0 47 0>;
|
||||
};
|
||||
|
||||
fimd@14400000 {
|
||||
/* sysmmu is not used in U-Boot */
|
||||
samsung,disable-sysmmu;
|
||||
|
|
180
arch/arm/dts/s5pc100-pinctrl.dtsi
Normal file
180
arch/arm/dts/s5pc100-pinctrl.dtsi
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* U-Boot additions to enable a generic Exynos GPIO driver
|
||||
*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*/
|
||||
|
||||
/ {
|
||||
pinctrl@e0300000 {
|
||||
gpa0: gpa0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpa1: gpa1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpb: gpb {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpc: gpc {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpd: gpd {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpe0: gpe0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpe1: gpe1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf0: gpf0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf1: gpf1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf2: gpf2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf3: gpf3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg0: gpg0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg1: gpg1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg2: gpg2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg3: gpg3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpi: gpi {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj0: gpj0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj1: gpj1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj2: gpj2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj3: gpj3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj4: gpj4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpk0: gpk0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpk1: gpk1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpk2: gpk2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpk3: gpk3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpl0: gpl0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpl1: gpl1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpl2: gpl2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpl3: gpl3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpl4: gpl4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph0: gph0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph1: gph1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph2: gph2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph3: gph3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
273
arch/arm/dts/s5pc110-pinctrl.dtsi
Normal file
273
arch/arm/dts/s5pc110-pinctrl.dtsi
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* U-Boot additions to enable a generic Exynos GPIO driver
|
||||
*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*/
|
||||
|
||||
/ {
|
||||
pinctrl@e0200000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
gpa0: gpa0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpa1: gpa1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpb: gpb {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpc0: gpc0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpc1: gpc1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpd0: gpd0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpd1: gpd1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpe0: gpe0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpe1: gpe1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf0: gpf0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf1: gpf1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf2: gpf2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpf3: gpf3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg0: gpg0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg1: gpg1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg2: gpg2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpg3: gpg3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpi: gpi {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj0: gpj0 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj1: gpj1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj2: gpj2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj3: gpj3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpj4: gpj4 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp01: gpmp01 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp02: gpmp02 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp03: gpmp03 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp04: gpmp04 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp05: gpmp05 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp06: gpmp06 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp07: gpmp07 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp10: gpmp10 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp11: gpmp11 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp12: gpmp12 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp13: gpmp13 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp14: gpmp14 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp15: gpmp15 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp16: gpmp16 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp17: gpmp17 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp18: gpmp18 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp20: gpmp20 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp21: gpmp21 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp22: gpmp22 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp23: gpmp23 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp24: gpmp24 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp25: gpmp25 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp26: gpmp26 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp27: gpmp27 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpmp28: gpmp28 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph0: gph0 {
|
||||
reg = <0xc00>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph1: gph1 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph2: gph2 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gph3: gph3 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
|
@ -9,6 +9,7 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "skeleton.dtsi"
|
||||
#include "s5pc110-pinctrl.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Samsung Goni based on S5PC110";
|
||||
|
@ -17,6 +18,12 @@
|
|||
aliases {
|
||||
serial2 = "/serial@e2900800";
|
||||
console = "/serial@e2900800";
|
||||
pinctrl0 = &pinctrl0;
|
||||
};
|
||||
|
||||
pinctrl0: pinctrl@e0200000 {
|
||||
compatible = "samsung,s5pc110-pinctrl";
|
||||
reg = <0xe0200000 0x1000>;
|
||||
};
|
||||
|
||||
serial@e2900800 {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "skeleton.dtsi"
|
||||
#include "s5pc100-pinctrl.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Samsung SMDKC100 based on S5PC100";
|
||||
|
@ -17,6 +18,12 @@
|
|||
aliases {
|
||||
serial0 = "/serial@ec000000";
|
||||
console = "/serial@ec000000";
|
||||
pinctrl0 = &pinctrl0;
|
||||
};
|
||||
|
||||
pinctrl0: pinctrl@e0300000 {
|
||||
compatible = "samsung,s5pc100-pinctrl";
|
||||
reg = <0xe0200000 0x1000>;
|
||||
};
|
||||
|
||||
serial@ec000000 {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
usb1 = "/usb@c5000000";
|
||||
sdhci0 = "/sdhci@c8000600";
|
||||
sdhci1 = "/sdhci@c8000000";
|
||||
spi0 = "/spi@7000c380";
|
||||
};
|
||||
|
||||
memory {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
i2c4 = "/i2c@7000c700";
|
||||
sdhci0 = "/sdhci@78000600";
|
||||
sdhci1 = "/sdhci@78000000";
|
||||
spi0 = "/spi@7000da00";
|
||||
usb0 = "/usb@7d000000";
|
||||
usb1 = "/usb@7d008000";
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
i2c4 = "/i2c@7000c700";
|
||||
sdhci0 = "/sdhci@78000600";
|
||||
sdhci1 = "/sdhci@78000000";
|
||||
spi0 = "/spi@7000da00";
|
||||
usb0 = "/usb@7d008000";
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
i2c2 = "/i2c@7000c700";
|
||||
sdhci0 = "/sdhci@78000600";
|
||||
sdhci1 = "/sdhci@78000200";
|
||||
spi0 = "/spi@7000d400";
|
||||
usb0 = "/usb@7d000000";
|
||||
usb1 = "/usb@7d004000"; /* on module only, for ASIX */
|
||||
usb2 = "/usb@7d008000";
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/errno.h>
|
||||
|
@ -69,15 +70,53 @@ static void * const i2c_bases[] = {
|
|||
};
|
||||
|
||||
/* i2c_index can be from 0 - 2 */
|
||||
void setup_i2c(unsigned i2c_index, int speed, int slave_addr,
|
||||
struct i2c_pads_info *p)
|
||||
int setup_i2c(unsigned i2c_index, int speed, int slave_addr,
|
||||
struct i2c_pads_info *p)
|
||||
{
|
||||
char *name1, *name2;
|
||||
int ret;
|
||||
|
||||
if (i2c_index >= ARRAY_SIZE(i2c_bases))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
name1 = malloc(9);
|
||||
name2 = malloc(9);
|
||||
if (!name1 || !name2)
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(name1, "i2c_sda%d", i2c_index);
|
||||
sprintf(name2, "i2c_scl%d", i2c_index);
|
||||
ret = gpio_request(p->sda.gp, name1);
|
||||
if (ret)
|
||||
goto err_req1;
|
||||
|
||||
ret = gpio_request(p->scl.gp, name2);
|
||||
if (ret)
|
||||
goto err_req2;
|
||||
|
||||
/* Enable i2c clock */
|
||||
enable_i2c_clk(1, i2c_index);
|
||||
ret = enable_i2c_clk(1, i2c_index);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
/* Make sure bus is idle */
|
||||
force_idle_bus(p);
|
||||
ret = force_idle_bus(p);
|
||||
if (ret)
|
||||
goto err_idle;
|
||||
|
||||
bus_i2c_init(i2c_bases[i2c_index], speed, slave_addr,
|
||||
force_idle_bus, p);
|
||||
|
||||
return 0;
|
||||
|
||||
err_idle:
|
||||
err_clk:
|
||||
gpio_free(p->scl.gp);
|
||||
err_req2:
|
||||
gpio_free(p->sda.gp);
|
||||
err_req1:
|
||||
free(name1);
|
||||
free(name2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -52,4 +52,13 @@ struct bcm2835_gpio_regs {
|
|||
u32 gppudclk[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bcm2835_gpio_platdata - GPIO platform description
|
||||
*
|
||||
* @base: Base address of GPIO controller
|
||||
*/
|
||||
struct bcm2835_gpio_platdata {
|
||||
unsigned long base;
|
||||
};
|
||||
|
||||
#endif /* _BCM2835_GPIO_H_ */
|
||||
|
|
|
@ -284,7 +284,7 @@ enum exynos4_gpio_pin {
|
|||
EXYNOS4_GPIO_Y65,
|
||||
EXYNOS4_GPIO_Y66,
|
||||
EXYNOS4_GPIO_Y67,
|
||||
EXYNOS4_GPIO_X00 = 896, /* 896 0x380 */
|
||||
EXYNOS4_GPIO_X00, /* 256 0x100 */
|
||||
EXYNOS4_GPIO_X01,
|
||||
EXYNOS4_GPIO_X02,
|
||||
EXYNOS4_GPIO_X03,
|
||||
|
@ -292,7 +292,7 @@ enum exynos4_gpio_pin {
|
|||
EXYNOS4_GPIO_X05,
|
||||
EXYNOS4_GPIO_X06,
|
||||
EXYNOS4_GPIO_X07,
|
||||
EXYNOS4_GPIO_X10, /* 904 0x388 */
|
||||
EXYNOS4_GPIO_X10, /* 264 0x108 */
|
||||
EXYNOS4_GPIO_X11,
|
||||
EXYNOS4_GPIO_X12,
|
||||
EXYNOS4_GPIO_X13,
|
||||
|
@ -300,7 +300,7 @@ enum exynos4_gpio_pin {
|
|||
EXYNOS4_GPIO_X15,
|
||||
EXYNOS4_GPIO_X16,
|
||||
EXYNOS4_GPIO_X17,
|
||||
EXYNOS4_GPIO_X20, /* 912 0x390 */
|
||||
EXYNOS4_GPIO_X20, /* 272 0x110 */
|
||||
EXYNOS4_GPIO_X21,
|
||||
EXYNOS4_GPIO_X22,
|
||||
EXYNOS4_GPIO_X23,
|
||||
|
@ -308,7 +308,7 @@ enum exynos4_gpio_pin {
|
|||
EXYNOS4_GPIO_X25,
|
||||
EXYNOS4_GPIO_X26,
|
||||
EXYNOS4_GPIO_X27,
|
||||
EXYNOS4_GPIO_X30, /* 920 0x398 */
|
||||
EXYNOS4_GPIO_X30, /* 280 0x118 */
|
||||
EXYNOS4_GPIO_X31,
|
||||
EXYNOS4_GPIO_X32,
|
||||
EXYNOS4_GPIO_X33,
|
||||
|
@ -318,7 +318,7 @@ enum exynos4_gpio_pin {
|
|||
EXYNOS4_GPIO_X37,
|
||||
|
||||
/* GPIO_PART3_STARTS */
|
||||
EXYNOS4_GPIO_MAX_PORT_PART_2, /* 928 0x3A0 */
|
||||
EXYNOS4_GPIO_MAX_PORT_PART_2, /* 288 0x120 */
|
||||
EXYNOS4_GPIO_Z0 = EXYNOS4_GPIO_MAX_PORT_PART_2,
|
||||
EXYNOS4_GPIO_Z1,
|
||||
EXYNOS4_GPIO_Z2,
|
||||
|
@ -389,7 +389,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_D15,
|
||||
EXYNOS4X12_GPIO_D16,
|
||||
EXYNOS4X12_GPIO_D17,
|
||||
EXYNOS4X12_GPIO_F00 = 96, /* 96 0x60 */
|
||||
EXYNOS4X12_GPIO_F00, /* 56 0x38 */
|
||||
EXYNOS4X12_GPIO_F01,
|
||||
EXYNOS4X12_GPIO_F02,
|
||||
EXYNOS4X12_GPIO_F03,
|
||||
|
@ -397,7 +397,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_F05,
|
||||
EXYNOS4X12_GPIO_F06,
|
||||
EXYNOS4X12_GPIO_F07,
|
||||
EXYNOS4X12_GPIO_F10, /* 104 0x68 */
|
||||
EXYNOS4X12_GPIO_F10, /* 64 0x40 */
|
||||
EXYNOS4X12_GPIO_F11,
|
||||
EXYNOS4X12_GPIO_F12,
|
||||
EXYNOS4X12_GPIO_F13,
|
||||
|
@ -405,7 +405,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_F15,
|
||||
EXYNOS4X12_GPIO_F16,
|
||||
EXYNOS4X12_GPIO_F17,
|
||||
EXYNOS4X12_GPIO_F20, /* 112 0x70 */
|
||||
EXYNOS4X12_GPIO_F20, /* 72 0x48 */
|
||||
EXYNOS4X12_GPIO_F21,
|
||||
EXYNOS4X12_GPIO_F22,
|
||||
EXYNOS4X12_GPIO_F23,
|
||||
|
@ -413,7 +413,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_F25,
|
||||
EXYNOS4X12_GPIO_F26,
|
||||
EXYNOS4X12_GPIO_F27,
|
||||
EXYNOS4X12_GPIO_F30, /* 120 0x78 */
|
||||
EXYNOS4X12_GPIO_F30, /* 80 0x50 */
|
||||
EXYNOS4X12_GPIO_F31,
|
||||
EXYNOS4X12_GPIO_F32,
|
||||
EXYNOS4X12_GPIO_F33,
|
||||
|
@ -421,7 +421,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_F35,
|
||||
EXYNOS4X12_GPIO_F36,
|
||||
EXYNOS4X12_GPIO_F37,
|
||||
EXYNOS4X12_GPIO_J00 = 144, /* 144 0x90 */
|
||||
EXYNOS4X12_GPIO_J00, /* 88 0x58 */
|
||||
EXYNOS4X12_GPIO_J01,
|
||||
EXYNOS4X12_GPIO_J02,
|
||||
EXYNOS4X12_GPIO_J03,
|
||||
|
@ -429,7 +429,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_J05,
|
||||
EXYNOS4X12_GPIO_J06,
|
||||
EXYNOS4X12_GPIO_J07,
|
||||
EXYNOS4X12_GPIO_J10, /* 152 0x98 */
|
||||
EXYNOS4X12_GPIO_J10, /* 96 0x60 */
|
||||
EXYNOS4X12_GPIO_J11,
|
||||
EXYNOS4X12_GPIO_J12,
|
||||
EXYNOS4X12_GPIO_J13,
|
||||
|
@ -439,8 +439,8 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_J17,
|
||||
|
||||
/* GPIO_PART2_STARTS */
|
||||
EXYNOS4X12_GPIO_MAX_PORT_PART_1,/* 160 0xA0 */
|
||||
EXYNOS4X12_GPIO_K00 = 176, /* 176 0xB0 */
|
||||
EXYNOS4X12_GPIO_MAX_PORT_PART_1,/* 104 0x66 */
|
||||
EXYNOS4X12_GPIO_K00 = EXYNOS4X12_GPIO_MAX_PORT_PART_1,
|
||||
EXYNOS4X12_GPIO_K01,
|
||||
EXYNOS4X12_GPIO_K02,
|
||||
EXYNOS4X12_GPIO_K03,
|
||||
|
@ -448,7 +448,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_K05,
|
||||
EXYNOS4X12_GPIO_K06,
|
||||
EXYNOS4X12_GPIO_K07,
|
||||
EXYNOS4X12_GPIO_K10, /* 184 0xB8 */
|
||||
EXYNOS4X12_GPIO_K10, /* 112 0x70 */
|
||||
EXYNOS4X12_GPIO_K11,
|
||||
EXYNOS4X12_GPIO_K12,
|
||||
EXYNOS4X12_GPIO_K13,
|
||||
|
@ -456,7 +456,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_K15,
|
||||
EXYNOS4X12_GPIO_K16,
|
||||
EXYNOS4X12_GPIO_K17,
|
||||
EXYNOS4X12_GPIO_K20, /* 192 0xC0 */
|
||||
EXYNOS4X12_GPIO_K20, /* 120 0x78 */
|
||||
EXYNOS4X12_GPIO_K21,
|
||||
EXYNOS4X12_GPIO_K22,
|
||||
EXYNOS4X12_GPIO_K23,
|
||||
|
@ -464,7 +464,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_K25,
|
||||
EXYNOS4X12_GPIO_K26,
|
||||
EXYNOS4X12_GPIO_K27,
|
||||
EXYNOS4X12_GPIO_K30, /* 200 0xC8 */
|
||||
EXYNOS4X12_GPIO_K30, /* 128 0x80 */
|
||||
EXYNOS4X12_GPIO_K31,
|
||||
EXYNOS4X12_GPIO_K32,
|
||||
EXYNOS4X12_GPIO_K33,
|
||||
|
@ -472,7 +472,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_K35,
|
||||
EXYNOS4X12_GPIO_K36,
|
||||
EXYNOS4X12_GPIO_K37,
|
||||
EXYNOS4X12_GPIO_L00, /* 208 0xD0 */
|
||||
EXYNOS4X12_GPIO_L00, /* 136 0x88 */
|
||||
EXYNOS4X12_GPIO_L01,
|
||||
EXYNOS4X12_GPIO_L02,
|
||||
EXYNOS4X12_GPIO_L03,
|
||||
|
@ -480,7 +480,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_L05,
|
||||
EXYNOS4X12_GPIO_L06,
|
||||
EXYNOS4X12_GPIO_L07,
|
||||
EXYNOS4X12_GPIO_L10, /* 216 0xD8 */
|
||||
EXYNOS4X12_GPIO_L10, /* 144 0x90 */
|
||||
EXYNOS4X12_GPIO_L11,
|
||||
EXYNOS4X12_GPIO_L12,
|
||||
EXYNOS4X12_GPIO_L13,
|
||||
|
@ -488,7 +488,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_L15,
|
||||
EXYNOS4X12_GPIO_L16,
|
||||
EXYNOS4X12_GPIO_L17,
|
||||
EXYNOS4X12_GPIO_L20, /* 224 0xE0 */
|
||||
EXYNOS4X12_GPIO_L20, /* 152 0x98 */
|
||||
EXYNOS4X12_GPIO_L21,
|
||||
EXYNOS4X12_GPIO_L22,
|
||||
EXYNOS4X12_GPIO_L23,
|
||||
|
@ -496,7 +496,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_L25,
|
||||
EXYNOS4X12_GPIO_L26,
|
||||
EXYNOS4X12_GPIO_L27,
|
||||
EXYNOS4X12_GPIO_Y00, /* 232 0xE8 */
|
||||
EXYNOS4X12_GPIO_Y00, /* 160 0xa0 */
|
||||
EXYNOS4X12_GPIO_Y01,
|
||||
EXYNOS4X12_GPIO_Y02,
|
||||
EXYNOS4X12_GPIO_Y03,
|
||||
|
@ -504,7 +504,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Y05,
|
||||
EXYNOS4X12_GPIO_Y06,
|
||||
EXYNOS4X12_GPIO_Y07,
|
||||
EXYNOS4X12_GPIO_Y10, /* 240 0xF0 */
|
||||
EXYNOS4X12_GPIO_Y10, /* 168 0xa8 */
|
||||
EXYNOS4X12_GPIO_Y11,
|
||||
EXYNOS4X12_GPIO_Y12,
|
||||
EXYNOS4X12_GPIO_Y13,
|
||||
|
@ -512,7 +512,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Y15,
|
||||
EXYNOS4X12_GPIO_Y16,
|
||||
EXYNOS4X12_GPIO_Y17,
|
||||
EXYNOS4X12_GPIO_Y20, /* 248 0xF8 */
|
||||
EXYNOS4X12_GPIO_Y20, /* 176 0xb0 */
|
||||
EXYNOS4X12_GPIO_Y21,
|
||||
EXYNOS4X12_GPIO_Y22,
|
||||
EXYNOS4X12_GPIO_Y23,
|
||||
|
@ -520,7 +520,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Y25,
|
||||
EXYNOS4X12_GPIO_Y26,
|
||||
EXYNOS4X12_GPIO_Y27,
|
||||
EXYNOS4X12_GPIO_Y30, /* 256 0x100 */
|
||||
EXYNOS4X12_GPIO_Y30, /* 184 0xb8 */
|
||||
EXYNOS4X12_GPIO_Y31,
|
||||
EXYNOS4X12_GPIO_Y32,
|
||||
EXYNOS4X12_GPIO_Y33,
|
||||
|
@ -528,7 +528,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Y35,
|
||||
EXYNOS4X12_GPIO_Y36,
|
||||
EXYNOS4X12_GPIO_Y37,
|
||||
EXYNOS4X12_GPIO_Y40, /* 264 0x108 */
|
||||
EXYNOS4X12_GPIO_Y40, /* 192 0xc0 */
|
||||
EXYNOS4X12_GPIO_Y41,
|
||||
EXYNOS4X12_GPIO_Y42,
|
||||
EXYNOS4X12_GPIO_Y43,
|
||||
|
@ -536,7 +536,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Y45,
|
||||
EXYNOS4X12_GPIO_Y46,
|
||||
EXYNOS4X12_GPIO_Y47,
|
||||
EXYNOS4X12_GPIO_Y50, /* 272 0x110 */
|
||||
EXYNOS4X12_GPIO_Y50, /* 200 0xc8 */
|
||||
EXYNOS4X12_GPIO_Y51,
|
||||
EXYNOS4X12_GPIO_Y52,
|
||||
EXYNOS4X12_GPIO_Y53,
|
||||
|
@ -544,7 +544,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Y55,
|
||||
EXYNOS4X12_GPIO_Y56,
|
||||
EXYNOS4X12_GPIO_Y57,
|
||||
EXYNOS4X12_GPIO_Y60, /* 280 0x118 */
|
||||
EXYNOS4X12_GPIO_Y60, /* 208 0xd0 */
|
||||
EXYNOS4X12_GPIO_Y61,
|
||||
EXYNOS4X12_GPIO_Y62,
|
||||
EXYNOS4X12_GPIO_Y63,
|
||||
|
@ -552,7 +552,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Y65,
|
||||
EXYNOS4X12_GPIO_Y66,
|
||||
EXYNOS4X12_GPIO_Y67,
|
||||
EXYNOS4X12_GPIO_M00 = 312, /* 312 0xF0 */
|
||||
EXYNOS4X12_GPIO_M00, /* 216 0xd8 */
|
||||
EXYNOS4X12_GPIO_M01,
|
||||
EXYNOS4X12_GPIO_M02,
|
||||
EXYNOS4X12_GPIO_M03,
|
||||
|
@ -560,7 +560,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_M05,
|
||||
EXYNOS4X12_GPIO_M06,
|
||||
EXYNOS4X12_GPIO_M07,
|
||||
EXYNOS4X12_GPIO_M10, /* 320 0xF8 */
|
||||
EXYNOS4X12_GPIO_M10, /* 224 0xe0 */
|
||||
EXYNOS4X12_GPIO_M11,
|
||||
EXYNOS4X12_GPIO_M12,
|
||||
EXYNOS4X12_GPIO_M13,
|
||||
|
@ -568,7 +568,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_M15,
|
||||
EXYNOS4X12_GPIO_M16,
|
||||
EXYNOS4X12_GPIO_M17,
|
||||
EXYNOS4X12_GPIO_M20, /* 328 0x100 */
|
||||
EXYNOS4X12_GPIO_M20, /* 232 0xe8 */
|
||||
EXYNOS4X12_GPIO_M21,
|
||||
EXYNOS4X12_GPIO_M22,
|
||||
EXYNOS4X12_GPIO_M23,
|
||||
|
@ -576,7 +576,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_M25,
|
||||
EXYNOS4X12_GPIO_M26,
|
||||
EXYNOS4X12_GPIO_M27,
|
||||
EXYNOS4X12_GPIO_M30, /* 336 0x108 */
|
||||
EXYNOS4X12_GPIO_M30, /* 240 0xf0 */
|
||||
EXYNOS4X12_GPIO_M31,
|
||||
EXYNOS4X12_GPIO_M32,
|
||||
EXYNOS4X12_GPIO_M33,
|
||||
|
@ -584,7 +584,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_M35,
|
||||
EXYNOS4X12_GPIO_M36,
|
||||
EXYNOS4X12_GPIO_M37,
|
||||
EXYNOS4X12_GPIO_M40, /* 344 0x110 */
|
||||
EXYNOS4X12_GPIO_M40, /* 248 0xf8 */
|
||||
EXYNOS4X12_GPIO_M41,
|
||||
EXYNOS4X12_GPIO_M42,
|
||||
EXYNOS4X12_GPIO_M43,
|
||||
|
@ -592,7 +592,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_M45,
|
||||
EXYNOS4X12_GPIO_M46,
|
||||
EXYNOS4X12_GPIO_M47,
|
||||
EXYNOS4X12_GPIO_X00 = 928, /* 928 0x3A0 */
|
||||
EXYNOS4X12_GPIO_X00, /* 256 0x100 */
|
||||
EXYNOS4X12_GPIO_X01,
|
||||
EXYNOS4X12_GPIO_X02,
|
||||
EXYNOS4X12_GPIO_X03,
|
||||
|
@ -600,7 +600,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_X05,
|
||||
EXYNOS4X12_GPIO_X06,
|
||||
EXYNOS4X12_GPIO_X07,
|
||||
EXYNOS4X12_GPIO_X10, /* 936 0x3A8 */
|
||||
EXYNOS4X12_GPIO_X10, /* 264 0x108 */
|
||||
EXYNOS4X12_GPIO_X11,
|
||||
EXYNOS4X12_GPIO_X12,
|
||||
EXYNOS4X12_GPIO_X13,
|
||||
|
@ -608,7 +608,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_X15,
|
||||
EXYNOS4X12_GPIO_X16,
|
||||
EXYNOS4X12_GPIO_X17,
|
||||
EXYNOS4X12_GPIO_X20, /* 944 0x3B0 */
|
||||
EXYNOS4X12_GPIO_X20, /* 272 0x110 */
|
||||
EXYNOS4X12_GPIO_X21,
|
||||
EXYNOS4X12_GPIO_X22,
|
||||
EXYNOS4X12_GPIO_X23,
|
||||
|
@ -616,7 +616,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_X25,
|
||||
EXYNOS4X12_GPIO_X26,
|
||||
EXYNOS4X12_GPIO_X27,
|
||||
EXYNOS4X12_GPIO_X30, /* 952 0x3B8 */
|
||||
EXYNOS4X12_GPIO_X30, /* 280 0x118 */
|
||||
EXYNOS4X12_GPIO_X31,
|
||||
EXYNOS4X12_GPIO_X32,
|
||||
EXYNOS4X12_GPIO_X33,
|
||||
|
@ -626,7 +626,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_X37,
|
||||
|
||||
/* GPIO_PART3_STARTS */
|
||||
EXYNOS4X12_GPIO_MAX_PORT_PART_2,/* 960 0x3C0 */
|
||||
EXYNOS4X12_GPIO_MAX_PORT_PART_2,/* 288 0x120 */
|
||||
EXYNOS4X12_GPIO_Z0 = EXYNOS4X12_GPIO_MAX_PORT_PART_2,
|
||||
EXYNOS4X12_GPIO_Z1,
|
||||
EXYNOS4X12_GPIO_Z2,
|
||||
|
@ -637,7 +637,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_Z7,
|
||||
|
||||
/* GPIO_PART4_STARTS */
|
||||
EXYNOS4X12_GPIO_MAX_PORT_PART_3,/* 968 0x3C8 */
|
||||
EXYNOS4X12_GPIO_MAX_PORT_PART_3,/* 296 0x128 */
|
||||
EXYNOS4X12_GPIO_V00 = EXYNOS4X12_GPIO_MAX_PORT_PART_3,
|
||||
EXYNOS4X12_GPIO_V01,
|
||||
EXYNOS4X12_GPIO_V02,
|
||||
|
@ -646,7 +646,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_V05,
|
||||
EXYNOS4X12_GPIO_V06,
|
||||
EXYNOS4X12_GPIO_V07,
|
||||
EXYNOS4X12_GPIO_V10, /* 976 0x3D0 */
|
||||
EXYNOS4X12_GPIO_V10, /* 304 0x130 */
|
||||
EXYNOS4X12_GPIO_V11,
|
||||
EXYNOS4X12_GPIO_V12,
|
||||
EXYNOS4X12_GPIO_V13,
|
||||
|
@ -654,7 +654,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_V15,
|
||||
EXYNOS4X12_GPIO_V16,
|
||||
EXYNOS4X12_GPIO_V17,
|
||||
EXYNOS4X12_GPIO_V20 = 992, /* 992 0x3E0 */
|
||||
EXYNOS4X12_GPIO_V20, /* 312 0x138 */
|
||||
EXYNOS4X12_GPIO_V21,
|
||||
EXYNOS4X12_GPIO_V22,
|
||||
EXYNOS4X12_GPIO_V23,
|
||||
|
@ -662,7 +662,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_V25,
|
||||
EXYNOS4X12_GPIO_V26,
|
||||
EXYNOS4X12_GPIO_V27,
|
||||
EXYNOS4X12_GPIO_V30 = 1000, /* 1000 0x3E8 */
|
||||
EXYNOS4X12_GPIO_V30, /* 320 0x140 */
|
||||
EXYNOS4X12_GPIO_V31,
|
||||
EXYNOS4X12_GPIO_V32,
|
||||
EXYNOS4X12_GPIO_V33,
|
||||
|
@ -670,7 +670,7 @@ enum exynos4X12_gpio_pin {
|
|||
EXYNOS4X12_GPIO_V35,
|
||||
EXYNOS4X12_GPIO_V36,
|
||||
EXYNOS4X12_GPIO_V37,
|
||||
EXYNOS4X12_GPIO_V40 = 1016, /* 1016 0x3F8 */
|
||||
EXYNOS4X12_GPIO_V40, /* 328 0x148 */
|
||||
EXYNOS4X12_GPIO_V41,
|
||||
EXYNOS4X12_GPIO_V42,
|
||||
EXYNOS4X12_GPIO_V43,
|
||||
|
@ -1504,12 +1504,7 @@ static const struct gpio_name_num_table exynos5420_gpio_table[] = {
|
|||
void gpio_cfg_pin(int gpio, int cfg);
|
||||
void gpio_set_pull(int gpio, int mode);
|
||||
void gpio_set_drv(int gpio, int mode);
|
||||
int gpio_direction_input(unsigned gpio);
|
||||
int gpio_direction_output(unsigned gpio, int value);
|
||||
int gpio_set_value(unsigned gpio, int value);
|
||||
int gpio_get_value(unsigned gpio);
|
||||
void gpio_set_rate(int gpio, int mode);
|
||||
struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio);
|
||||
int s5p_gpio_get_pin(unsigned gpio);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -682,8 +682,7 @@ enum s5pc110_gpio_pin {
|
|||
S5PC110_GPIO_MP285,
|
||||
S5PC110_GPIO_MP286,
|
||||
S5PC110_GPIO_MP287,
|
||||
S5PC110_GPIO_RES,
|
||||
S5PC110_GPIO_H00 = (S5PC110_GPIO_RES + (48 * 8)),
|
||||
S5PC110_GPIO_H00,
|
||||
S5PC110_GPIO_H01,
|
||||
S5PC110_GPIO_H02,
|
||||
S5PC110_GPIO_H03,
|
||||
|
@ -815,11 +814,7 @@ static const struct gpio_name_num_table s5pc110_gpio_table[] = {
|
|||
void gpio_cfg_pin(int gpio, int cfg);
|
||||
void gpio_set_pull(int gpio, int mode);
|
||||
void gpio_set_drv(int gpio, int mode);
|
||||
int gpio_direction_output(unsigned gpio, int value);
|
||||
int gpio_set_value(unsigned gpio, int value);
|
||||
int gpio_get_value(unsigned gpio);
|
||||
void gpio_set_rate(int gpio, int mode);
|
||||
struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio);
|
||||
int s5p_gpio_get_pin(unsigned gpio);
|
||||
|
||||
/* GPIO pins per bank */
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* NVIDIA Tegra SPI controller
|
||||
*
|
||||
* Copyright 2010-2013 NVIDIA Corporation
|
||||
*
|
||||
* This software may be used and distributed according to the
|
||||
* terms of the GNU Public License, Version 2, incorporated
|
||||
* herein by reference.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* Version 2 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _TEGRA114_SPI_H_
|
||||
#define _TEGRA114_SPI_H_
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
int tegra114_spi_init(int *node_list, int count);
|
||||
int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs);
|
||||
struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int mode);
|
||||
void tegra114_spi_free_slave(struct spi_slave *slave);
|
||||
int tegra114_spi_claim_bus(struct spi_slave *slave);
|
||||
void tegra114_spi_cs_activate(struct spi_slave *slave);
|
||||
void tegra114_spi_cs_deactivate(struct spi_slave *slave);
|
||||
int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
|
||||
const void *data_out, void *data_in, unsigned long flags);
|
||||
|
||||
#endif /* _TEGRA114_SPI_H_ */
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* NVIDIA Tegra20 SPI-FLASH controller
|
||||
*
|
||||
* Copyright 2010-2012 NVIDIA Corporation
|
||||
*
|
||||
* This software may be used and distributed according to the
|
||||
* terms of the GNU Public License, Version 2, incorporated
|
||||
* herein by reference.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* Version 2 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _TEGRA20_SPI_H_
|
||||
#define _TEGRA20_SPI_H_
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs);
|
||||
struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int mode);
|
||||
void tegra20_spi_free_slave(struct spi_slave *slave);
|
||||
int tegra20_spi_init(int *node_list, int count);
|
||||
int tegra20_spi_claim_bus(struct spi_slave *slave);
|
||||
void tegra20_spi_cs_activate(struct spi_slave *slave);
|
||||
void tegra20_spi_cs_deactivate(struct spi_slave *slave);
|
||||
int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
|
||||
const void *data_out, void *data_in, unsigned long flags);
|
||||
|
||||
#endif /* _TEGRA20_SPI_H_ */
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* NVIDIA Tegra SPI-SLINK controller
|
||||
*
|
||||
* Copyright 2010-2013 NVIDIA Corporation
|
||||
*
|
||||
* This software may be used and distributed according to the
|
||||
* terms of the GNU Public License, Version 2, incorporated
|
||||
* herein by reference.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* Version 2 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _TEGRA30_SPI_H_
|
||||
#define _TEGRA30_SPI_H_
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
int tegra30_spi_init(int *node_list, int count);
|
||||
int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs);
|
||||
struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int mode);
|
||||
void tegra30_spi_free_slave(struct spi_slave *slave);
|
||||
int tegra30_spi_claim_bus(struct spi_slave *slave);
|
||||
void tegra30_spi_cs_activate(struct spi_slave *slave);
|
||||
void tegra30_spi_cs_deactivate(struct spi_slave *slave);
|
||||
int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
|
||||
const void *data_out, void *data_in, unsigned long flags);
|
||||
|
||||
#endif /* _TEGRA30_SPI_H_ */
|
|
@ -52,8 +52,8 @@ struct i2c_pads_info {
|
|||
&mx6q_##name : &mx6s_##name
|
||||
#endif
|
||||
|
||||
void setup_i2c(unsigned i2c_index, int speed, int slave_addr,
|
||||
struct i2c_pads_info *p);
|
||||
int setup_i2c(unsigned i2c_index, int speed, int slave_addr,
|
||||
struct i2c_pads_info *p);
|
||||
void bus_i2c_init(void *base, int speed, int slave_addr,
|
||||
int (*idle_bus_fn)(void *p), void *p);
|
||||
int bus_i2c_read(void *base, uchar chip, uint addr, int alen, uchar *buf,
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
chosen {
|
||||
stdout-path = "/serial";
|
||||
};
|
||||
|
@ -131,4 +134,27 @@
|
|||
num-gpios = <20>;
|
||||
};
|
||||
|
||||
spi@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
compatible = "sandbox,spi";
|
||||
cs-gpios = <0>, <&gpio_a 0>;
|
||||
flash@0 {
|
||||
reg = <0>;
|
||||
compatible = "spansion,m25p16", "sandbox,spi-flash";
|
||||
spi-max-frequency = <40000000>;
|
||||
sandbox,filename = "spi.bin";
|
||||
};
|
||||
};
|
||||
|
||||
cros-ec@0 {
|
||||
compatible = "google,cros-ec";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
firmware_storage_spi: flash@0 {
|
||||
reg = <0 0x400000>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -32,19 +32,6 @@ struct sandbox_spi_emu_ops {
|
|||
int (*xfer)(void *priv, const u8 *rx, u8 *tx, uint bytes);
|
||||
};
|
||||
|
||||
/*
|
||||
* There are times when the data lines are allowed to tristate. What
|
||||
* is actually sensed on the line depends on the hardware. It could
|
||||
* always be 0xFF/0x00 (if there are pull ups/downs), or things could
|
||||
* float and so we'd get garbage back. This func encapsulates that
|
||||
* scenario so we can worry about the details here.
|
||||
*/
|
||||
static inline void sandbox_spi_tristate(u8 *buf, uint len)
|
||||
{
|
||||
/* XXX: make this into a user config option ? */
|
||||
memset(buf, 0xff, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the bus/cs from the spi spec and return the start of the spi
|
||||
* client spec. If the bus/cs are invalid for the current config, then
|
||||
|
|
|
@ -42,7 +42,7 @@ enum state_terminal_raw {
|
|||
|
||||
struct sandbox_spi_info {
|
||||
const char *spec;
|
||||
const struct sandbox_spi_emu_ops *ops;
|
||||
struct udevice *emul;
|
||||
};
|
||||
|
||||
/* The complete state of the test system */
|
||||
|
|
|
@ -13,11 +13,12 @@
|
|||
#include <malloc.h>
|
||||
#include <netdev.h>
|
||||
#include <miiphy.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include <asm/arch/kirkwood.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/mpp.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
#include "lsxl.h"
|
||||
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fsl_esdhc.h>
|
||||
#include <miiphy.h>
|
||||
#include <netdev.h>
|
||||
#include <fdt_support.h>
|
||||
#include <sata.h>
|
||||
#include <serial_mxc.h>
|
||||
#include <asm/arch/crm_regs.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/arch/iomux.h>
|
||||
|
@ -69,16 +71,23 @@ static iomux_v3_cfg_t const sata_pads[] = {
|
|||
IOMUX_PADS(PAD_EIM_BCLK__GPIO6_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL)),
|
||||
};
|
||||
|
||||
static void cm_fx6_setup_issd(void)
|
||||
static int cm_fx6_setup_issd(void)
|
||||
{
|
||||
SETUP_IOMUX_PADS(sata_pads);
|
||||
/* Make sure this gpio has logical 0 value */
|
||||
gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0);
|
||||
udelay(100);
|
||||
int ret, i;
|
||||
|
||||
cm_fx6_sata_power(0);
|
||||
mdelay(250);
|
||||
cm_fx6_sata_power(1);
|
||||
SETUP_IOMUX_PADS(sata_pads);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cm_fx6_issd_gpios); i++) {
|
||||
ret = gpio_request(cm_fx6_issd_gpios[i], "sata");
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_request(CM_FX6_SATA_PWLOSS_INT, "sata_pwloss_int");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CM_FX6_SATA_INIT_RETRIES 10
|
||||
|
@ -86,7 +95,14 @@ int sata_initialize(void)
|
|||
{
|
||||
int err, i;
|
||||
|
||||
cm_fx6_setup_issd();
|
||||
/* Make sure this gpio has logical 0 value */
|
||||
gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0);
|
||||
udelay(100);
|
||||
|
||||
cm_fx6_sata_power(0);
|
||||
mdelay(250);
|
||||
cm_fx6_sata_power(1);
|
||||
|
||||
for (i = 0; i < CM_FX6_SATA_INIT_RETRIES; i++) {
|
||||
err = setup_sata();
|
||||
if (err) {
|
||||
|
@ -109,6 +125,8 @@ int sata_initialize(void)
|
|||
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
static int cm_fx6_setup_issd(void) { return 0; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_MXC
|
||||
|
@ -141,49 +159,68 @@ I2C_PADS(i2c2_pads,
|
|||
IMX_GPIO_NR(1, 6));
|
||||
|
||||
|
||||
static void cm_fx6_setup_i2c(void)
|
||||
static int cm_fx6_setup_one_i2c(int busnum, struct i2c_pads_info *pads)
|
||||
{
|
||||
setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c0_pads));
|
||||
setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c1_pads));
|
||||
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c2_pads));
|
||||
int ret;
|
||||
|
||||
ret = setup_i2c(busnum, CONFIG_SYS_I2C_SPEED, 0x7f, pads);
|
||||
if (ret)
|
||||
printf("Warning: I2C%d setup failed: %d\n", busnum, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cm_fx6_setup_i2c(void)
|
||||
{
|
||||
int ret = 0, err;
|
||||
|
||||
/* i2c<x>_pads are wierd macro variables; we can't use an array */
|
||||
err = cm_fx6_setup_one_i2c(0, I2C_PADS_INFO(i2c0_pads));
|
||||
if (err)
|
||||
ret = err;
|
||||
err = cm_fx6_setup_one_i2c(1, I2C_PADS_INFO(i2c1_pads));
|
||||
if (err)
|
||||
ret = err;
|
||||
err = cm_fx6_setup_one_i2c(2, I2C_PADS_INFO(i2c2_pads));
|
||||
if (err)
|
||||
ret = err;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static void cm_fx6_setup_i2c(void) { }
|
||||
static int cm_fx6_setup_i2c(void) { return 0; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_MX6
|
||||
#define WEAK_PULLDOWN (PAD_CTL_PUS_100K_DOWN | \
|
||||
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
|
||||
PAD_CTL_HYS | PAD_CTL_SRE_SLOW)
|
||||
#define MX6_USBNC_BASEADDR 0x2184800
|
||||
#define USBNC_USB_H1_PWR_POL (1 << 9)
|
||||
|
||||
static int cm_fx6_usb_hub_reset(void)
|
||||
static int cm_fx6_setup_usb_host(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = gpio_request(CM_FX6_USB_HUB_RST, "usb hub rst");
|
||||
if (err) {
|
||||
printf("USB hub rst gpio request failed: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
SETUP_IOMUX_PAD(PAD_GPIO_0__USB_H1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL));
|
||||
SETUP_IOMUX_PAD(PAD_SD3_RST__GPIO7_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL));
|
||||
gpio_direction_output(CM_FX6_USB_HUB_RST, 0);
|
||||
udelay(10);
|
||||
gpio_direction_output(CM_FX6_USB_HUB_RST, 1);
|
||||
mdelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cm_fx6_init_usb_otg(void)
|
||||
static int cm_fx6_setup_usb_otg(void)
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
|
||||
|
||||
ret = gpio_request(SB_FX6_USB_OTG_PWR, "usb-pwr");
|
||||
if (ret) {
|
||||
printf("USB OTG pwr gpio request failed: %d\n", ret);
|
||||
return ret;
|
||||
err = gpio_request(SB_FX6_USB_OTG_PWR, "usb-pwr");
|
||||
if (err) {
|
||||
printf("USB OTG pwr gpio request failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
SETUP_IOMUX_PAD(PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL));
|
||||
|
@ -194,25 +231,27 @@ static int cm_fx6_init_usb_otg(void)
|
|||
return gpio_direction_output(SB_FX6_USB_OTG_PWR, 0);
|
||||
}
|
||||
|
||||
#define MX6_USBNC_BASEADDR 0x2184800
|
||||
#define USBNC_USB_H1_PWR_POL (1 << 9)
|
||||
int board_ehci_hcd_init(int port)
|
||||
{
|
||||
int ret;
|
||||
u32 *usbnc_usb_uh1_ctrl = (u32 *)(MX6_USBNC_BASEADDR + 4);
|
||||
|
||||
switch (port) {
|
||||
case 0:
|
||||
return cm_fx6_init_usb_otg();
|
||||
case 1:
|
||||
SETUP_IOMUX_PAD(PAD_GPIO_0__USB_H1_PWR |
|
||||
MUX_PAD_CTRL(NO_PAD_CTRL));
|
||||
/* Only 1 host controller in use. port 0 is OTG & needs no attention */
|
||||
if (port != 1)
|
||||
return 0;
|
||||
|
||||
/* Set PWR polarity to match power switch's enable polarity */
|
||||
setbits_le32(usbnc_usb_uh1_ctrl, USBNC_USB_H1_PWR_POL);
|
||||
return cm_fx6_usb_hub_reset();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Set PWR polarity to match power switch's enable polarity */
|
||||
setbits_le32(usbnc_usb_uh1_ctrl, USBNC_USB_H1_PWR_POL);
|
||||
ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
udelay(10);
|
||||
ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -224,6 +263,9 @@ int board_ehci_power(int port, int on)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int cm_fx6_setup_usb_otg(void) { return 0; }
|
||||
static int cm_fx6_setup_usb_host(void) { return 0; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FEC_MXC
|
||||
|
@ -318,12 +360,17 @@ static int handle_mac_address(void)
|
|||
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
int res = handle_mac_address();
|
||||
if (res)
|
||||
int err;
|
||||
|
||||
err = handle_mac_address();
|
||||
if (err)
|
||||
puts("No MAC address found\n");
|
||||
|
||||
SETUP_IOMUX_PADS(enet_pads);
|
||||
/* phy reset */
|
||||
err = gpio_request(CM_FX6_ENET_NRST, "enet_nrst");
|
||||
if (err)
|
||||
printf("Etnernet NRST gpio request failed: %d\n", err);
|
||||
gpio_direction_output(CM_FX6_ENET_NRST, 0);
|
||||
udelay(500);
|
||||
gpio_set_value(CM_FX6_ENET_NRST, 1);
|
||||
|
@ -394,6 +441,16 @@ int board_mmc_init(bd_t *bis)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MXC_SPI
|
||||
int cm_fx6_setup_ecspi(void)
|
||||
{
|
||||
cm_fx6_set_ecspi_iomux();
|
||||
return gpio_request(CM_FX6_ECSPI_BUS0_CS0, "ecspi_bus0_cs0");
|
||||
}
|
||||
#else
|
||||
int cm_fx6_setup_ecspi(void) { return 0; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF_BOARD_SETUP
|
||||
void ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
|
@ -409,9 +466,37 @@ void ft_board_setup(void *blob, bd_t *bd)
|
|||
|
||||
int board_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
|
||||
cm_fx6_setup_gpmi_nand();
|
||||
cm_fx6_setup_i2c();
|
||||
|
||||
ret = cm_fx6_setup_ecspi();
|
||||
if (ret)
|
||||
printf("Warning: ECSPI setup failed: %d\n", ret);
|
||||
|
||||
ret = cm_fx6_setup_usb_otg();
|
||||
if (ret)
|
||||
printf("Warning: USB OTG setup failed: %d\n", ret);
|
||||
|
||||
ret = cm_fx6_setup_usb_host();
|
||||
if (ret)
|
||||
printf("Warning: USB host setup failed: %d\n", ret);
|
||||
|
||||
/*
|
||||
* cm-fx6 may have iSSD not assembled and in this case it has
|
||||
* bypasses for a (m)SATA socket on the baseboard. The socketed
|
||||
* device is not controlled by those GPIOs. So just print a warning
|
||||
* if the setup fails.
|
||||
*/
|
||||
ret = cm_fx6_setup_issd();
|
||||
if (ret)
|
||||
printf("Warning: iSSD setup failed: %d\n", ret);
|
||||
|
||||
/* Warn on failure but do not abort boot */
|
||||
ret = cm_fx6_setup_i2c();
|
||||
if (ret)
|
||||
printf("Warning: I2C setup failed: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -481,3 +566,11 @@ u32 get_board_rev(void)
|
|||
return cl_eeprom_get_board_rev();
|
||||
}
|
||||
|
||||
static struct mxc_serial_platdata cm_fx6_mxc_serial_plat = {
|
||||
.reg = (struct mxc_uart *)UART4_BASE,
|
||||
};
|
||||
|
||||
U_BOOT_DEVICE(cm_fx6_serial) = {
|
||||
.name = "serial_mxc",
|
||||
.platdata = &cm_fx6_mxc_serial_plat,
|
||||
};
|
||||
|
|
|
@ -114,9 +114,8 @@ int board_init(void)
|
|||
clock_init();
|
||||
clock_verify();
|
||||
|
||||
#ifdef CONFIG_FDT_SPI
|
||||
#ifdef CONFIG_TEGRA_SPI
|
||||
pin_mux_spi();
|
||||
spi_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PWM_TEGRA
|
||||
|
|
|
@ -16,15 +16,26 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <dm.h>
|
||||
#include <fdt_support.h>
|
||||
#include <lcd.h>
|
||||
#include <mmc.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/mbox.h>
|
||||
#include <asm/arch/sdhci.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static const struct bcm2835_gpio_platdata gpio_platdata = {
|
||||
.base = BCM2835_GPIO_BASE,
|
||||
};
|
||||
|
||||
U_BOOT_DEVICE(bcm2835_gpios) = {
|
||||
.name = "gpio_bcm2835",
|
||||
.platdata = &gpio_platdata,
|
||||
};
|
||||
|
||||
struct msg_get_arm_mem {
|
||||
struct bcm2835_mbox_hdr hdr;
|
||||
struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mmc.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
int checkboard(void)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mmc.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
int checkboard(void)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mmc.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
int checkboard(void)
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <usb.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/dwmmc.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/power.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
@ -19,6 +19,8 @@ int board_usb_init(int index, enum usb_init_type init)
|
|||
/* Configure gpios for usb 3503 hub:
|
||||
* disconnect, toggle reset and connect
|
||||
*/
|
||||
gpio_request(EXYNOS5_GPIO_D17, "usb_connect");
|
||||
gpio_request(EXYNOS5_GPIO_X35, "usb_reset");
|
||||
gpio_direction_output(EXYNOS5_GPIO_D17, 0);
|
||||
gpio_direction_output(EXYNOS5_GPIO_X35, 0);
|
||||
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
#include <tmu.h>
|
||||
#include <netdev.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/board.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/dwmmc.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/power.h>
|
||||
|
@ -87,9 +87,6 @@ int board_init(void)
|
|||
boot_temp_check();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXYNOS_SPI
|
||||
spi_init();
|
||||
#endif
|
||||
return exynos_init();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <malloc.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <power/pmic.h>
|
||||
|
@ -412,6 +411,8 @@ void check_boot_mode(void)
|
|||
void keys_init(void)
|
||||
{
|
||||
/* Set direction to input */
|
||||
gpio_request(KEY_VOL_UP_GPIO, "volume-up");
|
||||
gpio_request(KEY_VOL_DOWN_GPIO, "volume-down");
|
||||
gpio_direction_input(KEY_VOL_UP_GPIO);
|
||||
gpio_direction_input(KEY_VOL_DOWN_GPIO);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <power/pmic.h>
|
||||
#include <usb/s3c_udc.h>
|
||||
|
@ -33,6 +33,16 @@ int board_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_INIT_BOARD
|
||||
void i2c_init_board(void)
|
||||
{
|
||||
gpio_request(S5PC110_GPIO_J43, "i2c_clk");
|
||||
gpio_request(S5PC110_GPIO_J40, "i2c_data");
|
||||
gpio_direction_output(S5PC110_GPIO_J43, 1);
|
||||
gpio_direction_output(S5PC110_GPIO_J40, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
int power_init_board(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -80,6 +90,7 @@ int board_mmc_init(bd_t *bis)
|
|||
int i, ret, ret_sd = 0;
|
||||
|
||||
/* MASSMEMORY_EN: XMSMDATA7: GPJ2[7] output high */
|
||||
gpio_request(S5PC110_GPIO_J27, "massmemory_en");
|
||||
gpio_direction_output(S5PC110_GPIO_J27, 1);
|
||||
|
||||
/*
|
||||
|
@ -108,6 +119,7 @@ int board_mmc_init(bd_t *bis)
|
|||
* SD card (T_FLASH) detect and init
|
||||
* T_FLASH_DETECT: EINT28: GPH3[4] input mode
|
||||
*/
|
||||
gpio_request(S5PC110_GPIO_H34, "t_flash_detect");
|
||||
gpio_cfg_pin(S5PC110_GPIO_H34, S5P_GPIO_INPUT);
|
||||
gpio_set_pull(S5PC110_GPIO_H34, S5P_GPIO_PULL_UP);
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/periph.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
|
|
|
@ -29,6 +29,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
static void board_enable_audio_codec(void)
|
||||
{
|
||||
/* Enable MAX98095 Codec */
|
||||
gpio_request(EXYNOS5_GPIO_X17, "max98095_enable");
|
||||
gpio_direction_output(EXYNOS5_GPIO_X17, 1);
|
||||
gpio_set_pull(EXYNOS5_GPIO_X17, S5P_GPIO_PULL_NONE);
|
||||
}
|
||||
|
@ -199,16 +200,19 @@ static int board_dp_bridge_setup(void)
|
|||
/* Setup the GPIOs */
|
||||
|
||||
/* PD is ACTIVE_LOW, and initially de-asserted */
|
||||
gpio_request(EXYNOS5_GPIO_Y25, "dp_bridge_pd");
|
||||
gpio_set_pull(EXYNOS5_GPIO_Y25, S5P_GPIO_PULL_NONE);
|
||||
gpio_direction_output(EXYNOS5_GPIO_Y25, 1);
|
||||
|
||||
/* Reset is ACTIVE_LOW */
|
||||
gpio_request(EXYNOS5_GPIO_X15, "dp_bridge_reset");
|
||||
gpio_set_pull(EXYNOS5_GPIO_X15, S5P_GPIO_PULL_NONE);
|
||||
gpio_direction_output(EXYNOS5_GPIO_X15, 0);
|
||||
|
||||
udelay(10);
|
||||
gpio_set_value(EXYNOS5_GPIO_X15, 1);
|
||||
|
||||
gpio_request(EXYNOS5_GPIO_X07, "dp_bridge_hpd");
|
||||
gpio_direction_input(EXYNOS5_GPIO_X07);
|
||||
|
||||
/*
|
||||
|
@ -236,10 +240,12 @@ static int board_dp_bridge_setup(void)
|
|||
void exynos_cfg_lcd_gpio(void)
|
||||
{
|
||||
/* For Backlight */
|
||||
gpio_request(EXYNOS5_GPIO_B20, "lcd_backlight");
|
||||
gpio_cfg_pin(EXYNOS5_GPIO_B20, S5P_GPIO_OUTPUT);
|
||||
gpio_set_value(EXYNOS5_GPIO_B20, 1);
|
||||
|
||||
/* LCD power on */
|
||||
gpio_request(EXYNOS5_GPIO_X15, "lcd_power");
|
||||
gpio_cfg_pin(EXYNOS5_GPIO_X15, S5P_GPIO_OUTPUT);
|
||||
gpio_set_value(EXYNOS5_GPIO_X15, 1);
|
||||
|
||||
|
@ -276,6 +282,7 @@ void exynos_backlight_on(unsigned int on)
|
|||
mdelay(10);
|
||||
|
||||
/* board_dp_backlight_en */
|
||||
gpio_request(EXYNOS5_GPIO_X30, "board_dp_backlight_en");
|
||||
gpio_direction_output(EXYNOS5_GPIO_X30, 1);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
#include <lcd.h>
|
||||
#include <spi.h>
|
||||
#include <errno.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/board.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/system.h>
|
||||
#include <asm/arch/dp_info.h>
|
||||
|
@ -74,9 +74,12 @@ void exynos_lcd_power_on(void)
|
|||
mdelay(5);
|
||||
|
||||
/* TODO(ajaykumar.rs@samsung.com): Use device tree */
|
||||
gpio_request(EXYNOS5420_GPIO_X35, "edp_slp#");
|
||||
gpio_direction_output(EXYNOS5420_GPIO_X35, 1); /* EDP_SLP# */
|
||||
mdelay(10);
|
||||
gpio_request(EXYNOS5420_GPIO_Y77, "edp_rst#");
|
||||
gpio_direction_output(EXYNOS5420_GPIO_Y77, 1); /* EDP_RST# */
|
||||
gpio_request(EXYNOS5420_GPIO_X26, "edp_hpd");
|
||||
gpio_direction_input(EXYNOS5420_GPIO_X26); /* EDP_HPD */
|
||||
gpio_set_pull(EXYNOS5420_GPIO_X26, S5P_GPIO_PULL_NONE);
|
||||
|
||||
|
@ -88,6 +91,7 @@ void exynos_lcd_power_on(void)
|
|||
void exynos_backlight_on(unsigned int onoff)
|
||||
{
|
||||
/* For PWM */
|
||||
gpio_request(EXYNOS5420_GPIO_B20, "backlight_on");
|
||||
gpio_cfg_pin(EXYNOS5420_GPIO_B20, S5P_GPIO_FUNC(0x1));
|
||||
gpio_set_value(EXYNOS5420_GPIO_B20, 1);
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/sromc.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <netdev.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <netdev.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/periph.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#include <common.h>
|
||||
#include <lcd.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/mipi_dsim.h>
|
||||
|
@ -63,6 +63,8 @@ void i2c_init_board(void)
|
|||
}
|
||||
|
||||
/* I2C_8 -> FG */
|
||||
gpio_request(EXYNOS4_GPIO_Y40, "i2c_clk");
|
||||
gpio_request(EXYNOS4_GPIO_Y41, "i2c_data");
|
||||
gpio_direction_output(EXYNOS4_GPIO_Y40, 1);
|
||||
gpio_direction_output(EXYNOS4_GPIO_Y41, 1);
|
||||
}
|
||||
|
@ -346,12 +348,17 @@ int exynos_power_init(void)
|
|||
static unsigned int get_hw_revision(void)
|
||||
{
|
||||
int hwrev = 0;
|
||||
char str[10];
|
||||
int i;
|
||||
|
||||
/* hw_rev[3:0] == GPE1[3:0] */
|
||||
for (i = EXYNOS4_GPIO_E10; i < EXYNOS4_GPIO_E14; i++) {
|
||||
gpio_cfg_pin(i, S5P_GPIO_INPUT);
|
||||
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
||||
for (i = 0; i < 4; i++) {
|
||||
int pin = i + EXYNOS4_GPIO_E10;
|
||||
|
||||
sprintf(str, "hw_rev%d", i);
|
||||
gpio_request(pin, str);
|
||||
gpio_cfg_pin(pin, S5P_GPIO_INPUT);
|
||||
gpio_set_pull(pin, S5P_GPIO_PULL_NONE);
|
||||
}
|
||||
|
||||
udelay(1);
|
||||
|
@ -517,6 +524,7 @@ static void board_power_init(void)
|
|||
static void exynos_uart_init(void)
|
||||
{
|
||||
/* UART_SEL GPY4[7] (part2) at EXYNOS4 */
|
||||
gpio_request(EXYNOS4_GPIO_Y47, "uart_sel");
|
||||
gpio_set_pull(EXYNOS4_GPIO_Y47, S5P_GPIO_PULL_UP);
|
||||
gpio_direction_output(EXYNOS4_GPIO_Y47, 1);
|
||||
}
|
||||
|
@ -534,6 +542,7 @@ int exynos_early_init_f(void)
|
|||
|
||||
void exynos_reset_lcd(void)
|
||||
{
|
||||
gpio_request(EXYNOS4_GPIO_Y45, "lcd_reset");
|
||||
gpio_direction_output(EXYNOS4_GPIO_Y45, 1);
|
||||
udelay(10000);
|
||||
gpio_direction_output(EXYNOS4_GPIO_Y45, 0);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <lcd.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/power.h>
|
||||
#include <asm/arch/mipi_dsim.h>
|
||||
|
@ -32,6 +33,7 @@ static inline u32 get_model_rev(void);
|
|||
static void check_hw_revision(void)
|
||||
{
|
||||
int modelrev = 0;
|
||||
char str[12];
|
||||
int i;
|
||||
|
||||
/*
|
||||
|
@ -40,13 +42,22 @@ static void check_hw_revision(void)
|
|||
* TRM say that it may cause unexcepted state and leakage current.
|
||||
* and pull-none is only for output function.
|
||||
*/
|
||||
for (i = EXYNOS4X12_GPIO_M10; i < EXYNOS4X12_GPIO_M12; i++)
|
||||
gpio_cfg_pin(i, S5P_GPIO_INPUT);
|
||||
for (i = 0; i < 2; i++) {
|
||||
int pin = i + EXYNOS4X12_GPIO_M10;
|
||||
|
||||
sprintf(str, "model_rev%d", i);
|
||||
gpio_request(pin, str);
|
||||
gpio_cfg_pin(pin, S5P_GPIO_INPUT);
|
||||
}
|
||||
|
||||
/* GPM1[5:2]: HW_REV[3:0] */
|
||||
for (i = EXYNOS4X12_GPIO_M12; i < EXYNOS4X12_GPIO_M16; i++) {
|
||||
gpio_cfg_pin(i, S5P_GPIO_INPUT);
|
||||
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
||||
for (i = 0; i < 4; i++) {
|
||||
int pin = i + EXYNOS4X12_GPIO_M12;
|
||||
|
||||
sprintf(str, "hw_rev%d", i);
|
||||
gpio_request(pin, str);
|
||||
gpio_cfg_pin(pin, S5P_GPIO_INPUT);
|
||||
gpio_set_pull(pin, S5P_GPIO_PULL_NONE);
|
||||
}
|
||||
|
||||
/* GPM1[1:0]: MODEL_REV[1:0] */
|
||||
|
@ -102,10 +113,14 @@ static void board_init_i2c(void)
|
|||
}
|
||||
|
||||
/* I2C_8 */
|
||||
gpio_request(EXYNOS4X12_GPIO_F14, "i2c8_clk");
|
||||
gpio_request(EXYNOS4X12_GPIO_F15, "i2c8_data");
|
||||
gpio_direction_output(EXYNOS4X12_GPIO_F14, 1);
|
||||
gpio_direction_output(EXYNOS4X12_GPIO_F15, 1);
|
||||
|
||||
/* I2C_9 */
|
||||
gpio_request(EXYNOS4X12_GPIO_M21, "i2c9_clk");
|
||||
gpio_request(EXYNOS4X12_GPIO_M20, "i2c9_data");
|
||||
gpio_direction_output(EXYNOS4X12_GPIO_M21, 1);
|
||||
gpio_direction_output(EXYNOS4X12_GPIO_M20, 1);
|
||||
}
|
||||
|
@ -387,6 +402,7 @@ void exynos_lcd_power_on(void)
|
|||
struct pmic *p = pmic_get("MAX77686_PMIC");
|
||||
|
||||
/* LCD_2.2V_EN: GPC0[1] */
|
||||
gpio_request(EXYNOS4X12_GPIO_C01, "lcd_2v2_en");
|
||||
gpio_set_pull(EXYNOS4X12_GPIO_C01, S5P_GPIO_PULL_UP);
|
||||
gpio_direction_output(EXYNOS4X12_GPIO_C01, 1);
|
||||
|
||||
|
@ -399,6 +415,7 @@ void exynos_lcd_power_on(void)
|
|||
void exynos_reset_lcd(void)
|
||||
{
|
||||
/* reset lcd */
|
||||
gpio_request(EXYNOS4X12_GPIO_F21, "lcd_reset");
|
||||
gpio_direction_output(EXYNOS4X12_GPIO_F21, 0);
|
||||
udelay(10);
|
||||
gpio_set_value(EXYNOS4X12_GPIO_F21, 1);
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/adc.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/watchdog.h>
|
||||
#include <ld9040.h>
|
||||
|
@ -202,53 +201,6 @@ int exynos_early_init_f(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOFT_SPI
|
||||
static void soft_spi_init(void)
|
||||
{
|
||||
gpio_direction_output(CONFIG_SOFT_SPI_GPIO_SCLK,
|
||||
CONFIG_SOFT_SPI_MODE & SPI_CPOL);
|
||||
gpio_direction_output(CONFIG_SOFT_SPI_GPIO_MOSI, 1);
|
||||
gpio_direction_input(CONFIG_SOFT_SPI_GPIO_MISO);
|
||||
gpio_direction_output(CONFIG_SOFT_SPI_GPIO_CS,
|
||||
!(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
|
||||
}
|
||||
|
||||
void spi_cs_activate(struct spi_slave *slave)
|
||||
{
|
||||
gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
|
||||
!(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
|
||||
SPI_SCL(1);
|
||||
gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
|
||||
CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH);
|
||||
}
|
||||
|
||||
void spi_cs_deactivate(struct spi_slave *slave)
|
||||
{
|
||||
gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
|
||||
!(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
|
||||
}
|
||||
|
||||
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
|
||||
{
|
||||
return bus == 0 && cs == 0;
|
||||
}
|
||||
|
||||
void universal_spi_scl(int bit)
|
||||
{
|
||||
gpio_set_value(CONFIG_SOFT_SPI_GPIO_SCLK, bit);
|
||||
}
|
||||
|
||||
void universal_spi_sda(int bit)
|
||||
{
|
||||
gpio_set_value(CONFIG_SOFT_SPI_GPIO_MOSI, bit);
|
||||
}
|
||||
|
||||
int universal_spi_read(void)
|
||||
{
|
||||
return gpio_get_value(CONFIG_SOFT_SPI_GPIO_MISO);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void init_pmic_lcd(void)
|
||||
{
|
||||
unsigned char val;
|
||||
|
@ -331,9 +283,8 @@ void exynos_cfg_lcd_gpio(void)
|
|||
}
|
||||
|
||||
/* gpio pad configuration for LCD reset. */
|
||||
gpio_request(EXYNOS4_GPIO_Y45, "lcd_reset");
|
||||
gpio_cfg_pin(EXYNOS4_GPIO_Y45, S5P_GPIO_OUTPUT);
|
||||
|
||||
spi_init();
|
||||
}
|
||||
|
||||
int mipi_power(void)
|
||||
|
@ -387,6 +338,7 @@ int exynos_init(void)
|
|||
* you should set it HIGH since it removes the inverter
|
||||
*/
|
||||
/* MASSMEMORY_EN: XMDMDATA_6: GPE3[6] */
|
||||
gpio_request(EXYNOS4_GPIO_E36, "ldo_en");
|
||||
gpio_direction_output(EXYNOS4_GPIO_E36, 0);
|
||||
break;
|
||||
default:
|
||||
|
@ -395,13 +347,11 @@ int exynos_init(void)
|
|||
* But set it as HIGH to ensure
|
||||
*/
|
||||
/* MASSMEMORY_EN: XMDMADDR_3: GPE1[3] */
|
||||
gpio_request(EXYNOS4_GPIO_E13, "massmemory_en");
|
||||
gpio_direction_output(EXYNOS4_GPIO_E13, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOFT_SPI
|
||||
soft_spi_init();
|
||||
#endif
|
||||
check_hw_revision();
|
||||
printf("HW Revision:\t0x%x\n", board_rev);
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ static int initr_flash(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC
|
||||
#if defined(CONFIG_PPC) && !defined(CONFIG_DM_SPI)
|
||||
static int initr_spi(void)
|
||||
{
|
||||
/* PPC does this here */
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <div64.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <dm/device-internal.h>
|
||||
|
||||
static struct spi_flash *flash;
|
||||
|
||||
|
@ -80,7 +83,12 @@ static int do_spi_flash_probe(int argc, char * const argv[])
|
|||
unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
|
||||
unsigned int mode = CONFIG_SF_DEFAULT_MODE;
|
||||
char *endp;
|
||||
#ifdef CONFIG_DM_SPI_FLASH
|
||||
struct udevice *new, *bus_dev;
|
||||
int ret;
|
||||
#else
|
||||
struct spi_flash *new;
|
||||
#endif
|
||||
|
||||
if (argc >= 2) {
|
||||
cs = simple_strtoul(argv[1], &endp, 0);
|
||||
|
@ -108,6 +116,23 @@ static int do_spi_flash_probe(int argc, char * const argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_SPI_FLASH
|
||||
/* Remove the old device, otherwise probe will just be a nop */
|
||||
ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new);
|
||||
if (!ret) {
|
||||
device_remove(new);
|
||||
device_unbind(new);
|
||||
}
|
||||
flash = NULL;
|
||||
ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new);
|
||||
if (ret) {
|
||||
printf("Failed to initialize SPI flash at %u:%u (error %d)\n",
|
||||
bus, cs, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
flash = new->uclass_priv;
|
||||
#else
|
||||
new = spi_flash_probe(bus, cs, speed, mode);
|
||||
if (!new) {
|
||||
printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
|
||||
|
@ -117,6 +142,7 @@ static int do_spi_flash_probe(int argc, char * const argv[])
|
|||
if (flash)
|
||||
spi_flash_free(flash);
|
||||
flash = new;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <spi.h>
|
||||
|
||||
|
@ -42,19 +43,38 @@ static uchar din[MAX_SPI_BYTES];
|
|||
static int do_spi_xfer(int bus, int cs)
|
||||
{
|
||||
struct spi_slave *slave;
|
||||
int rcode = 0;
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_DM_SPI
|
||||
char name[30], *str;
|
||||
struct udevice *dev;
|
||||
|
||||
snprintf(name, sizeof(name), "generic_%d:%d", bus, cs);
|
||||
str = strdup(name);
|
||||
ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv",
|
||||
str, &dev, &slave);
|
||||
if (ret)
|
||||
return ret;
|
||||
#else
|
||||
slave = spi_setup_slave(bus, cs, 1000000, mode);
|
||||
if (!slave) {
|
||||
printf("Invalid device %d:%d\n", bus, cs);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
spi_claim_bus(slave);
|
||||
if (spi_xfer(slave, bitlen, dout, din,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END) != 0) {
|
||||
printf("Error during SPI transaction\n");
|
||||
rcode = -EIO;
|
||||
ret = spi_claim_bus(slave);
|
||||
if (ret)
|
||||
goto done;
|
||||
ret = spi_xfer(slave, bitlen, dout, din,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
#ifndef CONFIG_DM_SPI
|
||||
/* We don't get an error code in this case */
|
||||
if (ret)
|
||||
ret = -EIO;
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("Error %d during SPI transaction\n", ret);
|
||||
} else {
|
||||
int j;
|
||||
|
||||
|
@ -62,10 +82,13 @@ static int do_spi_xfer(int bus, int cs)
|
|||
printf("%02X", din[j]);
|
||||
printf("\n");
|
||||
}
|
||||
done:
|
||||
spi_release_bus(slave);
|
||||
#ifndef CONFIG_DM_SPI
|
||||
spi_free_slave(slave);
|
||||
#endif
|
||||
|
||||
return rcode;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,25 +10,44 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <cros_ec.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_DM_CROS_EC
|
||||
struct local_info {
|
||||
struct cros_ec_dev *cros_ec_dev; /* Pointer to cros_ec device */
|
||||
int cros_ec_err; /* Error for cros_ec, 0 if ok */
|
||||
};
|
||||
|
||||
static struct local_info local;
|
||||
#endif
|
||||
|
||||
struct cros_ec_dev *board_get_cros_ec_dev(void)
|
||||
{
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
|
||||
if (ret) {
|
||||
debug("%s: Error %d\n", __func__, ret);
|
||||
return NULL;
|
||||
}
|
||||
return dev->uclass_priv;
|
||||
#else
|
||||
return local.cros_ec_dev;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int board_init_cros_ec_devices(const void *blob)
|
||||
{
|
||||
#ifndef CONFIG_DM_CROS_EC
|
||||
local.cros_ec_err = cros_ec_init(blob, &local.cros_ec_dev);
|
||||
if (local.cros_ec_err)
|
||||
return -1; /* Will report in board_late_init() */
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -40,5 +59,16 @@ int cros_ec_board_init(void)
|
|||
|
||||
int cros_ec_get_error(void)
|
||||
{
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
|
||||
if (ret && ret != -ENODEV)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return local.cros_ec_err;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <common.h>
|
||||
#include <environment.h>
|
||||
#include <malloc.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include <search.h>
|
||||
#include <errno.h>
|
||||
|
|
|
@ -27,10 +27,12 @@ unsigned long get_version(void)
|
|||
# define i2c_write dummy
|
||||
# define i2c_read dummy
|
||||
#endif
|
||||
#ifndef CONFIG_CMD_SPI
|
||||
#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
|
||||
# define spi_init dummy
|
||||
# define spi_setup_slave dummy
|
||||
# define spi_free_slave dummy
|
||||
#endif
|
||||
#ifndef CONFIG_CMD_SPI
|
||||
# define spi_claim_bus dummy
|
||||
# define spi_release_bus dummy
|
||||
# define spi_xfer dummy
|
||||
|
|
25
doc/device-tree-bindings/mtd/spi/spi-flash.txt
Normal file
25
doc/device-tree-bindings/mtd/spi/spi-flash.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
* MTD SPI driver for serial flash chips
|
||||
|
||||
Required properties:
|
||||
- #address-cells, #size-cells : Must be present if the device has sub-nodes
|
||||
representing partitions.
|
||||
- compatible : Should be the manufacturer and the name of the chip. Bear in
|
||||
mind that the DT binding is not U-Boot-only, but in case of
|
||||
U-Boot, see spi_flash_params_table table in
|
||||
drivers/mtd/spi/sf_params.c for the list of supported chips.
|
||||
- reg : Chip-Select number
|
||||
- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
|
||||
|
||||
Optional properties:
|
||||
- memory-map : Address and size of the flash, if memory mapped. This may
|
||||
apply to Intel chipsets, which tend to memory-map flash.
|
||||
|
||||
Example:
|
||||
|
||||
flash: m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "spansion,m25p80";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <40000000>;
|
||||
};
|
34
doc/device-tree-bindings/spi/soft-spi.txt
Normal file
34
doc/device-tree-bindings/spi/soft-spi.txt
Normal file
|
@ -0,0 +1,34 @@
|
|||
Soft SPI
|
||||
|
||||
The soft SPI bus implementation allows the use of GPIO pins to simulate a
|
||||
SPI bus. No SPI host is required for this to work. The down-side is that the
|
||||
performance will typically be much lower than a real SPI bus.
|
||||
|
||||
The soft SPI node requires the following properties:
|
||||
|
||||
compatible: "u-boot,soft-spi"
|
||||
soft_spi_cs: GPIO number to use for SPI chip select (output)
|
||||
soft_spi_sclk: GPIO number to use for SPI clock (output)
|
||||
soft_spi_mosi: GPIO number to use for SPI MOSI line (output)
|
||||
soft_spi_miso GPIO number to use for SPI MISO line (input)
|
||||
spi-delay-us: Number of microseconds of delay between each CS transition
|
||||
|
||||
The GPIOs should be specified as required by the GPIO controller referenced.
|
||||
The first cell holds the phandle of the controller and the second cell
|
||||
typically holds the GPIO number.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
soft-spi {
|
||||
compatible = "u-boot,soft-spi";
|
||||
cs-gpio = <&gpio 235 0>; /* Y43 */
|
||||
sclk-gpio = <&gpio 225 0>; /* Y31 */
|
||||
mosi-gpio = <&gpio 227 0>; /* Y33 */
|
||||
miso-gpio = <&gpio 224 0>; /* Y30 */
|
||||
spi-delay-us = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs@0 {
|
||||
};
|
||||
};
|
|
@ -95,7 +95,7 @@ are provided in test/dm. To run them, try:
|
|||
You should see something like this:
|
||||
|
||||
<...U-Boot banner...>
|
||||
Running 21 driver model tests
|
||||
Running 22 driver model tests
|
||||
Test: dm_test_autobind
|
||||
Test: dm_test_autoprobe
|
||||
Test: dm_test_bus_children
|
||||
|
@ -103,6 +103,7 @@ You should see something like this:
|
|||
Device 'c-test@0': seq 0 is in use by 'a-test'
|
||||
Device 'c-test@1': seq 1 is in use by 'd-test'
|
||||
Test: dm_test_bus_children_funcs
|
||||
Test: dm_test_bus_children_iterators
|
||||
Test: dm_test_bus_parent_data
|
||||
Test: dm_test_bus_parent_ops
|
||||
Test: dm_test_children
|
||||
|
@ -358,7 +359,9 @@ Device Sequence Numbers
|
|||
U-Boot numbers devices from 0 in many situations, such as in the command
|
||||
line for I2C and SPI buses, and the device names for serial ports (serial0,
|
||||
serial1, ...). Driver model supports this numbering and permits devices
|
||||
to be locating by their 'sequence'.
|
||||
to be locating by their 'sequence'. This numbering unique identifies a
|
||||
device in its uclass, so no two devices within a particular uclass can have
|
||||
the same sequence number.
|
||||
|
||||
Sequence numbers start from 0 but gaps are permitted. For example, a board
|
||||
may have I2C buses 0, 1, 4, 5 but no 2 or 3. The choice of how devices are
|
||||
|
|
594
doc/driver-model/spi-howto.txt
Normal file
594
doc/driver-model/spi-howto.txt
Normal file
|
@ -0,0 +1,594 @@
|
|||
How to port a SPI driver to driver model
|
||||
========================================
|
||||
|
||||
Here is a rough step-by-step guide. It is based around converting the
|
||||
exynos SPI driver to driver model (DM) and the example code is based
|
||||
around U-Boot v2014.10-rc2 (commit be9f643).
|
||||
|
||||
It is quite long since it includes actual code examples.
|
||||
|
||||
Before driver model, SPI drivers have their own private structure which
|
||||
contains 'struct spi_slave'. With driver model, 'struct spi_slave' still
|
||||
exists, but now it is 'per-child data' for the SPI bus. Each child of the
|
||||
SPI bus is a SPI slave. The information that was stored in the
|
||||
driver-specific slave structure can now be port in private data for the
|
||||
SPI bus.
|
||||
|
||||
For example, struct tegra_spi_slave looks like this:
|
||||
|
||||
struct tegra_spi_slave {
|
||||
struct spi_slave slave;
|
||||
struct tegra_spi_ctrl *ctrl;
|
||||
};
|
||||
|
||||
In this case 'slave' will be in per-child data, and 'ctrl' will be in the
|
||||
SPI's buses private data.
|
||||
|
||||
|
||||
0. How long does this take?
|
||||
|
||||
You should be able to complete this within 2 hours, including testing but
|
||||
excluding preparing the patches. The API is basically the same as before
|
||||
with only minor changes:
|
||||
|
||||
- methods to set speed and mode are separated out
|
||||
- cs_info is used to get information on a chip select
|
||||
|
||||
|
||||
1. Enable driver mode for SPI and SPI flash
|
||||
|
||||
Add these to your board config:
|
||||
|
||||
#define CONFIG_DM_SPI
|
||||
#define CONFIG_DM_SPI_FLASH
|
||||
|
||||
|
||||
2. Add the skeleton
|
||||
|
||||
Put this code at the bottom of your existing driver file:
|
||||
|
||||
struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int mode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
|
||||
int spi_node)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int exynos_spi_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_spi_probe(struct udevice *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_spi_remove(struct udevice *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_spi_claim_bus(struct udevice *dev)
|
||||
{
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_spi_release_bus(struct udevice *dev)
|
||||
{
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen,
|
||||
const void *dout, void *din, unsigned long flags)
|
||||
{
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_spi_set_speed(struct udevice *dev, uint speed)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_spi_set_mode(struct udevice *dev, uint mode)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int exynos_cs_info(struct udevice *bus, uint cs,
|
||||
struct spi_cs_info *info)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static const struct dm_spi_ops exynos_spi_ops = {
|
||||
.claim_bus = exynos_spi_claim_bus,
|
||||
.release_bus = exynos_spi_release_bus,
|
||||
.xfer = exynos_spi_xfer,
|
||||
.set_speed = exynos_spi_set_speed,
|
||||
.set_mode = exynos_spi_set_mode,
|
||||
.cs_info = exynos_cs_info,
|
||||
};
|
||||
|
||||
static const struct udevice_id exynos_spi_ids[] = {
|
||||
{ .compatible = "samsung,exynos-spi" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(exynos_spi) = {
|
||||
.name = "exynos_spi",
|
||||
.id = UCLASS_SPI,
|
||||
.of_match = exynos_spi_ids,
|
||||
.ops = &exynos_spi_ops,
|
||||
.ofdata_to_platdata = exynos_spi_ofdata_to_platdata,
|
||||
.probe = exynos_spi_probe,
|
||||
.remove = exynos_spi_remove,
|
||||
};
|
||||
|
||||
|
||||
3. Replace 'exynos' in the above code with your driver name
|
||||
|
||||
|
||||
4. #ifdef out all of the code in your driver except for the above
|
||||
|
||||
This will allow you to get it building, which means you can work
|
||||
incrementally. Since all the methods return an error initially, there is
|
||||
less chance that you will accidentally leave something in.
|
||||
|
||||
Also, even though your conversion is basically a rewrite, it might help
|
||||
reviewers if you leave functions in the same place in the file,
|
||||
particularly for large drivers.
|
||||
|
||||
|
||||
5. Add some includes
|
||||
|
||||
Add these includes to your driver:
|
||||
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
6. Build
|
||||
|
||||
At this point you should be able to build U-Boot for your board with the
|
||||
empty SPI driver. You still have empty methods in your driver, but we will
|
||||
write these one by one.
|
||||
|
||||
If you have spi_init() functions or the like that are called from your
|
||||
board then the build will fail. Remove these calls and make a note of the
|
||||
init that needs to be done.
|
||||
|
||||
|
||||
7. Set up your platform data structure
|
||||
|
||||
This will hold the information your driver to operate, like its hardware
|
||||
address or maximum frequency.
|
||||
|
||||
You may already have a struct like this, or you may need to create one
|
||||
from some of the #defines or global variables in the driver.
|
||||
|
||||
Note that this information is not the run-time information. It should not
|
||||
include state that changes. It should be fixed throughout the live of
|
||||
U-Boot. Run-time information comes later.
|
||||
|
||||
Here is what was in the exynos spi driver:
|
||||
|
||||
struct spi_bus {
|
||||
enum periph_id periph_id;
|
||||
s32 frequency; /* Default clock frequency, -1 for none */
|
||||
struct exynos_spi *regs;
|
||||
int inited; /* 1 if this bus is ready for use */
|
||||
int node;
|
||||
uint deactivate_delay_us; /* Delay to wait after deactivate */
|
||||
};
|
||||
|
||||
Of these, inited is handled by DM and node is the device tree node, which
|
||||
DM tells you. The name is not quite right. So in this case we would use:
|
||||
|
||||
struct exynos_spi_platdata {
|
||||
enum periph_id periph_id;
|
||||
s32 frequency; /* Default clock frequency, -1 for none */
|
||||
struct exynos_spi *regs;
|
||||
uint deactivate_delay_us; /* Delay to wait after deactivate */
|
||||
};
|
||||
|
||||
|
||||
8a. Write ofdata_to_platdata() [for device tree only]
|
||||
|
||||
This method will convert information in the device tree node into a C
|
||||
structure in your driver (called platform data). If you are not using
|
||||
device tree, go to 8b.
|
||||
|
||||
DM will automatically allocate the struct for us when we are using device
|
||||
tree, but we need to tell it the size:
|
||||
|
||||
U_BOOT_DRIVER(spi_exynos) = {
|
||||
...
|
||||
.platdata_auto_alloc_size = sizeof(struct exynos_spi_platdata),
|
||||
|
||||
|
||||
Here is a sample function. It gets a pointer to the platform data and
|
||||
fills in the fields from device tree.
|
||||
|
||||
static int exynos_spi_ofdata_to_platdata(struct udevice *bus)
|
||||
{
|
||||
struct exynos_spi_platdata *plat = bus->platdata;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node = bus->of_offset;
|
||||
|
||||
plat->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
|
||||
plat->periph_id = pinmux_decode_periph_id(blob, node);
|
||||
|
||||
if (plat->periph_id == PERIPH_ID_NONE) {
|
||||
debug("%s: Invalid peripheral ID %d\n", __func__,
|
||||
plat->periph_id);
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
/* Use 500KHz as a suitable default */
|
||||
plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
|
||||
500000);
|
||||
plat->deactivate_delay_us = fdtdec_get_int(blob, node,
|
||||
"spi-deactivate-delay", 0);
|
||||
debug("%s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
|
||||
__func__, plat->regs, plat->periph_id, plat->frequency,
|
||||
plat->deactivate_delay_us);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
8b. Add the platform data [non-device-tree only]
|
||||
|
||||
Specify this data in a U_BOOT_DEVICE() declaration in your board file:
|
||||
|
||||
struct exynos_spi_platdata platdata_spi0 = {
|
||||
.periph_id = ...
|
||||
.frequency = ...
|
||||
.regs = ...
|
||||
.deactivate_delay_us = ...
|
||||
};
|
||||
|
||||
U_BOOT_DEVICE(board_spi0) = {
|
||||
.name = "exynos_spi",
|
||||
.platdata = &platdata_spi0,
|
||||
};
|
||||
|
||||
You will unfortunately need to put the struct into a header file in this
|
||||
case so that your board file can use it.
|
||||
|
||||
|
||||
9. Add the device private data
|
||||
|
||||
Most devices have some private data which they use to keep track of things
|
||||
while active. This is the run-time information and needs to be stored in
|
||||
a structure. There is probably a structure in the driver that includes a
|
||||
'struct spi_slave', so you can use that.
|
||||
|
||||
struct exynos_spi_slave {
|
||||
struct spi_slave slave;
|
||||
struct exynos_spi *regs;
|
||||
unsigned int freq; /* Default frequency */
|
||||
unsigned int mode;
|
||||
enum periph_id periph_id; /* Peripheral ID for this device */
|
||||
unsigned int fifo_size;
|
||||
int skip_preamble;
|
||||
struct spi_bus *bus; /* Pointer to our SPI bus info */
|
||||
ulong last_transaction_us; /* Time of last transaction end */
|
||||
};
|
||||
|
||||
|
||||
We should rename this to make its purpose more obvious, and get rid of
|
||||
the slave structure, so we have:
|
||||
|
||||
struct exynos_spi_priv {
|
||||
struct exynos_spi *regs;
|
||||
unsigned int freq; /* Default frequency */
|
||||
unsigned int mode;
|
||||
enum periph_id periph_id; /* Peripheral ID for this device */
|
||||
unsigned int fifo_size;
|
||||
int skip_preamble;
|
||||
ulong last_transaction_us; /* Time of last transaction end */
|
||||
};
|
||||
|
||||
|
||||
DM can auto-allocate this also:
|
||||
|
||||
U_BOOT_DRIVER(spi_exynos) = {
|
||||
...
|
||||
.priv_auto_alloc_size = sizeof(struct exynos_spi_priv),
|
||||
|
||||
|
||||
Note that this is created before the probe method is called, and destroyed
|
||||
after the remove method is called. It will be zeroed when the probe
|
||||
method is called.
|
||||
|
||||
|
||||
10. Add the probe() and remove() methods
|
||||
|
||||
Note: It's a good idea to build repeatedly as you are working, to avoid a
|
||||
huge amount of work getting things compiling at the end.
|
||||
|
||||
The probe method is supposed to set up the hardware. U-Boot used to use
|
||||
spi_setup_slave() to do this. So take a look at this function and see
|
||||
what you can copy out to set things up.
|
||||
|
||||
|
||||
static int exynos_spi_probe(struct udevice *bus)
|
||||
{
|
||||
struct exynos_spi_platdata *plat = dev_get_platdata(bus);
|
||||
struct exynos_spi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
priv->regs = plat->regs;
|
||||
if (plat->periph_id == PERIPH_ID_SPI1 ||
|
||||
plat->periph_id == PERIPH_ID_SPI2)
|
||||
priv->fifo_size = 64;
|
||||
else
|
||||
priv->fifo_size = 256;
|
||||
|
||||
priv->skip_preamble = 0;
|
||||
priv->last_transaction_us = timer_get_us();
|
||||
priv->freq = plat->frequency;
|
||||
priv->periph_id = plat->periph_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
This implementation doesn't actually touch the hardware, which is somewhat
|
||||
unusual for a driver. In this case we will do that when the device is
|
||||
claimed by something that wants to use the SPI bus.
|
||||
|
||||
For remove we could shut down the clocks, but in this case there is
|
||||
nothing to do. DM frees any memory that it allocated, so we can just
|
||||
remove exynos_spi_remove() and its reference in U_BOOT_DRIVER.
|
||||
|
||||
|
||||
11. Implement set_speed()
|
||||
|
||||
This should set up clocks so that the SPI bus is running at the right
|
||||
speed. With the old API spi_claim_bus() would normally do this and several
|
||||
of the following functions, so let's look at that function:
|
||||
|
||||
int spi_claim_bus(struct spi_slave *slave)
|
||||
{
|
||||
struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
|
||||
struct exynos_spi *regs = spi_slave->regs;
|
||||
u32 reg = 0;
|
||||
int ret;
|
||||
|
||||
ret = set_spi_clk(spi_slave->periph_id,
|
||||
spi_slave->freq);
|
||||
if (ret < 0) {
|
||||
debug("%s: Failed to setup spi clock\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
|
||||
|
||||
spi_flush_fifo(slave);
|
||||
|
||||
reg = readl(®s->ch_cfg);
|
||||
reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
|
||||
|
||||
if (spi_slave->mode & SPI_CPHA)
|
||||
reg |= SPI_CH_CPHA_B;
|
||||
|
||||
if (spi_slave->mode & SPI_CPOL)
|
||||
reg |= SPI_CH_CPOL_L;
|
||||
|
||||
writel(reg, ®s->ch_cfg);
|
||||
writel(SPI_FB_DELAY_180, ®s->fb_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
It sets up the speed, mode, pinmux, feedback delay and clears the FIFOs.
|
||||
With DM these will happen in separate methods.
|
||||
|
||||
|
||||
Here is an example for the speed part:
|
||||
|
||||
static int exynos_spi_set_speed(struct udevice *bus, uint speed)
|
||||
{
|
||||
struct exynos_spi_platdata *plat = bus->platdata;
|
||||
struct exynos_spi_priv *priv = dev_get_priv(bus);
|
||||
int ret;
|
||||
|
||||
if (speed > plat->frequency)
|
||||
speed = plat->frequency;
|
||||
ret = set_spi_clk(priv->periph_id, speed);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->freq = speed;
|
||||
debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
12. Implement set_mode()
|
||||
|
||||
This should adjust the SPI mode (polarity, etc.). Again this code probably
|
||||
comes from the old spi_claim_bus(). Here is an example:
|
||||
|
||||
|
||||
static int exynos_spi_set_mode(struct udevice *bus, uint mode)
|
||||
{
|
||||
struct exynos_spi_priv *priv = dev_get_priv(bus);
|
||||
uint32_t reg;
|
||||
|
||||
reg = readl(&priv->regs->ch_cfg);
|
||||
reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
|
||||
|
||||
if (mode & SPI_CPHA)
|
||||
reg |= SPI_CH_CPHA_B;
|
||||
|
||||
if (mode & SPI_CPOL)
|
||||
reg |= SPI_CH_CPOL_L;
|
||||
|
||||
writel(reg, &priv->regs->ch_cfg);
|
||||
priv->mode = mode;
|
||||
debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
13. Implement claim_bus()
|
||||
|
||||
This is where a client wants to make use of the bus, so claims it first.
|
||||
At this point we need to make sure everything is set up ready for data
|
||||
transfer. Note that this function is wholly internal to the driver - at
|
||||
present the SPI uclass never calls it.
|
||||
|
||||
Here again we look at the old claim function and see some code that is
|
||||
needed. It is anything unrelated to speed and mode:
|
||||
|
||||
static int exynos_spi_claim_bus(struct udevice *bus)
|
||||
{
|
||||
struct exynos_spi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
|
||||
spi_flush_fifo(priv->regs);
|
||||
|
||||
writel(SPI_FB_DELAY_180, &priv->regs->fb_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
The spi_flush_fifo() function is in the removed part of the code, so we
|
||||
need to expose it again (perhaps with an #endif before it and '#if 0'
|
||||
after it). It only needs access to priv->regs which is why we have
|
||||
passed that in:
|
||||
|
||||
/**
|
||||
* Flush spi tx, rx fifos and reset the SPI controller
|
||||
*
|
||||
* @param regs Pointer to SPI registers
|
||||
*/
|
||||
static void spi_flush_fifo(struct exynos_spi *regs)
|
||||
{
|
||||
clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
|
||||
clrbits_le32(®s->ch_cfg, SPI_CH_RST);
|
||||
setbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
|
||||
}
|
||||
|
||||
|
||||
14. Implement release_bus()
|
||||
|
||||
This releases the bus - in our example the old code in spi_release_bus()
|
||||
is a call to spi_flush_fifo, so we add:
|
||||
|
||||
static int exynos_spi_release_bus(struct udevice *bus)
|
||||
{
|
||||
struct exynos_spi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
spi_flush_fifo(priv->regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
15. Implement xfer()
|
||||
|
||||
This is the final method that we need to create, and it is where all the
|
||||
work happens. The method parameters are the same as the old spi_xfer() with
|
||||
the addition of a 'struct udevice' so conversion is pretty easy. Start
|
||||
by copying the contents of spi_xfer() to your new xfer() method and proceed
|
||||
from there.
|
||||
|
||||
If (flags & SPI_XFER_BEGIN) is non-zero then xfer() normally calls an
|
||||
activate function, something like this:
|
||||
|
||||
void spi_cs_activate(struct spi_slave *slave)
|
||||
{
|
||||
struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
|
||||
|
||||
/* If it's too soon to do another transaction, wait */
|
||||
if (spi_slave->bus->deactivate_delay_us &&
|
||||
spi_slave->last_transaction_us) {
|
||||
ulong delay_us; /* The delay completed so far */
|
||||
delay_us = timer_get_us() - spi_slave->last_transaction_us;
|
||||
if (delay_us < spi_slave->bus->deactivate_delay_us)
|
||||
udelay(spi_slave->bus->deactivate_delay_us - delay_us);
|
||||
}
|
||||
|
||||
clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
|
||||
debug("Activate CS, bus %d\n", spi_slave->slave.bus);
|
||||
spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
|
||||
}
|
||||
|
||||
The new version looks like this:
|
||||
|
||||
static void spi_cs_activate(struct udevice *dev)
|
||||
{
|
||||
struct udevice *bus = dev->parent;
|
||||
struct exynos_spi_platdata *pdata = dev_get_platdata(bus);
|
||||
struct exynos_spi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
/* If it's too soon to do another transaction, wait */
|
||||
if (pdata->deactivate_delay_us &&
|
||||
priv->last_transaction_us) {
|
||||
ulong delay_us; /* The delay completed so far */
|
||||
delay_us = timer_get_us() - priv->last_transaction_us;
|
||||
if (delay_us < pdata->deactivate_delay_us)
|
||||
udelay(pdata->deactivate_delay_us - delay_us);
|
||||
}
|
||||
|
||||
clrbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT);
|
||||
debug("Activate CS, bus '%s'\n", bus->name);
|
||||
priv->skip_preamble = priv->mode & SPI_PREAMBLE;
|
||||
}
|
||||
|
||||
All we have really done here is change the pointers and print the device name
|
||||
instead of the bus number. Other local static functions can be treated in
|
||||
the same way.
|
||||
|
||||
|
||||
16. Set up the per-child data and child pre-probe function
|
||||
|
||||
To minimise the pain and complexity of the SPI subsystem while the driver
|
||||
model change-over is in place, struct spi_slave is used to reference a
|
||||
SPI bus slave, even though that slave is actually a struct udevice. In fact
|
||||
struct spi_slave is the device's child data. We need to make sure this space
|
||||
is available. It is possible to allocate more space that struct spi_slave
|
||||
needs, but this is the minimum.
|
||||
|
||||
U_BOOT_DRIVER(exynos_spi) = {
|
||||
...
|
||||
.per_child_auto_alloc_size = sizeof(struct spi_slave),
|
||||
}
|
||||
|
||||
|
||||
17. Optional: Set up cs_info() if you want it
|
||||
|
||||
Sometimes it is useful to know whether a SPI chip select is valid, but this
|
||||
is not obvious from outside the driver. In this case you can provide a
|
||||
method for cs_info() to deal with this. If you don't provide it, then the
|
||||
device tree will be used to determine what chip selects are valid.
|
||||
|
||||
Return -ENODEV if the supplied chip select is invalid, or 0 if it is valid.
|
||||
If you don't provide the cs_info() method, -ENODEV is assumed for all
|
||||
chip selects that do not appear in the device tree.
|
||||
|
||||
|
||||
18. Test it
|
||||
|
||||
Now that you have the code written and it compiles, try testing it using
|
||||
the 'sf test' command. You may need to enable CONFIG_CMD_SF_TEST for your
|
||||
board.
|
||||
|
||||
|
||||
19. Prepare patches and send them to the mailing lists
|
||||
|
||||
You can use 'tools/patman/patman' to prepare, check and send patches for
|
||||
your work. See the README for details.
|
|
@ -5,3 +5,4 @@
|
|||
#
|
||||
|
||||
obj-y := device.o lists.o root.o uclass.o util.o
|
||||
obj-$(CONFIG_OF_CONTROL) += simple-bus.o
|
||||
|
|
|
@ -232,7 +232,7 @@ static void device_free(struct udevice *dev)
|
|||
}
|
||||
}
|
||||
|
||||
int device_probe(struct udevice *dev)
|
||||
int device_probe_child(struct udevice *dev, void *parent_priv)
|
||||
{
|
||||
struct driver *drv;
|
||||
int size = 0;
|
||||
|
@ -282,6 +282,8 @@ int device_probe(struct udevice *dev)
|
|||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
if (parent_priv)
|
||||
memcpy(dev->parent_priv, parent_priv, size);
|
||||
}
|
||||
|
||||
ret = device_probe(dev->parent);
|
||||
|
@ -335,6 +337,11 @@ fail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int device_probe(struct udevice *dev)
|
||||
{
|
||||
return device_probe_child(dev, NULL);
|
||||
}
|
||||
|
||||
int device_remove(struct udevice *dev)
|
||||
{
|
||||
struct driver *drv;
|
||||
|
@ -514,3 +521,30 @@ int device_get_child_by_of_offset(struct udevice *parent, int seq,
|
|||
ret = device_find_child_by_of_offset(parent, seq, &dev);
|
||||
return device_get_device_tail(dev, ret, devp);
|
||||
}
|
||||
|
||||
int device_find_first_child(struct udevice *parent, struct udevice **devp)
|
||||
{
|
||||
if (list_empty(&parent->child_head)) {
|
||||
*devp = NULL;
|
||||
} else {
|
||||
*devp = list_first_entry(&parent->child_head, struct udevice,
|
||||
sibling_node);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int device_find_next_child(struct udevice **devp)
|
||||
{
|
||||
struct udevice *dev = *devp;
|
||||
struct udevice *parent = dev->parent;
|
||||
|
||||
if (list_is_last(&dev->sibling_node, &parent->child_head)) {
|
||||
*devp = NULL;
|
||||
} else {
|
||||
*devp = list_entry(dev->sibling_node.next, struct udevice,
|
||||
sibling_node);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,19 +24,12 @@ struct driver *lists_driver_lookup_name(const char *name)
|
|||
ll_entry_start(struct driver, driver);
|
||||
const int n_ents = ll_entry_count(struct driver, driver);
|
||||
struct driver *entry;
|
||||
int len;
|
||||
|
||||
if (!drv || !n_ents)
|
||||
return NULL;
|
||||
|
||||
len = strlen(name);
|
||||
|
||||
for (entry = drv; entry != drv + n_ents; entry++) {
|
||||
if (strncmp(name, entry->name, len))
|
||||
continue;
|
||||
|
||||
/* Full match */
|
||||
if (len == strlen(entry->name))
|
||||
if (!strcmp(name, entry->name))
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
|
33
drivers/core/simple-bus.c
Normal file
33
drivers/core/simple-bus.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/root.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int simple_bus_post_bind(struct udevice *dev)
|
||||
{
|
||||
return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(simple_bus) = {
|
||||
.id = UCLASS_SIMPLE_BUS,
|
||||
.name = "simple_bus",
|
||||
.post_bind = simple_bus_post_bind,
|
||||
};
|
||||
|
||||
static const struct udevice_id generic_simple_bus_ids[] = {
|
||||
{ .compatible = "simple-bus" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(simple_bus_drv) = {
|
||||
.name = "generic_simple_bus",
|
||||
.id = UCLASS_SIMPLE_BUS,
|
||||
.of_match = generic_simple_bus_ids,
|
||||
};
|
|
@ -60,10 +60,6 @@ static int uclass_add(enum uclass_id id, struct uclass **ucp)
|
|||
id);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (uc_drv->ops) {
|
||||
dm_warn("No ops for uclass id %d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
uc = calloc(1, sizeof(*uc));
|
||||
if (!uc)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <errno.h>
|
||||
#include <div64.h>
|
||||
#include <dfu.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
static long dfu_get_medium_size_sf(struct dfu_entity *dfu)
|
||||
|
|
|
@ -6,73 +6,207 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
inline int gpio_is_valid(unsigned gpio)
|
||||
#define GPIO_NAME_SIZE 20
|
||||
|
||||
struct bcm2835_gpios {
|
||||
char label[BCM2835_GPIO_COUNT][GPIO_NAME_SIZE];
|
||||
struct bcm2835_gpio_regs *reg;
|
||||
};
|
||||
|
||||
/**
|
||||
* gpio_is_requested() - check if a GPIO has been requested
|
||||
*
|
||||
* @bank: Bank to check
|
||||
* @offset: GPIO offset within bank to check
|
||||
* @return true if marked as requested, false if not
|
||||
*/
|
||||
static inline bool gpio_is_requested(struct bcm2835_gpios *gpios, int offset)
|
||||
{
|
||||
return (gpio < BCM2835_GPIO_COUNT);
|
||||
return *gpios->label[offset] != '\0';
|
||||
}
|
||||
|
||||
int gpio_request(unsigned gpio, const char *label)
|
||||
static int check_requested(struct udevice *dev, unsigned offset,
|
||||
const char *func)
|
||||
{
|
||||
return !gpio_is_valid(gpio);
|
||||
}
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
|
||||
if (!gpio_is_requested(gpios, offset)) {
|
||||
printf("omap_gpio: %s: error: gpio %s%d not requested\n",
|
||||
func, uc_priv->bank_name, offset);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
int gpio_free(unsigned gpio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_direction_input(unsigned gpio)
|
||||
static int bcm2835_gpio_request(struct udevice *dev, unsigned offset,
|
||||
const char *label)
|
||||
{
|
||||
struct bcm2835_gpio_regs *reg =
|
||||
(struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
|
||||
if (gpio_is_requested(gpios, offset))
|
||||
return -EBUSY;
|
||||
|
||||
strncpy(gpios->label[offset], label, GPIO_NAME_SIZE);
|
||||
gpios->label[offset][GPIO_NAME_SIZE - 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835_gpio_free(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_requested(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
gpios->label[offset][0] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
|
||||
{
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
unsigned val;
|
||||
|
||||
val = readl(®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
|
||||
val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
|
||||
writel(val, ®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_direction_output(unsigned gpio, int value)
|
||||
static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio,
|
||||
int value)
|
||||
{
|
||||
struct bcm2835_gpio_regs *reg =
|
||||
(struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
unsigned val;
|
||||
|
||||
gpio_set_value(gpio, value);
|
||||
|
||||
val = readl(®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
|
||||
val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
|
||||
writel(val, ®->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_get_value(unsigned gpio)
|
||||
static bool bcm2835_gpio_is_output(const struct bcm2835_gpios *gpios, int gpio)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
|
||||
val &= BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio);
|
||||
return val ? true : false;
|
||||
}
|
||||
|
||||
static int bcm2835_get_value(const struct bcm2835_gpios *gpios, unsigned gpio)
|
||||
{
|
||||
struct bcm2835_gpio_regs *reg =
|
||||
(struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
|
||||
unsigned val;
|
||||
|
||||
val = readl(®->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
|
||||
val = readl(&gpios->reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
|
||||
|
||||
return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1;
|
||||
}
|
||||
|
||||
int gpio_set_value(unsigned gpio, int value)
|
||||
static int bcm2835_gpio_get_value(struct udevice *dev, unsigned gpio)
|
||||
{
|
||||
struct bcm2835_gpio_regs *reg =
|
||||
(struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
|
||||
u32 *output_reg = value ? reg->gpset : reg->gpclr;
|
||||
const struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
|
||||
return bcm2835_get_value(gpios, gpio);
|
||||
}
|
||||
|
||||
static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio,
|
||||
int value)
|
||||
{
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
u32 *output_reg = value ? gpios->reg->gpset : gpios->reg->gpclr;
|
||||
|
||||
writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio),
|
||||
&output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
|
||||
if (!gpio_is_requested(gpios, offset))
|
||||
return GPIOF_UNUSED;
|
||||
|
||||
/* GPIOF_FUNC is not implemented yet */
|
||||
if (bcm2835_gpio_is_output(gpios, offset))
|
||||
return GPIOF_OUTPUT;
|
||||
else
|
||||
return GPIOF_INPUT;
|
||||
}
|
||||
|
||||
static int bcm2835_gpio_get_state(struct udevice *dev, unsigned int offset,
|
||||
char *buf, int bufsize)
|
||||
{
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
const char *label;
|
||||
bool requested;
|
||||
bool is_output;
|
||||
int size;
|
||||
|
||||
label = gpios->label[offset];
|
||||
is_output = bcm2835_gpio_is_output(gpios, offset);
|
||||
size = snprintf(buf, bufsize, "%s%d: ",
|
||||
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
|
||||
buf += size;
|
||||
bufsize -= size;
|
||||
requested = gpio_is_requested(gpios, offset);
|
||||
snprintf(buf, bufsize, "%s: %d [%c]%s%s",
|
||||
is_output ? "out" : " in",
|
||||
bcm2835_get_value(gpios, offset),
|
||||
requested ? 'x' : ' ',
|
||||
requested ? " " : "",
|
||||
label);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops gpio_bcm2835_ops = {
|
||||
.request = bcm2835_gpio_request,
|
||||
.free = bcm2835_gpio_free,
|
||||
.direction_input = bcm2835_gpio_direction_input,
|
||||
.direction_output = bcm2835_gpio_direction_output,
|
||||
.get_value = bcm2835_gpio_get_value,
|
||||
.set_value = bcm2835_gpio_set_value,
|
||||
.get_function = bcm2835_gpio_get_function,
|
||||
.get_state = bcm2835_gpio_get_state,
|
||||
};
|
||||
|
||||
static int bcm2835_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
struct bcm2835_gpios *gpios = dev_get_priv(dev);
|
||||
struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
|
||||
uc_priv->bank_name = "GPIO";
|
||||
uc_priv->gpio_count = BCM2835_GPIO_COUNT;
|
||||
gpios->reg = (struct bcm2835_gpio_regs *)plat->base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(gpio_bcm2835) = {
|
||||
.name = "gpio_bcm2835",
|
||||
.id = UCLASS_GPIO,
|
||||
.ops = &gpio_bcm2835_ops,
|
||||
.probe = bcm2835_gpio_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct bcm2835_gpios),
|
||||
};
|
||||
|
|
|
@ -8,16 +8,31 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <errno.h>
|
||||
|
||||
enum mxc_gpio_direction {
|
||||
MXC_GPIO_DIRECTION_IN,
|
||||
MXC_GPIO_DIRECTION_OUT,
|
||||
};
|
||||
|
||||
#define GPIO_NAME_SIZE 20
|
||||
#define GPIO_PER_BANK 32
|
||||
|
||||
struct mxc_gpio_plat {
|
||||
struct gpio_regs *regs;
|
||||
};
|
||||
|
||||
struct mxc_bank_info {
|
||||
char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
|
||||
struct gpio_regs *regs;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_DM_GPIO
|
||||
#define GPIO_TO_PORT(n) (n / 32)
|
||||
|
||||
/* GPIO port description */
|
||||
|
@ -134,3 +149,290 @@ int gpio_direction_output(unsigned gpio, int value)
|
|||
|
||||
return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_GPIO
|
||||
/**
|
||||
* gpio_is_requested() - check if a GPIO has been requested
|
||||
*
|
||||
* @bank: Bank to check
|
||||
* @offset: GPIO offset within bank to check
|
||||
* @return true if marked as requested, false if not
|
||||
*/
|
||||
static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
|
||||
{
|
||||
return *bank->label[offset] != '\0';
|
||||
}
|
||||
|
||||
static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(®s->gpio_dir);
|
||||
|
||||
return val & (1 << offset) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
|
||||
enum mxc_gpio_direction direction)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
l = readl(®s->gpio_dir);
|
||||
|
||||
switch (direction) {
|
||||
case MXC_GPIO_DIRECTION_OUT:
|
||||
l |= 1 << offset;
|
||||
break;
|
||||
case MXC_GPIO_DIRECTION_IN:
|
||||
l &= ~(1 << offset);
|
||||
}
|
||||
writel(l, ®s->gpio_dir);
|
||||
}
|
||||
|
||||
static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
|
||||
int value)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
l = readl(®s->gpio_dr);
|
||||
if (value)
|
||||
l |= 1 << offset;
|
||||
else
|
||||
l &= ~(1 << offset);
|
||||
writel(l, ®s->gpio_dr);
|
||||
}
|
||||
|
||||
static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
|
||||
{
|
||||
return (readl(®s->gpio_psr) >> offset) & 0x01;
|
||||
}
|
||||
|
||||
static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
|
||||
{
|
||||
return (readl(®s->gpio_dr) >> offset) & 0x01;
|
||||
}
|
||||
|
||||
static int check_requested(struct udevice *dev, unsigned offset,
|
||||
const char *func)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
|
||||
if (!gpio_is_requested(bank, offset)) {
|
||||
printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
|
||||
func, uc_priv->bank_name, offset);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set GPIO pin 'gpio' as an input */
|
||||
static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_requested(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure GPIO direction as input. */
|
||||
mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set GPIO pin 'gpio' as an output, with polarity 'value' */
|
||||
static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_requested(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure GPIO output value. */
|
||||
mxc_gpio_bank_set_value(bank->regs, offset, value);
|
||||
|
||||
/* Configure GPIO direction as output. */
|
||||
mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read GPIO IN value of pin 'gpio' */
|
||||
static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_requested(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mxc_gpio_bank_get_value(bank->regs, offset);
|
||||
}
|
||||
|
||||
/* write GPIO OUT value to pin 'gpio' */
|
||||
static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_requested(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mxc_gpio_bank_set_value(bank->regs, offset, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
|
||||
char *buf, int bufsize)
|
||||
{
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
const char *label;
|
||||
bool requested;
|
||||
bool is_output;
|
||||
int size;
|
||||
|
||||
label = bank->label[offset];
|
||||
is_output = mxc_gpio_is_output(bank->regs, offset);
|
||||
size = snprintf(buf, bufsize, "%s%d: ",
|
||||
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
|
||||
buf += size;
|
||||
bufsize -= size;
|
||||
requested = gpio_is_requested(bank, offset);
|
||||
snprintf(buf, bufsize, "%s: %d [%c]%s%s",
|
||||
is_output ? "out" : " in",
|
||||
is_output ?
|
||||
mxc_gpio_bank_get_output_value(bank->regs, offset) :
|
||||
mxc_gpio_bank_get_value(bank->regs, offset),
|
||||
requested ? 'x' : ' ',
|
||||
requested ? " " : "",
|
||||
label);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_gpio_request(struct udevice *dev, unsigned offset,
|
||||
const char *label)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
|
||||
if (gpio_is_requested(bank, offset))
|
||||
return -EBUSY;
|
||||
|
||||
strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
|
||||
bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_gpio_free(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_requested(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
bank->label[offset][0] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
|
||||
if (!gpio_is_requested(bank, offset))
|
||||
return GPIOF_UNUSED;
|
||||
|
||||
/* GPIOF_FUNC is not implemented yet */
|
||||
if (mxc_gpio_is_output(bank->regs, offset))
|
||||
return GPIOF_OUTPUT;
|
||||
else
|
||||
return GPIOF_INPUT;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops gpio_mxc_ops = {
|
||||
.request = mxc_gpio_request,
|
||||
.free = mxc_gpio_free,
|
||||
.direction_input = mxc_gpio_direction_input,
|
||||
.direction_output = mxc_gpio_direction_output,
|
||||
.get_value = mxc_gpio_get_value,
|
||||
.set_value = mxc_gpio_set_value,
|
||||
.get_function = mxc_gpio_get_function,
|
||||
.get_state = mxc_gpio_get_state,
|
||||
};
|
||||
|
||||
static const struct mxc_gpio_plat mxc_plat[] = {
|
||||
{ (struct gpio_regs *)GPIO1_BASE_ADDR },
|
||||
{ (struct gpio_regs *)GPIO2_BASE_ADDR },
|
||||
{ (struct gpio_regs *)GPIO3_BASE_ADDR },
|
||||
#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
|
||||
defined(CONFIG_MX53) || defined(CONFIG_MX6)
|
||||
{ (struct gpio_regs *)GPIO4_BASE_ADDR },
|
||||
#endif
|
||||
#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
|
||||
{ (struct gpio_regs *)GPIO5_BASE_ADDR },
|
||||
{ (struct gpio_regs *)GPIO6_BASE_ADDR },
|
||||
#endif
|
||||
#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
|
||||
{ (struct gpio_regs *)GPIO7_BASE_ADDR },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int mxc_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
struct mxc_gpio_plat *plat = dev_get_platdata(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
int banknum;
|
||||
char name[18], *str;
|
||||
|
||||
banknum = plat - mxc_plat;
|
||||
sprintf(name, "GPIO%d_", banknum + 1);
|
||||
str = strdup(name);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
uc_priv->bank_name = str;
|
||||
uc_priv->gpio_count = GPIO_PER_BANK;
|
||||
bank->regs = plat->regs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(gpio_mxc) = {
|
||||
.name = "gpio_mxc",
|
||||
.id = UCLASS_GPIO,
|
||||
.ops = &gpio_mxc_ops,
|
||||
.probe = mxc_gpio_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct mxc_bank_info),
|
||||
};
|
||||
|
||||
U_BOOT_DEVICES(mxc_gpios) = {
|
||||
{ "gpio_mxc", &mxc_plat[0] },
|
||||
{ "gpio_mxc", &mxc_plat[1] },
|
||||
{ "gpio_mxc", &mxc_plat[2] },
|
||||
#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
|
||||
defined(CONFIG_MX53) || defined(CONFIG_MX6)
|
||||
{ "gpio_mxc", &mxc_plat[3] },
|
||||
#endif
|
||||
#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
|
||||
{ "gpio_mxc", &mxc_plat[4] },
|
||||
{ "gpio_mxc", &mxc_plat[5] },
|
||||
#endif
|
||||
#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
|
||||
{ "gpio_mxc", &mxc_plat[6] },
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -6,120 +6,72 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <dm/device-internal.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define S5P_GPIO_GET_PIN(x) (x % GPIO_PER_BANK)
|
||||
|
||||
#define CON_MASK(x) (0xf << ((x) << 2))
|
||||
#define CON_SFR(x, v) ((v) << ((x) << 2))
|
||||
#define CON_MASK(val) (0xf << ((val) << 2))
|
||||
#define CON_SFR(gpio, cfg) ((cfg) << ((gpio) << 2))
|
||||
#define CON_SFR_UNSHIFT(val, gpio) ((val) >> ((gpio) << 2))
|
||||
|
||||
#define DAT_MASK(x) (0x1 << (x))
|
||||
#define DAT_SET(x) (0x1 << (x))
|
||||
#define DAT_MASK(gpio) (0x1 << (gpio))
|
||||
#define DAT_SET(gpio) (0x1 << (gpio))
|
||||
|
||||
#define PULL_MASK(x) (0x3 << ((x) << 1))
|
||||
#define PULL_MODE(x, v) ((v) << ((x) << 1))
|
||||
#define PULL_MASK(gpio) (0x3 << ((gpio) << 1))
|
||||
#define PULL_MODE(gpio, pull) ((pull) << ((gpio) << 1))
|
||||
|
||||
#define DRV_MASK(x) (0x3 << ((x) << 1))
|
||||
#define DRV_SET(x, m) ((m) << ((x) << 1))
|
||||
#define RATE_MASK(x) (0x1 << (x + 16))
|
||||
#define RATE_SET(x) (0x1 << (x + 16))
|
||||
#define DRV_MASK(gpio) (0x3 << ((gpio) << 1))
|
||||
#define DRV_SET(gpio, mode) ((mode) << ((gpio) << 1))
|
||||
#define RATE_MASK(gpio) (0x1 << (gpio + 16))
|
||||
#define RATE_SET(gpio) (0x1 << (gpio + 16))
|
||||
|
||||
#define name_to_gpio(n) s5p_name_to_gpio(n)
|
||||
static inline int s5p_name_to_gpio(const char *name)
|
||||
#define GPIO_NAME_SIZE 20
|
||||
|
||||
/* Platform data for each bank */
|
||||
struct exynos_gpio_platdata {
|
||||
struct s5p_gpio_bank *bank;
|
||||
const char *bank_name; /* Name of port, e.g. 'gpa0" */
|
||||
};
|
||||
|
||||
/* Information about each bank at run-time */
|
||||
struct exynos_bank_info {
|
||||
char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
|
||||
struct s5p_gpio_bank *bank;
|
||||
};
|
||||
|
||||
static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
|
||||
{
|
||||
unsigned num, irregular_set_number, irregular_bank_base;
|
||||
const struct gpio_name_num_table *tabp;
|
||||
char this_bank, bank_name, irregular_bank_name;
|
||||
char *endp;
|
||||
const struct gpio_info *data;
|
||||
unsigned int upto;
|
||||
int i, count;
|
||||
|
||||
/*
|
||||
* The gpio name starts with either 'g' or 'gp' followed by the bank
|
||||
* name character. Skip one or two characters depending on the prefix.
|
||||
*/
|
||||
if (name[0] == 'g' && name[1] == 'p')
|
||||
name += 2;
|
||||
else if (name[0] == 'g')
|
||||
name++;
|
||||
else
|
||||
return -1; /* Name must start with 'g' */
|
||||
data = get_gpio_data();
|
||||
count = get_bank_num();
|
||||
upto = 0;
|
||||
|
||||
bank_name = *name++;
|
||||
if (!*name)
|
||||
return -1; /* At least one digit is required/expected. */
|
||||
|
||||
/*
|
||||
* On both exynos5 and exynos5420 architectures there is a bank of
|
||||
* GPIOs which does not fall into the regular address pattern. Those
|
||||
* banks are c4 on Exynos5 and y7 on Exynos5420. The rest of the below
|
||||
* assignments help to handle these irregularities.
|
||||
*/
|
||||
#if defined(CONFIG_EXYNOS4) || defined(CONFIG_EXYNOS5)
|
||||
if (cpu_is_exynos5()) {
|
||||
if (proid_is_exynos5420()) {
|
||||
tabp = exynos5420_gpio_table;
|
||||
irregular_bank_name = 'y';
|
||||
irregular_set_number = '7';
|
||||
irregular_bank_base = EXYNOS5420_GPIO_Y70;
|
||||
} else {
|
||||
tabp = exynos5_gpio_table;
|
||||
irregular_bank_name = 'c';
|
||||
irregular_set_number = '4';
|
||||
irregular_bank_base = EXYNOS5_GPIO_C40;
|
||||
for (i = 0; i < count; i++) {
|
||||
debug("i=%d, upto=%d\n", i, upto);
|
||||
if (gpio < data->max_gpio) {
|
||||
struct s5p_gpio_bank *bank;
|
||||
bank = (struct s5p_gpio_bank *)data->reg_addr;
|
||||
bank += (gpio - upto) / GPIO_PER_BANK;
|
||||
debug("gpio=%d, bank=%p\n", gpio, bank);
|
||||
return bank;
|
||||
}
|
||||
} else {
|
||||
if (proid_is_exynos4412())
|
||||
tabp = exynos4x12_gpio_table;
|
||||
else
|
||||
tabp = exynos4_gpio_table;
|
||||
irregular_bank_name = 0;
|
||||
irregular_set_number = 0;
|
||||
irregular_bank_base = 0;
|
||||
|
||||
upto = data->max_gpio;
|
||||
data++;
|
||||
}
|
||||
#else
|
||||
if (cpu_is_s5pc110())
|
||||
tabp = s5pc110_gpio_table;
|
||||
else
|
||||
tabp = s5pc100_gpio_table;
|
||||
irregular_bank_name = 0;
|
||||
irregular_set_number = 0;
|
||||
irregular_bank_base = 0;
|
||||
#endif
|
||||
|
||||
this_bank = tabp->bank;
|
||||
do {
|
||||
if (bank_name == this_bank) {
|
||||
unsigned pin_index; /* pin number within the bank */
|
||||
if ((bank_name == irregular_bank_name) &&
|
||||
(name[0] == irregular_set_number)) {
|
||||
pin_index = name[1] - '0';
|
||||
/* Irregular sets have 8 pins. */
|
||||
if (pin_index >= GPIO_PER_BANK)
|
||||
return -1;
|
||||
num = irregular_bank_base + pin_index;
|
||||
} else {
|
||||
pin_index = simple_strtoul(name, &endp, 8);
|
||||
pin_index -= tabp->bank_offset;
|
||||
/*
|
||||
* Sanity check: bunk 'z' has no set number,
|
||||
* for all other banks there must be exactly
|
||||
* two octal digits, and the resulting number
|
||||
* should not exceed the number of pins in the
|
||||
* bank.
|
||||
*/
|
||||
if (((bank_name != 'z') && !name[1]) ||
|
||||
*endp ||
|
||||
(pin_index >= tabp->bank_size))
|
||||
return -1;
|
||||
num = tabp->base + pin_index;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
this_bank = (++tabp)->bank;
|
||||
} while (this_bank);
|
||||
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
|
||||
|
@ -143,16 +95,23 @@ static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
|
|||
writel(value, &bank->dat);
|
||||
}
|
||||
|
||||
static void s5p_gpio_direction_output(struct s5p_gpio_bank *bank,
|
||||
int gpio, int en)
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
/* Common GPIO API - SPL does not support driver model yet */
|
||||
int gpio_set_value(unsigned gpio, int value)
|
||||
{
|
||||
s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_OUTPUT);
|
||||
s5p_gpio_set_value(bank, gpio, en);
|
||||
}
|
||||
s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
|
||||
s5p_gpio_get_pin(gpio), value);
|
||||
|
||||
static void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int s5p_gpio_get_cfg_pin(struct s5p_gpio_bank *bank, int gpio)
|
||||
{
|
||||
s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_INPUT);
|
||||
unsigned int value;
|
||||
|
||||
value = readl(&bank->con);
|
||||
value &= CON_MASK(gpio);
|
||||
return CON_SFR_UNSHIFT(value, gpio);
|
||||
}
|
||||
|
||||
static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
|
||||
|
@ -162,6 +121,7 @@ static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
|
|||
value = readl(&bank->dat);
|
||||
return !!(value & DAT_MASK(gpio));
|
||||
}
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
|
||||
{
|
||||
|
@ -222,78 +182,156 @@ static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
|
|||
writel(value, &bank->drv);
|
||||
}
|
||||
|
||||
struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
|
||||
{
|
||||
const struct gpio_info *data;
|
||||
unsigned int upto;
|
||||
int i, count;
|
||||
|
||||
data = get_gpio_data();
|
||||
count = get_bank_num();
|
||||
upto = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
debug("i=%d, upto=%d\n", i, upto);
|
||||
if (gpio < data->max_gpio) {
|
||||
struct s5p_gpio_bank *bank;
|
||||
bank = (struct s5p_gpio_bank *)data->reg_addr;
|
||||
bank += (gpio - upto) / GPIO_PER_BANK;
|
||||
debug("gpio=%d, bank=%p\n", gpio, bank);
|
||||
return bank;
|
||||
}
|
||||
|
||||
upto = data->max_gpio;
|
||||
data++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int s5p_gpio_get_pin(unsigned gpio)
|
||||
{
|
||||
return S5P_GPIO_GET_PIN(gpio);
|
||||
}
|
||||
|
||||
/* Common GPIO API */
|
||||
|
||||
int gpio_request(unsigned gpio, const char *label)
|
||||
/* Driver model interface */
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static int exynos_gpio_get_state(struct udevice *dev, unsigned int offset,
|
||||
char *buf, int bufsize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
const char *label;
|
||||
bool is_output;
|
||||
int size;
|
||||
int cfg;
|
||||
|
||||
int gpio_free(unsigned gpio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_direction_input(unsigned gpio)
|
||||
{
|
||||
s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
|
||||
s5p_gpio_get_pin(gpio));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_direction_output(unsigned gpio, int value)
|
||||
{
|
||||
s5p_gpio_direction_output(s5p_gpio_get_bank(gpio),
|
||||
s5p_gpio_get_pin(gpio), value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_get_value(unsigned gpio)
|
||||
{
|
||||
return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio),
|
||||
s5p_gpio_get_pin(gpio));
|
||||
}
|
||||
|
||||
int gpio_set_value(unsigned gpio, int value)
|
||||
{
|
||||
s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
|
||||
s5p_gpio_get_pin(gpio), value);
|
||||
label = state->label[offset];
|
||||
cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
|
||||
is_output = cfg == S5P_GPIO_OUTPUT;
|
||||
size = snprintf(buf, bufsize, "%s%d: ",
|
||||
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
|
||||
buf += size;
|
||||
bufsize -= size;
|
||||
if (is_output || cfg == S5P_GPIO_INPUT) {
|
||||
snprintf(buf, bufsize, "%s: %d [%c]%s%s",
|
||||
is_output ? "out" : " in",
|
||||
s5p_gpio_get_value(state->bank, offset),
|
||||
*label ? 'x' : ' ',
|
||||
*label ? " " : "",
|
||||
label);
|
||||
} else {
|
||||
snprintf(buf, bufsize, "sfpio");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_reserved(struct udevice *dev, unsigned offset,
|
||||
const char *func)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
|
||||
if (!*state->label[offset]) {
|
||||
printf("exynos_gpio: %s: error: gpio %s%d not reserved\n",
|
||||
func, uc_priv->bank_name, offset);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set GPIO pin 'gpio' as an input */
|
||||
static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_reserved(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure GPIO direction as input. */
|
||||
s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set GPIO pin 'gpio' as an output, with polarity 'value' */
|
||||
static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_reserved(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure GPIO output value. */
|
||||
s5p_gpio_set_value(state->bank, offset, value);
|
||||
|
||||
/* Configure GPIO direction as output. */
|
||||
s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_OUTPUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read GPIO IN value of pin 'gpio' */
|
||||
static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_reserved(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return s5p_gpio_get_value(state->bank, offset);
|
||||
}
|
||||
|
||||
/* write GPIO OUT value to pin 'gpio' */
|
||||
static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_reserved(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
s5p_gpio_set_value(state->bank, offset, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_gpio_request(struct udevice *dev, unsigned offset,
|
||||
const char *label)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
|
||||
if (*state->label[offset])
|
||||
return -EBUSY;
|
||||
|
||||
strncpy(state->label[offset], label, GPIO_NAME_SIZE);
|
||||
state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_gpio_free(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_reserved(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
state->label[offset][0] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* nCONFIG_SPL_BUILD */
|
||||
|
||||
/*
|
||||
* There is no common GPIO API for pull, drv, pin, rate (yet). These
|
||||
* functions are kept here to preserve function ordering for review.
|
||||
*/
|
||||
void gpio_set_pull(int gpio, int mode)
|
||||
{
|
||||
s5p_gpio_set_pull(s5p_gpio_get_bank(gpio),
|
||||
|
@ -317,3 +355,117 @@ void gpio_set_rate(int gpio, int mode)
|
|||
s5p_gpio_set_rate(s5p_gpio_get_bank(gpio),
|
||||
s5p_gpio_get_pin(gpio), mode);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct exynos_bank_info *state = dev_get_priv(dev);
|
||||
int cfg;
|
||||
|
||||
if (!*state->label[offset])
|
||||
return GPIOF_UNUSED;
|
||||
cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
|
||||
if (cfg == S5P_GPIO_OUTPUT)
|
||||
return GPIOF_OUTPUT;
|
||||
else if (cfg == S5P_GPIO_INPUT)
|
||||
return GPIOF_INPUT;
|
||||
else
|
||||
return GPIOF_FUNC;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops gpio_exynos_ops = {
|
||||
.request = exynos_gpio_request,
|
||||
.free = exynos_gpio_free,
|
||||
.direction_input = exynos_gpio_direction_input,
|
||||
.direction_output = exynos_gpio_direction_output,
|
||||
.get_value = exynos_gpio_get_value,
|
||||
.set_value = exynos_gpio_set_value,
|
||||
.get_function = exynos_gpio_get_function,
|
||||
.get_state = exynos_gpio_get_state,
|
||||
};
|
||||
|
||||
static int gpio_exynos_probe(struct udevice *dev)
|
||||
{
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
struct exynos_bank_info *priv = dev->priv;
|
||||
struct exynos_gpio_platdata *plat = dev->platdata;
|
||||
|
||||
/* Only child devices have ports */
|
||||
if (!plat)
|
||||
return 0;
|
||||
|
||||
priv->bank = plat->bank;
|
||||
|
||||
uc_priv->gpio_count = GPIO_PER_BANK;
|
||||
uc_priv->bank_name = plat->bank_name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* We have a top-level GPIO device with no actual GPIOs. It has a child
|
||||
* device for each Exynos GPIO bank.
|
||||
*/
|
||||
static int gpio_exynos_bind(struct udevice *parent)
|
||||
{
|
||||
struct exynos_gpio_platdata *plat = parent->platdata;
|
||||
struct s5p_gpio_bank *bank, *base;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node;
|
||||
|
||||
/* If this is a child device, there is nothing to do here */
|
||||
if (plat)
|
||||
return 0;
|
||||
|
||||
base = (struct s5p_gpio_bank *)fdtdec_get_addr(gd->fdt_blob,
|
||||
parent->of_offset, "reg");
|
||||
for (node = fdt_first_subnode(blob, parent->of_offset), bank = base;
|
||||
node > 0;
|
||||
node = fdt_next_subnode(blob, node), bank++) {
|
||||
struct exynos_gpio_platdata *plat;
|
||||
struct udevice *dev;
|
||||
fdt_addr_t reg;
|
||||
int ret;
|
||||
|
||||
if (!fdtdec_get_bool(blob, node, "gpio-controller"))
|
||||
continue;
|
||||
plat = calloc(1, sizeof(*plat));
|
||||
if (!plat)
|
||||
return -ENOMEM;
|
||||
reg = fdtdec_get_addr(blob, node, "reg");
|
||||
if (reg != FDT_ADDR_T_NONE)
|
||||
bank = (struct s5p_gpio_bank *)((ulong)base + reg);
|
||||
plat->bank = bank;
|
||||
plat->bank_name = fdt_get_name(blob, node, NULL);
|
||||
debug("dev at %p: %s\n", bank, plat->bank_name);
|
||||
|
||||
ret = device_bind(parent, parent->driver,
|
||||
plat->bank_name, plat, -1, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev->of_offset = parent->of_offset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id exynos_gpio_ids[] = {
|
||||
{ .compatible = "samsung,s5pc100-pinctrl" },
|
||||
{ .compatible = "samsung,s5pc110-pinctrl" },
|
||||
{ .compatible = "samsung,exynos4210-pinctrl" },
|
||||
{ .compatible = "samsung,exynos4x12-pinctrl" },
|
||||
{ .compatible = "samsung,exynos5250-pinctrl" },
|
||||
{ .compatible = "samsung,exynos5420-pinctrl" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(gpio_exynos) = {
|
||||
.name = "gpio_exynos",
|
||||
.id = UCLASS_GPIO,
|
||||
.of_match = exynos_gpio_ids,
|
||||
.bind = gpio_exynos_bind,
|
||||
.probe = gpio_exynos_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct exynos_bank_info),
|
||||
.ops = &gpio_exynos_ops,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <cros_ec.h>
|
||||
#include <fdtdec.h>
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include <asm/errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
#define debug_trace(fmt, b...) debug(fmt, #b)
|
||||
|
@ -38,7 +41,9 @@ enum {
|
|||
CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
|
||||
};
|
||||
|
||||
#ifndef CONFIG_DM_CROS_EC
|
||||
static struct cros_ec_dev static_dev, *last_dev;
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -204,6 +209,9 @@ static int send_command_proto3(struct cros_ec_dev *dev,
|
|||
const void *dout, int dout_len,
|
||||
uint8_t **dinp, int din_len)
|
||||
{
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct dm_cros_ec_ops *ops;
|
||||
#endif
|
||||
int out_bytes, in_bytes;
|
||||
int rv;
|
||||
|
||||
|
@ -218,6 +226,10 @@ static int send_command_proto3(struct cros_ec_dev *dev,
|
|||
if (in_bytes < 0)
|
||||
return in_bytes;
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
ops = dm_cros_ec_get_ops(dev->dev);
|
||||
rv = ops->packet(dev->dev, out_bytes, in_bytes);
|
||||
#else
|
||||
switch (dev->interface) {
|
||||
#ifdef CONFIG_CROS_EC_SPI
|
||||
case CROS_EC_IF_SPI:
|
||||
|
@ -235,6 +247,7 @@ static int send_command_proto3(struct cros_ec_dev *dev,
|
|||
debug("%s: Unsupported interface\n", __func__);
|
||||
rv = -1;
|
||||
}
|
||||
#endif
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
|
@ -246,6 +259,9 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
|
|||
const void *dout, int dout_len,
|
||||
uint8_t **dinp, int din_len)
|
||||
{
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct dm_cros_ec_ops *ops;
|
||||
#endif
|
||||
int ret = -1;
|
||||
|
||||
/* Handle protocol version 3 support */
|
||||
|
@ -254,6 +270,11 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
|
|||
dout, dout_len, dinp, din_len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
ops = dm_cros_ec_get_ops(dev->dev);
|
||||
ret = ops->command(dev->dev, cmd, cmd_version,
|
||||
(const uint8_t *)dout, dout_len, dinp, din_len);
|
||||
#else
|
||||
switch (dev->interface) {
|
||||
#ifdef CONFIG_CROS_EC_SPI
|
||||
case CROS_EC_IF_SPI:
|
||||
|
@ -280,6 +301,7 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
|
|||
default:
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -990,6 +1012,7 @@ int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_CROS_EC
|
||||
/**
|
||||
* Decode EC interface details from the device tree and allocate a suitable
|
||||
* device.
|
||||
|
@ -1055,11 +1078,61 @@ static int cros_ec_decode_fdt(const void *blob, int node,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
int cros_ec_register(struct udevice *dev)
|
||||
{
|
||||
struct cros_ec_dev *cdev = dev->uclass_priv;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node = dev->of_offset;
|
||||
char id[MSG_BYTES];
|
||||
|
||||
cdev->dev = dev;
|
||||
fdtdec_decode_gpio(blob, node, "ec-interrupt", &cdev->ec_int);
|
||||
cdev->optimise_flash_write = fdtdec_get_bool(blob, node,
|
||||
"optimise-flash-write");
|
||||
|
||||
/* we will poll the EC interrupt line */
|
||||
fdtdec_setup_gpio(&cdev->ec_int);
|
||||
if (fdt_gpio_isvalid(&cdev->ec_int)) {
|
||||
gpio_request(cdev->ec_int.gpio, "cros-ec-irq");
|
||||
gpio_direction_input(cdev->ec_int.gpio);
|
||||
}
|
||||
|
||||
if (cros_ec_check_version(cdev)) {
|
||||
debug("%s: Could not detect CROS-EC version\n", __func__);
|
||||
return -CROS_EC_ERR_CHECK_VERSION;
|
||||
}
|
||||
|
||||
if (cros_ec_read_id(cdev, id, sizeof(id))) {
|
||||
debug("%s: Could not read KBC ID\n", __func__);
|
||||
return -CROS_EC_ERR_READ_ID;
|
||||
}
|
||||
|
||||
/* Remember this device for use by the cros_ec command */
|
||||
debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
|
||||
{
|
||||
char id[MSG_BYTES];
|
||||
struct cros_ec_dev *dev;
|
||||
char id[MSG_BYTES];
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct udevice *udev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_find_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (!ret)
|
||||
device_remove(udev);
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev = udev->uclass_priv;
|
||||
return 0;
|
||||
#else
|
||||
int node = 0;
|
||||
|
||||
*cros_ecp = NULL;
|
||||
|
@ -1108,11 +1181,14 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
|
|||
default:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* we will poll the EC interrupt line */
|
||||
fdtdec_setup_gpio(&dev->ec_int);
|
||||
if (fdt_gpio_isvalid(&dev->ec_int))
|
||||
if (fdt_gpio_isvalid(&dev->ec_int)) {
|
||||
gpio_request(dev->ec_int.gpio, "cros-ec-irq");
|
||||
gpio_direction_input(dev->ec_int.gpio);
|
||||
}
|
||||
|
||||
if (cros_ec_check_version(dev)) {
|
||||
debug("%s: Could not detect CROS-EC version\n", __func__);
|
||||
|
@ -1125,11 +1201,15 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
|
|||
}
|
||||
|
||||
/* Remember this device for use by the cros_ec command */
|
||||
last_dev = *cros_ecp = dev;
|
||||
*cros_ecp = dev;
|
||||
#ifndef CONFIG_DM_CROS_EC
|
||||
last_dev = dev;
|
||||
#endif
|
||||
debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int cros_ec_decode_region(int argc, char * const argv[])
|
||||
{
|
||||
|
@ -1147,15 +1227,10 @@ int cros_ec_decode_region(int argc, char * const argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config)
|
||||
int cros_ec_decode_ec_flash(const void *blob, int node,
|
||||
struct fdt_cros_ec *config)
|
||||
{
|
||||
int flash_node, node;
|
||||
|
||||
node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
|
||||
if (node < 0) {
|
||||
debug("Failed to find chrome-ec node'\n");
|
||||
return -1;
|
||||
}
|
||||
int flash_node;
|
||||
|
||||
flash_node = fdt_subnode_offset(blob, node, "flash");
|
||||
if (flash_node < 0) {
|
||||
|
@ -1516,7 +1591,10 @@ static int cros_ec_i2c_passthrough(struct cros_ec_dev *dev, int flag,
|
|||
|
||||
static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct cros_ec_dev *dev = last_dev;
|
||||
struct cros_ec_dev *dev;
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct udevice *udev;
|
||||
#endif
|
||||
const char *cmd;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -1525,19 +1603,31 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
|
||||
cmd = argv[1];
|
||||
if (0 == strcmp("init", cmd)) {
|
||||
#ifndef CONFIG_DM_CROS_EC
|
||||
ret = cros_ec_init(gd->fdt_blob, &dev);
|
||||
if (ret) {
|
||||
printf("Could not init cros_ec device (err %d)\n", ret);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (ret) {
|
||||
printf("Cannot get cros-ec device (err=%d)\n", ret);
|
||||
return 1;
|
||||
}
|
||||
dev = udev->uclass_priv;
|
||||
#else
|
||||
/* Just use the last allocated device; there should be only one */
|
||||
if (!last_dev) {
|
||||
printf("No CROS-EC device available\n");
|
||||
return 1;
|
||||
}
|
||||
dev = last_dev;
|
||||
#endif
|
||||
if (0 == strcmp("id", cmd)) {
|
||||
char id[MSG_BYTES];
|
||||
|
||||
|
@ -1794,3 +1884,11 @@ U_BOOT_CMD(
|
|||
"crosec i2c mw chip address[.0, .1, .2] value [count] - write to I2C passthru (fill)"
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
UCLASS_DRIVER(cros_ec) = {
|
||||
.id = UCLASS_CROS_EC,
|
||||
.name = "cros_ec",
|
||||
.per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <cros_ec.h>
|
||||
#include <dm.h>
|
||||
#include <ec_commands.h>
|
||||
#include <errno.h>
|
||||
#include <hash.h>
|
||||
|
@ -85,7 +86,7 @@ struct ec_state {
|
|||
struct ec_keymatrix_entry *matrix; /* the key matrix info */
|
||||
uint8_t keyscan[KEYBOARD_COLS];
|
||||
bool recovery_req;
|
||||
} s_state, *state;
|
||||
} s_state, *g_state;
|
||||
|
||||
/**
|
||||
* cros_ec_read_state() - read the sandbox EC state from the state file
|
||||
|
@ -138,7 +139,7 @@ static int cros_ec_read_state(const void *blob, int node)
|
|||
*/
|
||||
static int cros_ec_write_state(void *blob, int node)
|
||||
{
|
||||
struct ec_state *ec = &s_state;
|
||||
struct ec_state *ec = g_state;
|
||||
|
||||
/* We are guaranteed enough space to write basic properties */
|
||||
fdt_setprop_u32(blob, node, "current-image", ec->current_image);
|
||||
|
@ -369,7 +370,7 @@ static int process_cmd(struct ec_state *ec,
|
|||
struct fmap_entry *entry;
|
||||
int ret, size;
|
||||
|
||||
entry = &state->ec_config.region[EC_FLASH_REGION_RW];
|
||||
entry = &ec->ec_config.region[EC_FLASH_REGION_RW];
|
||||
|
||||
switch (req->cmd) {
|
||||
case EC_VBOOT_HASH_RECALC:
|
||||
|
@ -426,7 +427,7 @@ static int process_cmd(struct ec_state *ec,
|
|||
case EC_FLASH_REGION_RO:
|
||||
case EC_FLASH_REGION_RW:
|
||||
case EC_FLASH_REGION_WP_RO:
|
||||
entry = &state->ec_config.region[req->region];
|
||||
entry = &ec->ec_config.region[req->region];
|
||||
resp->offset = entry->offset;
|
||||
resp->size = entry->length;
|
||||
len = sizeof(*resp);
|
||||
|
@ -466,16 +467,24 @@ static int process_cmd(struct ec_state *ec,
|
|||
return len;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
int cros_ec_sandbox_packet(struct udevice *udev, int out_bytes, int in_bytes)
|
||||
{
|
||||
struct cros_ec_dev *dev = udev->uclass_priv;
|
||||
struct ec_state *ec = dev_get_priv(dev->dev);
|
||||
#else
|
||||
int cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
|
||||
int in_bytes)
|
||||
{
|
||||
struct ec_state *ec = &s_state;
|
||||
#endif
|
||||
struct ec_host_request *req_hdr = (struct ec_host_request *)dev->dout;
|
||||
const void *req_data = req_hdr + 1;
|
||||
struct ec_host_response *resp_hdr = (struct ec_host_response *)dev->din;
|
||||
void *resp_data = resp_hdr + 1;
|
||||
int len;
|
||||
|
||||
len = process_cmd(&s_state, req_hdr, req_data, resp_hdr, resp_data);
|
||||
len = process_cmd(ec, req_hdr, req_data, resp_hdr, resp_data);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
|
@ -498,7 +507,11 @@ int cros_ec_sandbox_decode_fdt(struct cros_ec_dev *dev, const void *blob)
|
|||
|
||||
void cros_ec_check_keyboard(struct cros_ec_dev *dev)
|
||||
{
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct ec_state *ec = dev_get_priv(dev->dev);
|
||||
#else
|
||||
struct ec_state *ec = &s_state;
|
||||
#endif
|
||||
ulong start;
|
||||
|
||||
printf("Press keys for EC to detect on reset (ESC=recovery)...");
|
||||
|
@ -512,6 +525,52 @@ void cros_ec_check_keyboard(struct cros_ec_dev *dev)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
int cros_ec_probe(struct udevice *dev)
|
||||
{
|
||||
struct ec_state *ec = dev->priv;
|
||||
struct cros_ec_dev *cdev = dev->uclass_priv;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node;
|
||||
int err;
|
||||
|
||||
memcpy(ec, &s_state, sizeof(*ec));
|
||||
err = cros_ec_decode_ec_flash(blob, dev->of_offset, &ec->ec_config);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
|
||||
if (node < 0) {
|
||||
debug("%s: No cros_ec keyboard found\n", __func__);
|
||||
} else if (keyscan_read_fdt_matrix(ec, blob, node)) {
|
||||
debug("%s: Could not read key matrix\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we loaded EC data, check that the length matches */
|
||||
if (ec->flash_data &&
|
||||
ec->flash_data_len != ec->ec_config.flash.length) {
|
||||
printf("EC data length is %x, expected %x, discarding data\n",
|
||||
ec->flash_data_len, ec->ec_config.flash.length);
|
||||
os_free(ec->flash_data);
|
||||
ec->flash_data = NULL;
|
||||
}
|
||||
|
||||
/* Otherwise allocate the memory */
|
||||
if (!ec->flash_data) {
|
||||
ec->flash_data_len = ec->ec_config.flash.length;
|
||||
ec->flash_data = os_malloc(ec->flash_data_len);
|
||||
if (!ec->flash_data)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cdev->dev = dev;
|
||||
g_state = ec;
|
||||
return cros_ec_register(dev);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Initialize sandbox EC emulation.
|
||||
*
|
||||
|
@ -525,8 +584,13 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
|
|||
int node;
|
||||
int err;
|
||||
|
||||
state = &s_state;
|
||||
err = cros_ec_decode_ec_flash(blob, &ec->ec_config);
|
||||
node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
|
||||
if (node < 0) {
|
||||
debug("Failed to find chrome-ec node'\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = cros_ec_decode_ec_flash(blob, node, &ec->ec_config);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -557,3 +621,24 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
struct dm_cros_ec_ops cros_ec_ops = {
|
||||
.packet = cros_ec_sandbox_packet,
|
||||
};
|
||||
|
||||
static const struct udevice_id cros_ec_ids[] = {
|
||||
{ .compatible = "google,cros-ec" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(cros_ec_sandbox) = {
|
||||
.name = "cros_ec",
|
||||
.id = UCLASS_CROS_EC,
|
||||
.of_match = cros_ec_ids,
|
||||
.probe = cros_ec_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct ec_state),
|
||||
.ops = &cros_ec_ops,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -15,23 +15,34 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <cros_ec.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <spi.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
int cros_ec_spi_packet(struct udevice *udev, int out_bytes, int in_bytes)
|
||||
{
|
||||
struct cros_ec_dev *dev = udev->uclass_priv;
|
||||
#else
|
||||
int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes)
|
||||
{
|
||||
#endif
|
||||
struct spi_slave *slave = dev_get_parentdata(dev->dev);
|
||||
int rv;
|
||||
|
||||
/* Do the transfer */
|
||||
if (spi_claim_bus(dev->spi)) {
|
||||
if (spi_claim_bus(slave)) {
|
||||
debug("%s: Cannot claim SPI bus\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = spi_xfer(dev->spi, max(out_bytes, in_bytes) * 8,
|
||||
rv = spi_xfer(slave, max(out_bytes, in_bytes) * 8,
|
||||
dev->dout, dev->din,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
|
||||
spi_release_bus(dev->spi);
|
||||
spi_release_bus(slave);
|
||||
|
||||
if (rv) {
|
||||
debug("%s: Cannot complete SPI transfer\n", __func__);
|
||||
|
@ -56,10 +67,19 @@ int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes)
|
|||
* @param din_len Maximum size of response in bytes
|
||||
* @return number of bytes in response, or -1 on error
|
||||
*/
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
int cros_ec_spi_command(struct udevice *udev, uint8_t cmd, int cmd_version,
|
||||
const uint8_t *dout, int dout_len,
|
||||
uint8_t **dinp, int din_len)
|
||||
{
|
||||
struct cros_ec_dev *dev = udev->uclass_priv;
|
||||
#else
|
||||
int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
|
||||
const uint8_t *dout, int dout_len,
|
||||
uint8_t **dinp, int din_len)
|
||||
{
|
||||
#endif
|
||||
struct spi_slave *slave = dev_get_parentdata(dev->dev);
|
||||
int in_bytes = din_len + 4; /* status, length, checksum, trailer */
|
||||
uint8_t *out;
|
||||
uint8_t *p;
|
||||
|
@ -92,7 +112,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
|
|||
*/
|
||||
memset(dev->din, '\0', in_bytes);
|
||||
|
||||
if (spi_claim_bus(dev->spi)) {
|
||||
if (spi_claim_bus(slave)) {
|
||||
debug("%s: Cannot claim SPI bus\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
@ -113,10 +133,10 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
|
|||
p = dev->din + sizeof(int64_t) - 2;
|
||||
len = dout_len + 4;
|
||||
cros_ec_dump_data("out", cmd, out, len);
|
||||
rv = spi_xfer(dev->spi, max(len, in_bytes) * 8, out, p,
|
||||
rv = spi_xfer(slave, max(len, in_bytes) * 8, out, p,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
|
||||
spi_release_bus(dev->spi);
|
||||
spi_release_bus(slave);
|
||||
|
||||
if (rv) {
|
||||
debug("%s: Cannot complete SPI transfer\n", __func__);
|
||||
|
@ -146,6 +166,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
|
|||
return len;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_CROS_EC
|
||||
int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
|
||||
{
|
||||
/* Decode interface-specific FDT params */
|
||||
|
@ -165,11 +186,59 @@ int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
|
|||
*/
|
||||
int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
|
||||
{
|
||||
dev->spi = spi_setup_slave_fdt(blob, dev->node, dev->parent_node);
|
||||
if (!dev->spi) {
|
||||
int ret;
|
||||
|
||||
ret = spi_setup_slave_fdt(blob, dev->node, dev->parent_node,
|
||||
&slave);
|
||||
if (ret) {
|
||||
debug("%s: Could not setup SPI slave\n", __func__);
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_CROS_EC
|
||||
int cros_ec_probe(struct udevice *dev)
|
||||
{
|
||||
struct spi_slave *slave = dev_get_parentdata(dev);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* TODO(sjg@chromium.org)
|
||||
*
|
||||
* This is really horrible at present. It is an artifact of removing
|
||||
* the child_pre_probe() method for SPI. Everything here could go in
|
||||
* an automatic function, except that spi_get_bus_and_cs() wants to
|
||||
* set it up manually and call device_probe_child().
|
||||
*
|
||||
* The solution may be to re-enable the child_pre_probe() method for
|
||||
* SPI and have it do nothing if the child is already passed in via
|
||||
* device_probe_child().
|
||||
*/
|
||||
slave->dev = dev;
|
||||
ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
|
||||
if (ret)
|
||||
return ret;
|
||||
return cros_ec_register(dev);
|
||||
}
|
||||
|
||||
struct dm_cros_ec_ops cros_ec_ops = {
|
||||
.packet = cros_ec_spi_packet,
|
||||
.command = cros_ec_spi_command,
|
||||
};
|
||||
|
||||
static const struct udevice_id cros_ec_ids[] = {
|
||||
{ .compatible = "google,cros-ec" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(cros_ec_spi) = {
|
||||
.name = "cros_ec",
|
||||
.id = UCLASS_CROS_EC,
|
||||
.of_match = cros_ec_ids,
|
||||
.probe = cros_ec_probe,
|
||||
.ops = &cros_ec_ops,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -102,6 +102,7 @@ struct sdhci_host sdhci_host[SDHCI_MAX_HOSTS];
|
|||
|
||||
static int do_sdhci_init(struct sdhci_host *host)
|
||||
{
|
||||
char str[20];
|
||||
int dev_id, flag;
|
||||
int err = 0;
|
||||
|
||||
|
@ -109,6 +110,8 @@ static int do_sdhci_init(struct sdhci_host *host)
|
|||
dev_id = host->index + PERIPH_ID_SDMMC0;
|
||||
|
||||
if (fdt_gpio_isvalid(&host->pwr_gpio)) {
|
||||
sprintf(str, "sdhci%d_power", host->index & 0xf);
|
||||
gpio_request(host->pwr_gpio.gpio, str);
|
||||
gpio_direction_output(host->pwr_gpio.gpio, 1);
|
||||
err = exynos_pinmux_config(dev_id, flag);
|
||||
if (err) {
|
||||
|
@ -118,7 +121,9 @@ static int do_sdhci_init(struct sdhci_host *host)
|
|||
}
|
||||
|
||||
if (fdt_gpio_isvalid(&host->cd_gpio)) {
|
||||
gpio_direction_output(host->cd_gpio.gpio, 0xf);
|
||||
sprintf(str, "sdhci%d_cd", host->index & 0xf);
|
||||
gpio_request(host->cd_gpio.gpio, str);
|
||||
gpio_direction_output(host->cd_gpio.gpio, 1);
|
||||
if (gpio_get_value(host->cd_gpio.gpio))
|
||||
return -ENODEV;
|
||||
|
||||
|
|
|
@ -5,13 +5,18 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_SPL_SPI_LOAD) += spi_spl_load.o
|
||||
obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o
|
||||
endif
|
||||
|
||||
#ifndef CONFIG_DM_SPI
|
||||
obj-$(CONFIG_SPI_FLASH) += sf_probe.o
|
||||
#endif
|
||||
obj-$(CONFIG_CMD_SF) += sf.o
|
||||
obj-$(CONFIG_SPI_FLASH) += sf_params.o sf_probe.o sf_ops.o
|
||||
obj-$(CONFIG_SPI_FLASH) += sf_ops.o sf_params.o
|
||||
obj-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o
|
||||
obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
|
||||
obj-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include "sf_internal.h"
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <spi.h>
|
||||
#include <os.h>
|
||||
|
@ -19,6 +20,11 @@
|
|||
#include <asm/getopt.h>
|
||||
#include <asm/spi.h>
|
||||
#include <asm/state.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* The different states that our SPI flash transitions between.
|
||||
|
@ -34,12 +40,14 @@ enum sandbox_sf_state {
|
|||
SF_ERASE, /* erase the flash */
|
||||
SF_READ_STATUS, /* read the flash's status register */
|
||||
SF_READ_STATUS1, /* read the flash's status register upper 8 bits*/
|
||||
SF_WRITE_STATUS, /* write the flash's status register */
|
||||
};
|
||||
|
||||
static const char *sandbox_sf_state_name(enum sandbox_sf_state state)
|
||||
{
|
||||
static const char * const states[] = {
|
||||
"CMD", "ID", "ADDR", "READ", "WRITE", "ERASE", "READ_STATUS",
|
||||
"READ_STATUS1", "WRITE_STATUS",
|
||||
};
|
||||
return states[state];
|
||||
}
|
||||
|
@ -58,6 +66,7 @@ static u8 sandbox_sf_0xff[0x1000];
|
|||
|
||||
/* Internal state data for each SPI flash */
|
||||
struct sandbox_spi_flash {
|
||||
unsigned int cs; /* Chip select we are attached to */
|
||||
/*
|
||||
* As we receive data over the SPI bus, our flash transitions
|
||||
* between states. For example, we start off in the SF_CMD
|
||||
|
@ -84,71 +93,124 @@ struct sandbox_spi_flash {
|
|||
int fd;
|
||||
};
|
||||
|
||||
static int sandbox_sf_setup(void **priv, const char *spec)
|
||||
struct sandbox_spi_flash_plat_data {
|
||||
const char *filename;
|
||||
const char *device_name;
|
||||
int bus;
|
||||
int cs;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a very strange probe function. If it has platform data (which may
|
||||
* have come from the device tree) then this function gets the filename and
|
||||
* device type from there. Failing that it looks at the command line
|
||||
* parameter.
|
||||
*/
|
||||
static int sandbox_sf_probe(struct udevice *dev)
|
||||
{
|
||||
/* spec = idcode:file */
|
||||
struct sandbox_spi_flash *sbsf;
|
||||
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
|
||||
const char *file;
|
||||
size_t len, idname_len;
|
||||
const struct spi_flash_params *data;
|
||||
struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev);
|
||||
struct sandbox_state *state = state_get_current();
|
||||
struct udevice *bus = dev->parent;
|
||||
const char *spec = NULL;
|
||||
int ret = 0;
|
||||
int cs = -1;
|
||||
int i;
|
||||
|
||||
file = strchr(spec, ':');
|
||||
if (!file) {
|
||||
printf("sandbox_sf: unable to parse file\n");
|
||||
goto error;
|
||||
debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev);
|
||||
if (bus->seq >= 0 && bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) {
|
||||
for (i = 0; i < CONFIG_SANDBOX_SPI_MAX_CS; i++) {
|
||||
if (state->spi[bus->seq][i].emul == dev)
|
||||
cs = i;
|
||||
}
|
||||
}
|
||||
idname_len = file - spec;
|
||||
++file;
|
||||
if (cs == -1) {
|
||||
printf("Error: Unknown chip select for device '%s'",
|
||||
dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
debug("found at cs %d\n", cs);
|
||||
|
||||
if (!pdata->filename) {
|
||||
struct sandbox_state *state = state_get_current();
|
||||
|
||||
assert(bus->seq != -1);
|
||||
if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS)
|
||||
spec = state->spi[bus->seq][cs].spec;
|
||||
if (!spec)
|
||||
return -ENOENT;
|
||||
|
||||
file = strchr(spec, ':');
|
||||
if (!file) {
|
||||
printf("sandbox_sf: unable to parse file\n");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
idname_len = file - spec;
|
||||
pdata->filename = file + 1;
|
||||
pdata->device_name = spec;
|
||||
++file;
|
||||
} else {
|
||||
spec = strchr(pdata->device_name, ',');
|
||||
if (spec)
|
||||
spec++;
|
||||
else
|
||||
spec = pdata->device_name;
|
||||
idname_len = strlen(spec);
|
||||
}
|
||||
debug("%s: device='%s'\n", __func__, spec);
|
||||
|
||||
for (data = spi_flash_params_table; data->name; data++) {
|
||||
len = strlen(data->name);
|
||||
if (idname_len != len)
|
||||
continue;
|
||||
if (!memcmp(spec, data->name, len))
|
||||
if (!strncasecmp(spec, data->name, len))
|
||||
break;
|
||||
}
|
||||
if (!data->name) {
|
||||
printf("sandbox_sf: unknown flash '%*s'\n", (int)idname_len,
|
||||
spec);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (sandbox_sf_0xff[0] == 0x00)
|
||||
memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff));
|
||||
|
||||
sbsf = calloc(sizeof(*sbsf), 1);
|
||||
if (!sbsf) {
|
||||
printf("sandbox_sf: out of memory\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
sbsf->fd = os_open(file, 02);
|
||||
sbsf->fd = os_open(pdata->filename, 02);
|
||||
if (sbsf->fd == -1) {
|
||||
free(sbsf);
|
||||
printf("sandbox_sf: unable to open file '%s'\n", file);
|
||||
printf("sandbox_sf: unable to open file '%s'\n",
|
||||
pdata->filename);
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
sbsf->data = data;
|
||||
sbsf->cs = cs;
|
||||
|
||||
*priv = sbsf;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sandbox_sf_free(void *priv)
|
||||
static int sandbox_sf_remove(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_spi_flash *sbsf = priv;
|
||||
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
|
||||
|
||||
os_close(sbsf->fd);
|
||||
free(sbsf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sandbox_sf_cs_activate(void *priv)
|
||||
static void sandbox_sf_cs_activate(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_spi_flash *sbsf = priv;
|
||||
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
|
||||
|
||||
debug("sandbox_sf: CS activated; state is fresh!\n");
|
||||
|
||||
|
@ -160,11 +222,24 @@ static void sandbox_sf_cs_activate(void *priv)
|
|||
sbsf->cmd = SF_CMD;
|
||||
}
|
||||
|
||||
static void sandbox_sf_cs_deactivate(void *priv)
|
||||
static void sandbox_sf_cs_deactivate(struct udevice *dev)
|
||||
{
|
||||
debug("sandbox_sf: CS deactivated; cmd done processing!\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* There are times when the data lines are allowed to tristate. What
|
||||
* is actually sensed on the line depends on the hardware. It could
|
||||
* always be 0xFF/0x00 (if there are pull ups/downs), or things could
|
||||
* float and so we'd get garbage back. This func encapsulates that
|
||||
* scenario so we can worry about the details here.
|
||||
*/
|
||||
static void sandbox_spi_tristate(u8 *buf, uint len)
|
||||
{
|
||||
/* XXX: make this into a user config option ? */
|
||||
memset(buf, 0xff, len);
|
||||
}
|
||||
|
||||
/* Figure out what command this stream is telling us to do */
|
||||
static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
|
||||
u8 *tx)
|
||||
|
@ -172,7 +247,8 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
|
|||
enum sandbox_sf_state oldstate = sbsf->state;
|
||||
|
||||
/* We need to output a byte for the cmd byte we just ate */
|
||||
sandbox_spi_tristate(tx, 1);
|
||||
if (tx)
|
||||
sandbox_spi_tristate(tx, 1);
|
||||
|
||||
sbsf->cmd = rx[0];
|
||||
switch (sbsf->cmd) {
|
||||
|
@ -200,6 +276,9 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
|
|||
debug(" write enabled\n");
|
||||
sbsf->status |= STAT_WEL;
|
||||
break;
|
||||
case CMD_WRITE_STATUS:
|
||||
sbsf->state = SF_WRITE_STATUS;
|
||||
break;
|
||||
default: {
|
||||
int flags = sbsf->data->flags;
|
||||
|
||||
|
@ -216,7 +295,7 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
|
|||
sbsf->erase_size = 64 << 10;
|
||||
} else {
|
||||
debug(" cmd unknown: %#x\n", sbsf->cmd);
|
||||
return 1;
|
||||
return -EIO;
|
||||
}
|
||||
sbsf->state = SF_ADDR;
|
||||
break;
|
||||
|
@ -246,20 +325,27 @@ int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
||||
uint bytes)
|
||||
static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
|
||||
const void *rxp, void *txp, unsigned long flags)
|
||||
{
|
||||
struct sandbox_spi_flash *sbsf = priv;
|
||||
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
|
||||
const uint8_t *rx = rxp;
|
||||
uint8_t *tx = txp;
|
||||
uint cnt, pos = 0;
|
||||
int bytes = bitlen / 8;
|
||||
int ret;
|
||||
|
||||
debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state,
|
||||
sandbox_sf_state_name(sbsf->state), bytes);
|
||||
|
||||
if ((flags & SPI_XFER_BEGIN))
|
||||
sandbox_sf_cs_activate(dev);
|
||||
|
||||
if (sbsf->state == SF_CMD) {
|
||||
/* Figure out the initial state */
|
||||
if (sandbox_sf_process_cmd(sbsf, rx, tx))
|
||||
return 1;
|
||||
ret = sandbox_sf_process_cmd(sbsf, rx, tx);
|
||||
if (ret)
|
||||
return ret;
|
||||
++pos;
|
||||
}
|
||||
|
||||
|
@ -290,7 +376,9 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
|||
sbsf->off = (sbsf->off << 8) | rx[pos];
|
||||
debug("addr:%06x\n", sbsf->off);
|
||||
|
||||
sandbox_spi_tristate(&tx[pos++], 1);
|
||||
if (tx)
|
||||
sandbox_spi_tristate(&tx[pos], 1);
|
||||
pos++;
|
||||
|
||||
/* See if we're done processing */
|
||||
if (sbsf->addr_bytes <
|
||||
|
@ -300,7 +388,7 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
|||
/* Next state! */
|
||||
if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) {
|
||||
puts("sandbox_sf: os_lseek() failed");
|
||||
return 1;
|
||||
return -EIO;
|
||||
}
|
||||
switch (sbsf->cmd) {
|
||||
case CMD_READ_ARRAY_FAST:
|
||||
|
@ -326,10 +414,11 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
|||
|
||||
cnt = bytes - pos;
|
||||
debug(" tx: read(%u)\n", cnt);
|
||||
assert(tx);
|
||||
ret = os_read(sbsf->fd, tx + pos, cnt);
|
||||
if (ret < 0) {
|
||||
puts("sandbox_spi: os_read() failed\n");
|
||||
return 1;
|
||||
puts("sandbox_sf: os_read() failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
pos += ret;
|
||||
break;
|
||||
|
@ -345,6 +434,10 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
|||
memset(tx + pos, sbsf->status >> 8, cnt);
|
||||
pos += cnt;
|
||||
break;
|
||||
case SF_WRITE_STATUS:
|
||||
debug(" write status: %#x (ignored)\n", rx[pos]);
|
||||
pos = bytes;
|
||||
break;
|
||||
case SF_WRITE:
|
||||
/*
|
||||
* XXX: need to handle exotic behavior:
|
||||
|
@ -359,11 +452,12 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
|||
|
||||
cnt = bytes - pos;
|
||||
debug(" rx: write(%u)\n", cnt);
|
||||
sandbox_spi_tristate(&tx[pos], cnt);
|
||||
if (tx)
|
||||
sandbox_spi_tristate(&tx[pos], cnt);
|
||||
ret = os_write(sbsf->fd, rx + pos, cnt);
|
||||
if (ret < 0) {
|
||||
puts("sandbox_spi: os_write() failed\n");
|
||||
return 1;
|
||||
return -EIO;
|
||||
}
|
||||
pos += ret;
|
||||
sbsf->status &= ~STAT_WEL;
|
||||
|
@ -388,7 +482,8 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
|||
sbsf->erase_size);
|
||||
|
||||
cnt = bytes - pos;
|
||||
sandbox_spi_tristate(&tx[pos], cnt);
|
||||
if (tx)
|
||||
sandbox_spi_tristate(&tx[pos], cnt);
|
||||
pos += cnt;
|
||||
|
||||
/*
|
||||
|
@ -410,17 +505,33 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
|
|||
}
|
||||
|
||||
done:
|
||||
return pos == bytes ? 0 : 1;
|
||||
if (flags & SPI_XFER_END)
|
||||
sandbox_sf_cs_deactivate(dev);
|
||||
return pos == bytes ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static const struct sandbox_spi_emu_ops sandbox_sf_ops = {
|
||||
.setup = sandbox_sf_setup,
|
||||
.free = sandbox_sf_free,
|
||||
.cs_activate = sandbox_sf_cs_activate,
|
||||
.cs_deactivate = sandbox_sf_cs_deactivate,
|
||||
int sandbox_sf_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev);
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node = dev->of_offset;
|
||||
|
||||
pdata->filename = fdt_getprop(blob, node, "sandbox,filename", NULL);
|
||||
pdata->device_name = fdt_getprop(blob, node, "compatible", NULL);
|
||||
if (!pdata->filename || !pdata->device_name) {
|
||||
debug("%s: Missing properties, filename=%s, device_name=%s\n",
|
||||
__func__, pdata->filename, pdata->device_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_spi_emul_ops sandbox_sf_emul_ops = {
|
||||
.xfer = sandbox_sf_xfer,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH
|
||||
static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state,
|
||||
const char *arg)
|
||||
{
|
||||
|
@ -438,8 +549,141 @@ static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state,
|
|||
* spec here, but the problem is that no U-Boot init has been done
|
||||
* yet. Perhaps we can figure something out.
|
||||
*/
|
||||
state->spi[bus][cs].ops = &sandbox_sf_ops;
|
||||
state->spi[bus][cs].spec = spec;
|
||||
return 0;
|
||||
}
|
||||
SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: <bus>:<cs>:<id>:<file>");
|
||||
|
||||
int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
|
||||
struct udevice *bus, int of_offset, const char *spec)
|
||||
{
|
||||
struct udevice *emul;
|
||||
char name[20], *str;
|
||||
struct driver *drv;
|
||||
int ret;
|
||||
|
||||
/* now the emulator */
|
||||
strncpy(name, spec, sizeof(name) - 6);
|
||||
name[sizeof(name) - 6] = '\0';
|
||||
strcat(name, "-emul");
|
||||
str = strdup(name);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
drv = lists_driver_lookup_name("sandbox_sf_emul");
|
||||
if (!drv) {
|
||||
puts("Cannot find sandbox_sf_emul driver\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
ret = device_bind(bus, drv, str, NULL, of_offset, &emul);
|
||||
if (ret) {
|
||||
printf("Cannot create emul device for spec '%s' (err=%d)\n",
|
||||
spec, ret);
|
||||
return ret;
|
||||
}
|
||||
state->spi[busnum][cs].emul = emul;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs)
|
||||
{
|
||||
state->spi[busnum][cs].emul = NULL;
|
||||
}
|
||||
|
||||
static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum,
|
||||
int cs, const char *spec)
|
||||
{
|
||||
struct udevice *bus, *slave;
|
||||
int ret;
|
||||
|
||||
ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, true, &bus);
|
||||
if (ret) {
|
||||
printf("Invalid bus %d for spec '%s' (err=%d)\n", busnum,
|
||||
spec, ret);
|
||||
return ret;
|
||||
}
|
||||
ret = device_find_child_by_seq(bus, cs, true, &slave);
|
||||
if (!ret) {
|
||||
printf("Chip select %d already exists for spec '%s'\n", cs,
|
||||
spec);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
ret = spi_bind_device(bus, cs, "spi_flash_std", spec, &slave);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sandbox_sf_bind_emul(state, busnum, cs, bus, -1, spec);
|
||||
}
|
||||
|
||||
int sandbox_spi_get_emul(struct sandbox_state *state,
|
||||
struct udevice *bus, struct udevice *slave,
|
||||
struct udevice **emulp)
|
||||
{
|
||||
struct sandbox_spi_info *info;
|
||||
int busnum = bus->seq;
|
||||
int cs = spi_chip_select(slave);
|
||||
int ret;
|
||||
|
||||
info = &state->spi[busnum][cs];
|
||||
if (!info->emul) {
|
||||
/* Use the same device tree node as the SPI flash device */
|
||||
debug("%s: busnum=%u, cs=%u: binding SPI flash emulation: ",
|
||||
__func__, busnum, cs);
|
||||
ret = sandbox_sf_bind_emul(state, busnum, cs, bus,
|
||||
slave->of_offset, slave->name);
|
||||
if (ret) {
|
||||
debug("failed (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
debug("OK\n");
|
||||
}
|
||||
*emulp = info->emul;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_scan_other(bool pre_reloc_only)
|
||||
{
|
||||
struct sandbox_state *state = state_get_current();
|
||||
int busnum, cs;
|
||||
|
||||
if (pre_reloc_only)
|
||||
return 0;
|
||||
for (busnum = 0; busnum < CONFIG_SANDBOX_SPI_MAX_BUS; busnum++) {
|
||||
for (cs = 0; cs < CONFIG_SANDBOX_SPI_MAX_CS; cs++) {
|
||||
const char *spec = state->spi[busnum][cs].spec;
|
||||
int ret;
|
||||
|
||||
if (spec) {
|
||||
ret = sandbox_sf_bind_bus_cs(state, busnum,
|
||||
cs, spec);
|
||||
if (ret) {
|
||||
debug("%s: Bind failed for bus %d, cs %d\n",
|
||||
__func__, busnum, cs);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct udevice_id sandbox_sf_ids[] = {
|
||||
{ .compatible = "sandbox,spi-flash" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_sf_emul) = {
|
||||
.name = "sandbox_sf_emul",
|
||||
.id = UCLASS_SPI_EMUL,
|
||||
.of_match = sandbox_sf_ids,
|
||||
.ofdata_to_platdata = sandbox_sf_ofdata_to_platdata,
|
||||
.probe = sandbox_sf_probe,
|
||||
.remove = sandbox_sf_remove,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_spi_flash),
|
||||
.platdata_auto_alloc_size = sizeof(struct sandbox_spi_flash_plat_data),
|
||||
.ops = &sandbox_sf_emul_ops,
|
||||
};
|
||||
|
|
63
drivers/mtd/spi/sf-uclass.c
Normal file
63
drivers/mtd/spi/sf-uclass.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include "sf_internal.h"
|
||||
|
||||
/*
|
||||
* TODO(sjg@chromium.org): This is an old-style function. We should remove
|
||||
* it when all SPI flash drivers use dm
|
||||
*/
|
||||
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int spi_mode)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
||||
if (spi_flash_probe_bus_cs(bus, cs, max_hz, spi_mode, &dev))
|
||||
return NULL;
|
||||
|
||||
return dev->uclass_priv;
|
||||
}
|
||||
|
||||
void spi_flash_free(struct spi_flash *flash)
|
||||
{
|
||||
spi_flash_remove(flash->spi->dev);
|
||||
}
|
||||
|
||||
int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int spi_mode,
|
||||
struct udevice **devp)
|
||||
{
|
||||
struct spi_slave *slave;
|
||||
struct udevice *bus;
|
||||
char name[20], *str;
|
||||
int ret;
|
||||
|
||||
snprintf(name, sizeof(name), "%d:%d", busnum, cs);
|
||||
str = strdup(name);
|
||||
ret = spi_get_bus_and_cs(busnum, cs, max_hz, spi_mode,
|
||||
"spi_flash_std", str, &bus, &slave);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*devp = slave->dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spi_flash_remove(struct udevice *dev)
|
||||
{
|
||||
return device_remove(dev);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(spi_flash) = {
|
||||
.id = UCLASS_SPI_FLASH,
|
||||
.name = "spi_flash",
|
||||
.per_device_auto_alloc_size = sizeof(struct spi_flash),
|
||||
};
|
|
@ -10,6 +10,36 @@
|
|||
#ifndef _SF_INTERNAL_H_
|
||||
#define _SF_INTERNAL_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
/* Dual SPI flash memories - see SPI_COMM_DUAL_... */
|
||||
enum spi_dual_flash {
|
||||
SF_SINGLE_FLASH = 0,
|
||||
SF_DUAL_STACKED_FLASH = 1 << 0,
|
||||
SF_DUAL_PARALLEL_FLASH = 1 << 1,
|
||||
};
|
||||
|
||||
/* Enum list - Full read commands */
|
||||
enum spi_read_cmds {
|
||||
ARRAY_SLOW = 1 << 0,
|
||||
DUAL_OUTPUT_FAST = 1 << 1,
|
||||
DUAL_IO_FAST = 1 << 2,
|
||||
QUAD_OUTPUT_FAST = 1 << 3,
|
||||
QUAD_IO_FAST = 1 << 4,
|
||||
};
|
||||
|
||||
#define RD_EXTN (ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST)
|
||||
#define RD_FULL (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST)
|
||||
|
||||
/* sf param flags */
|
||||
enum {
|
||||
SECT_4K = 1 << 0,
|
||||
SECT_32K = 1 << 1,
|
||||
E_FSR = 1 << 2,
|
||||
WR_QPP = 1 << 3,
|
||||
};
|
||||
|
||||
#define SPI_FLASH_3B_ADDR_LEN 3
|
||||
#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN)
|
||||
#define SPI_FLASH_16MB_BOUN 0x1000000
|
||||
|
@ -30,12 +60,12 @@
|
|||
#define CMD_WRITE_STATUS 0x01
|
||||
#define CMD_PAGE_PROGRAM 0x02
|
||||
#define CMD_WRITE_DISABLE 0x04
|
||||
#define CMD_READ_STATUS 0x05
|
||||
#define CMD_READ_STATUS 0x05
|
||||
#define CMD_QUAD_PAGE_PROGRAM 0x32
|
||||
#define CMD_READ_STATUS1 0x35
|
||||
#define CMD_WRITE_ENABLE 0x06
|
||||
#define CMD_READ_CONFIG 0x35
|
||||
#define CMD_FLAG_STATUS 0x70
|
||||
#define CMD_READ_CONFIG 0x35
|
||||
#define CMD_FLAG_STATUS 0x70
|
||||
|
||||
/* Read commands */
|
||||
#define CMD_READ_ARRAY_SLOW 0x03
|
||||
|
@ -57,7 +87,7 @@
|
|||
/* Common status */
|
||||
#define STATUS_WIP (1 << 0)
|
||||
#define STATUS_QEB_WINSPAN (1 << 1)
|
||||
#define STATUS_QEB_MXIC (1 << 6)
|
||||
#define STATUS_QEB_MXIC (1 << 6)
|
||||
#define STATUS_PEC (1 << 7)
|
||||
|
||||
#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
|
||||
|
@ -66,19 +96,42 @@
|
|||
|
||||
/* Flash timeout values */
|
||||
#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ)
|
||||
#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ)
|
||||
#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ)
|
||||
#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ)
|
||||
|
||||
/* SST specific */
|
||||
#ifdef CONFIG_SPI_FLASH_SST
|
||||
# define SST_WP 0x01 /* Supports AAI word program */
|
||||
# define SST_WP 0x01 /* Supports AAI word program */
|
||||
# define CMD_SST_BP 0x02 /* Byte Program */
|
||||
# define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */
|
||||
# define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */
|
||||
|
||||
int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
|
||||
const void *buf);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct spi_flash_params - SPI/QSPI flash device params structure
|
||||
*
|
||||
* @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
|
||||
* @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
|
||||
* @ext_jedec: Device ext_jedec ID
|
||||
* @sector_size: Sector size of this device
|
||||
* @nr_sectors: No.of sectors on this device
|
||||
* @e_rd_cmd: Enum list for read commands
|
||||
* @flags: Important param, for flash specific behaviour
|
||||
*/
|
||||
struct spi_flash_params {
|
||||
const char *name;
|
||||
u32 jedec;
|
||||
u16 ext_jedec;
|
||||
u32 sector_size;
|
||||
u32 nr_sectors;
|
||||
u8 e_rd_cmd;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
extern const struct spi_flash_params spi_flash_params_table[];
|
||||
|
||||
/* Send a single-byte command to the device and read the response */
|
||||
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
#include "sf_internal.h"
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <malloc.h>
|
||||
#include <spi.h>
|
||||
|
@ -95,15 +97,15 @@ static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
|
|||
}
|
||||
}
|
||||
|
||||
static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
|
||||
u8 *idcode)
|
||||
static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
|
||||
struct spi_flash *flash)
|
||||
{
|
||||
const struct spi_flash_params *params;
|
||||
struct spi_flash *flash;
|
||||
u8 cmd;
|
||||
u16 jedec = idcode[1] << 8 | idcode[2];
|
||||
u16 ext_jedec = idcode[3] << 8 | idcode[4];
|
||||
|
||||
/* Validate params from spi_flash_params table */
|
||||
params = spi_flash_params_table;
|
||||
for (; params->name != NULL; params++) {
|
||||
if ((params->jedec >> 16) == idcode[0]) {
|
||||
|
@ -120,13 +122,7 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
|
|||
printf("SF: Unsupported flash IDs: ");
|
||||
printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
|
||||
idcode[0], jedec, ext_jedec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flash = calloc(1, sizeof(*flash));
|
||||
if (!flash) {
|
||||
debug("SF: Failed to allocate spi_flash\n");
|
||||
return NULL;
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
|
||||
/* Assign spi data */
|
||||
|
@ -136,13 +132,15 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
|
|||
flash->dual_flash = flash->spi->option;
|
||||
|
||||
/* Assign spi_flash ops */
|
||||
#ifndef CONFIG_DM_SPI_FLASH
|
||||
flash->write = spi_flash_cmd_write_ops;
|
||||
#ifdef CONFIG_SPI_FLASH_SST
|
||||
#if defined(CONFIG_SPI_FLASH_SST)
|
||||
if (params->flags & SST_WP)
|
||||
flash->write = sst_write_wp;
|
||||
#endif
|
||||
flash->erase = spi_flash_cmd_erase_ops;
|
||||
flash->read = spi_flash_cmd_read_ops;
|
||||
#endif
|
||||
|
||||
/* Compute the flash size */
|
||||
flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
|
||||
|
@ -227,15 +225,18 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
|
|||
#ifdef CONFIG_SPI_FLASH_BAR
|
||||
u8 curr_bank = 0;
|
||||
if (flash->size > SPI_FLASH_16MB_BOUN) {
|
||||
int ret;
|
||||
|
||||
flash->bank_read_cmd = (idcode[0] == 0x01) ?
|
||||
CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
|
||||
flash->bank_write_cmd = (idcode[0] == 0x01) ?
|
||||
CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
|
||||
|
||||
if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
|
||||
&curr_bank, 1)) {
|
||||
ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
|
||||
&curr_bank, 1);
|
||||
if (ret) {
|
||||
debug("SF: fail to read bank addr register\n");
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
flash->bank_curr = curr_bank;
|
||||
} else {
|
||||
|
@ -250,7 +251,7 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
|
|||
spi_flash_cmd_write_status(flash, 0);
|
||||
#endif
|
||||
|
||||
return flash;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_CONTROL
|
||||
|
@ -309,23 +310,29 @@ static int spi_enable_wp_pin(struct spi_flash *flash)
|
|||
}
|
||||
#endif
|
||||
|
||||
static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
|
||||
/**
|
||||
* spi_flash_probe_slave() - Probe for a SPI flash device on a bus
|
||||
*
|
||||
* @spi: Bus to probe
|
||||
* @flashp: Pointer to place to put flash info, which may be NULL if the
|
||||
* space should be allocated
|
||||
*/
|
||||
int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
|
||||
{
|
||||
struct spi_flash *flash = NULL;
|
||||
u8 idcode[5];
|
||||
int ret;
|
||||
|
||||
/* Setup spi_slave */
|
||||
if (!spi) {
|
||||
printf("SF: Failed to set up slave\n");
|
||||
return NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Claim spi bus */
|
||||
ret = spi_claim_bus(spi);
|
||||
if (ret) {
|
||||
debug("SF: Failed to claim SPI bus: %d\n", ret);
|
||||
goto err_claim_bus;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the ID codes */
|
||||
|
@ -340,10 +347,10 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
|
|||
print_buffer(0, idcode, 1, sizeof(idcode), 0);
|
||||
#endif
|
||||
|
||||
/* Validate params from spi_flash_params table */
|
||||
flash = spi_flash_validate_params(spi, idcode);
|
||||
if (!flash)
|
||||
if (spi_flash_validate_params(spi, idcode, flash)) {
|
||||
ret = -EINVAL;
|
||||
goto err_read_id;
|
||||
}
|
||||
|
||||
/* Set the quad enable bit - only for quad commands */
|
||||
if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
|
||||
|
@ -351,13 +358,15 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
|
|||
(flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
|
||||
if (spi_flash_set_qeb(flash, idcode[0])) {
|
||||
debug("SF: Fail to set QEB for %02x\n", idcode[0]);
|
||||
return NULL;
|
||||
ret = -EINVAL;
|
||||
goto err_read_id;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_CONTROL
|
||||
if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
|
||||
debug("SF: FDT decode error\n");
|
||||
ret = -EINVAL;
|
||||
goto err_read_id;
|
||||
}
|
||||
#endif
|
||||
|
@ -385,32 +394,51 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
|
|||
/* Release spi bus */
|
||||
spi_release_bus(spi);
|
||||
|
||||
return flash;
|
||||
return 0;
|
||||
|
||||
err_read_id:
|
||||
spi_release_bus(spi);
|
||||
err_claim_bus:
|
||||
spi_free_slave(spi);
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
|
||||
#ifndef CONFIG_DM_SPI_FLASH
|
||||
struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
|
||||
{
|
||||
struct spi_flash *flash;
|
||||
|
||||
/* Allocate space if needed (not used by sf-uclass */
|
||||
flash = calloc(1, sizeof(*flash));
|
||||
if (!flash) {
|
||||
debug("SF: Failed to allocate spi_flash\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (spi_flash_probe_slave(bus, flash)) {
|
||||
spi_free_slave(bus);
|
||||
free(flash);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return flash;
|
||||
}
|
||||
|
||||
struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int spi_mode)
|
||||
{
|
||||
struct spi_slave *spi;
|
||||
struct spi_slave *bus;
|
||||
|
||||
spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
|
||||
return spi_flash_probe_slave(spi);
|
||||
bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
|
||||
return spi_flash_probe_tail(bus);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_SPI_FLASH
|
||||
struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
|
||||
int spi_node)
|
||||
{
|
||||
struct spi_slave *spi;
|
||||
struct spi_slave *bus;
|
||||
|
||||
spi = spi_setup_slave_fdt(blob, slave_node, spi_node);
|
||||
return spi_flash_probe_slave(spi);
|
||||
bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
|
||||
return spi_flash_probe_tail(bus);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -419,3 +447,61 @@ void spi_flash_free(struct spi_flash *flash)
|
|||
spi_free_slave(flash->spi);
|
||||
free(flash);
|
||||
}
|
||||
|
||||
#else /* defined CONFIG_DM_SPI_FLASH */
|
||||
|
||||
static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
|
||||
void *buf)
|
||||
{
|
||||
struct spi_flash *flash = dev->uclass_priv;
|
||||
|
||||
return spi_flash_cmd_read_ops(flash, offset, len, buf);
|
||||
}
|
||||
|
||||
int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
|
||||
const void *buf)
|
||||
{
|
||||
struct spi_flash *flash = dev->uclass_priv;
|
||||
|
||||
return spi_flash_cmd_write_ops(flash, offset, len, buf);
|
||||
}
|
||||
|
||||
int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
|
||||
{
|
||||
struct spi_flash *flash = dev->uclass_priv;
|
||||
|
||||
return spi_flash_cmd_erase_ops(flash, offset, len);
|
||||
}
|
||||
|
||||
int spi_flash_std_probe(struct udevice *dev)
|
||||
{
|
||||
struct spi_slave *slave = dev_get_parentdata(dev);
|
||||
struct spi_flash *flash;
|
||||
|
||||
flash = dev->uclass_priv;
|
||||
flash->dev = dev;
|
||||
debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
|
||||
return spi_flash_probe_slave(slave, flash);
|
||||
}
|
||||
|
||||
static const struct dm_spi_flash_ops spi_flash_std_ops = {
|
||||
.read = spi_flash_std_read,
|
||||
.write = spi_flash_std_write,
|
||||
.erase = spi_flash_std_erase,
|
||||
};
|
||||
|
||||
static const struct udevice_id spi_flash_std_ids[] = {
|
||||
{ .compatible = "spi-flash" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(spi_flash_std) = {
|
||||
.name = "spi_flash_std",
|
||||
.id = UCLASS_SPI_FLASH,
|
||||
.of_match = spi_flash_std_ids,
|
||||
.probe = spi_flash_std_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct spi_flash),
|
||||
.ops = &spi_flash_std_ops,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_DM_SPI_FLASH */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <spi.h>
|
||||
#include <spi_flash.h>
|
||||
#include <spl.h>
|
||||
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
|
||||
ifdef CONFIG_DM_SERIAL
|
||||
obj-y += serial-uclass.o
|
||||
obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o
|
||||
else
|
||||
obj-y += serial.o
|
||||
obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
|
||||
obj-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
|
||||
obj-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o
|
||||
endif
|
||||
|
||||
|
@ -25,8 +28,6 @@ obj-$(CONFIG_IMX_SERIAL) += serial_imx.o
|
|||
obj-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o
|
||||
obj-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
|
||||
obj-$(CONFIG_MXC_UART) += serial_mxc.o
|
||||
obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
|
||||
obj-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
|
||||
obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
|
||||
obj-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o
|
||||
obj-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
|
||||
|
|
|
@ -71,7 +71,7 @@ void serial_initialize(void)
|
|||
serial_find_console_or_panic();
|
||||
}
|
||||
|
||||
void serial_putc(char ch)
|
||||
static void serial_putc_dev(struct udevice *dev, char ch)
|
||||
{
|
||||
struct dm_serial_ops *ops = serial_get_ops(cur_dev);
|
||||
int err;
|
||||
|
@ -83,6 +83,11 @@ void serial_putc(char ch)
|
|||
serial_putc('\r');
|
||||
}
|
||||
|
||||
void serial_putc(char ch)
|
||||
{
|
||||
serial_putc_dev(cur_dev, ch);
|
||||
}
|
||||
|
||||
void serial_setbrg(void)
|
||||
{
|
||||
struct dm_serial_ops *ops = serial_get_ops(cur_dev);
|
||||
|
@ -107,28 +112,32 @@ int serial_tstc(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int serial_getc(void)
|
||||
static int serial_getc_dev(struct udevice *dev)
|
||||
{
|
||||
struct dm_serial_ops *ops = serial_get_ops(cur_dev);
|
||||
struct dm_serial_ops *ops = serial_get_ops(dev);
|
||||
int err;
|
||||
|
||||
do {
|
||||
err = ops->getc(cur_dev);
|
||||
err = ops->getc(dev);
|
||||
} while (err == -EAGAIN);
|
||||
|
||||
return err >= 0 ? err : 0;
|
||||
}
|
||||
|
||||
int serial_getc(void)
|
||||
{
|
||||
return serial_getc_dev(cur_dev);
|
||||
}
|
||||
|
||||
void serial_stdio_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void serial_stub_putc(struct stdio_dev *sdev, const char ch)
|
||||
static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
|
||||
{
|
||||
struct udevice *dev = sdev->priv;
|
||||
struct dm_serial_ops *ops = serial_get_ops(dev);
|
||||
|
||||
ops->putc(dev, ch);
|
||||
serial_putc_dev(dev, ch);
|
||||
}
|
||||
|
||||
void serial_stub_puts(struct stdio_dev *sdev, const char *str)
|
||||
|
@ -140,15 +149,8 @@ void serial_stub_puts(struct stdio_dev *sdev, const char *str)
|
|||
int serial_stub_getc(struct stdio_dev *sdev)
|
||||
{
|
||||
struct udevice *dev = sdev->priv;
|
||||
struct dm_serial_ops *ops = serial_get_ops(dev);
|
||||
|
||||
int err;
|
||||
|
||||
do {
|
||||
err = ops->getc(dev);
|
||||
} while (err == -EAGAIN);
|
||||
|
||||
return err >= 0 ? err : 0;
|
||||
return serial_getc_dev(dev);
|
||||
}
|
||||
|
||||
int serial_stub_tstc(struct stdio_dev *sdev)
|
||||
|
|
|
@ -5,37 +5,15 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <serial_mxc.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <serial.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#define __REG(x) (*((volatile u32 *)(x)))
|
||||
|
||||
#ifndef CONFIG_MXC_UART_BASE
|
||||
#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
|
||||
#endif
|
||||
|
||||
#define UART_PHYS CONFIG_MXC_UART_BASE
|
||||
|
||||
/* Register definitions */
|
||||
#define URXD 0x0 /* Receiver Register */
|
||||
#define UTXD 0x40 /* Transmitter Register */
|
||||
#define UCR1 0x80 /* Control Register 1 */
|
||||
#define UCR2 0x84 /* Control Register 2 */
|
||||
#define UCR3 0x88 /* Control Register 3 */
|
||||
#define UCR4 0x8c /* Control Register 4 */
|
||||
#define UFCR 0x90 /* FIFO Control Register */
|
||||
#define USR1 0x94 /* Status Register 1 */
|
||||
#define USR2 0x98 /* Status Register 2 */
|
||||
#define UESC 0x9c /* Escape Character Register */
|
||||
#define UTIM 0xa0 /* Escape Timer Register */
|
||||
#define UBIR 0xa4 /* BRM Incremental Register */
|
||||
#define UBMR 0xa8 /* BRM Modulator Register */
|
||||
#define UBRC 0xac /* Baud Rate Count Register */
|
||||
#define UTS 0xb4 /* UART Test Register (mx31) */
|
||||
|
||||
/* UART Control Register Bit Fields.*/
|
||||
#define URXD_CHARRDY (1<<15)
|
||||
#define URXD_ERR (1<<14)
|
||||
|
@ -128,6 +106,33 @@
|
|||
#define UTS_RXFULL (1<<3) /* RxFIFO full */
|
||||
#define UTS_SOFTRST (1<<0) /* Software reset */
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
|
||||
#ifndef CONFIG_MXC_UART_BASE
|
||||
#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
|
||||
#endif
|
||||
|
||||
#define UART_PHYS CONFIG_MXC_UART_BASE
|
||||
|
||||
#define __REG(x) (*((volatile u32 *)(x)))
|
||||
|
||||
/* Register definitions */
|
||||
#define URXD 0x0 /* Receiver Register */
|
||||
#define UTXD 0x40 /* Transmitter Register */
|
||||
#define UCR1 0x80 /* Control Register 1 */
|
||||
#define UCR2 0x84 /* Control Register 2 */
|
||||
#define UCR3 0x88 /* Control Register 3 */
|
||||
#define UCR4 0x8c /* Control Register 4 */
|
||||
#define UFCR 0x90 /* FIFO Control Register */
|
||||
#define USR1 0x94 /* Status Register 1 */
|
||||
#define USR2 0x98 /* Status Register 2 */
|
||||
#define UESC 0x9c /* Escape Character Register */
|
||||
#define UTIM 0xa0 /* Escape Timer Register */
|
||||
#define UBIR 0xa4 /* BRM Incremental Register */
|
||||
#define UBMR 0xa8 /* BRM Modulator Register */
|
||||
#define UBRC 0xac /* Baud Rate Count Register */
|
||||
#define UTS 0xb4 /* UART Test Register (mx31) */
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static void mxc_serial_setbrg(void)
|
||||
|
@ -222,3 +227,118 @@ __weak struct serial_device *default_serial_console(void)
|
|||
{
|
||||
return &mxc_serial_drv;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_SERIAL
|
||||
|
||||
struct mxc_uart {
|
||||
u32 rxd;
|
||||
u32 spare0[15];
|
||||
|
||||
u32 txd;
|
||||
u32 spare1[15];
|
||||
|
||||
u32 cr1;
|
||||
u32 cr2;
|
||||
u32 cr3;
|
||||
u32 cr4;
|
||||
|
||||
u32 fcr;
|
||||
u32 sr1;
|
||||
u32 sr2;
|
||||
u32 esc;
|
||||
|
||||
u32 tim;
|
||||
u32 bir;
|
||||
u32 bmr;
|
||||
u32 brc;
|
||||
|
||||
u32 onems;
|
||||
u32 ts;
|
||||
};
|
||||
|
||||
int mxc_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
struct mxc_uart *const uart = plat->reg;
|
||||
u32 clk = imx_get_uartclk();
|
||||
|
||||
writel(4 << 7, &uart->fcr); /* divide input clock by 2 */
|
||||
writel(0xf, &uart->bir);
|
||||
writel(clk / (2 * baudrate), &uart->bmr);
|
||||
|
||||
writel(UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST,
|
||||
&uart->cr2);
|
||||
writel(UCR1_UARTEN, &uart->cr1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
struct mxc_uart *const uart = plat->reg;
|
||||
|
||||
writel(0, &uart->cr1);
|
||||
writel(0, &uart->cr2);
|
||||
while (!(readl(&uart->cr2) & UCR2_SRST));
|
||||
writel(0x704 | UCR3_ADNIMP, &uart->cr3);
|
||||
writel(0x8000, &uart->cr4);
|
||||
writel(0x2b, &uart->esc);
|
||||
writel(0, &uart->tim);
|
||||
writel(0, &uart->ts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
struct mxc_uart *const uart = plat->reg;
|
||||
|
||||
if (readl(&uart->ts) & UTS_RXEMPTY)
|
||||
return -EAGAIN;
|
||||
|
||||
return readl(&uart->rxd) & URXD_RX_DATA;
|
||||
}
|
||||
|
||||
static int mxc_serial_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
struct mxc_uart *const uart = plat->reg;
|
||||
|
||||
if (!(readl(&uart->ts) & UTS_TXEMPTY))
|
||||
return -EAGAIN;
|
||||
|
||||
writel(ch, &uart->txd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
struct mxc_uart *const uart = plat->reg;
|
||||
uint32_t sr2 = readl(&uart->sr2);
|
||||
|
||||
if (input)
|
||||
return sr2 & USR2_RDR ? 1 : 0;
|
||||
else
|
||||
return sr2 & USR2_TXDC ? 0 : 1;
|
||||
}
|
||||
|
||||
static const struct dm_serial_ops mxc_serial_ops = {
|
||||
.putc = mxc_serial_putc,
|
||||
.pending = mxc_serial_pending,
|
||||
.getc = mxc_serial_getc,
|
||||
.setbrg = mxc_serial_setbrg,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_mxc) = {
|
||||
.name = "serial_mxc",
|
||||
.id = UCLASS_SERIAL,
|
||||
.probe = mxc_serial_probe,
|
||||
.ops = &mxc_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -12,203 +12,44 @@
|
|||
/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
#include <serial_pl01x.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "serial_pl01x.h"
|
||||
#include "serial_pl01x_internal.h"
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
|
||||
/*
|
||||
* Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
|
||||
* Integrator CP has two UARTs, use the first one, at 38400-8-N-1
|
||||
* Versatile PB has four UARTs.
|
||||
*/
|
||||
#define CONSOLE_PORT CONFIG_CONS_INDEX
|
||||
static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
|
||||
static enum pl01x_type pl01x_type __attribute__ ((section(".data")));
|
||||
static struct pl01x_regs *base_regs __attribute__ ((section(".data")));
|
||||
#define NUM_PORTS (sizeof(port)/sizeof(port[0]))
|
||||
|
||||
static void pl01x_putc (int portnum, char c);
|
||||
static int pl01x_getc (int portnum);
|
||||
static int pl01x_tstc (int portnum);
|
||||
unsigned int baudrate = CONFIG_BAUDRATE;
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static struct pl01x_regs *pl01x_get_regs(int portnum)
|
||||
{
|
||||
return (struct pl01x_regs *) port[portnum];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PL010_SERIAL
|
||||
|
||||
static int pl01x_serial_init(void)
|
||||
{
|
||||
struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
|
||||
unsigned int divisor;
|
||||
|
||||
/* First, disable everything */
|
||||
writel(0, ®s->pl010_cr);
|
||||
|
||||
/* Set baud rate */
|
||||
switch (baudrate) {
|
||||
case 9600:
|
||||
divisor = UART_PL010_BAUD_9600;
|
||||
break;
|
||||
|
||||
case 19200:
|
||||
divisor = UART_PL010_BAUD_9600;
|
||||
break;
|
||||
|
||||
case 38400:
|
||||
divisor = UART_PL010_BAUD_38400;
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
divisor = UART_PL010_BAUD_57600;
|
||||
break;
|
||||
|
||||
case 115200:
|
||||
divisor = UART_PL010_BAUD_115200;
|
||||
break;
|
||||
|
||||
default:
|
||||
divisor = UART_PL010_BAUD_38400;
|
||||
}
|
||||
|
||||
writel((divisor & 0xf00) >> 8, ®s->pl010_lcrm);
|
||||
writel(divisor & 0xff, ®s->pl010_lcrl);
|
||||
|
||||
/* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */
|
||||
writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN, ®s->pl010_lcrh);
|
||||
|
||||
/* Finally, enable the UART */
|
||||
writel(UART_PL010_CR_UARTEN, ®s->pl010_cr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PL010_SERIAL */
|
||||
|
||||
#ifdef CONFIG_PL011_SERIAL
|
||||
|
||||
static int pl01x_serial_init(void)
|
||||
{
|
||||
struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
|
||||
unsigned int temp;
|
||||
unsigned int divider;
|
||||
unsigned int remainder;
|
||||
unsigned int fraction;
|
||||
unsigned int lcr;
|
||||
|
||||
#ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT
|
||||
/* Empty RX fifo if necessary */
|
||||
if (readl(®s->pl011_cr) & UART_PL011_CR_UARTEN) {
|
||||
while (!(readl(®s->fr) & UART_PL01x_FR_RXFE))
|
||||
readl(®s->dr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* First, disable everything */
|
||||
writel(0, ®s->pl011_cr);
|
||||
|
||||
/*
|
||||
* Set baud rate
|
||||
*
|
||||
* IBRD = UART_CLK / (16 * BAUD_RATE)
|
||||
* FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE))
|
||||
*/
|
||||
temp = 16 * baudrate;
|
||||
divider = CONFIG_PL011_CLOCK / temp;
|
||||
remainder = CONFIG_PL011_CLOCK % temp;
|
||||
temp = (8 * remainder) / baudrate;
|
||||
fraction = (temp >> 1) + (temp & 1);
|
||||
|
||||
writel(divider, ®s->pl011_ibrd);
|
||||
writel(fraction, ®s->pl011_fbrd);
|
||||
|
||||
/* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */
|
||||
lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN;
|
||||
writel(lcr, ®s->pl011_lcrh);
|
||||
|
||||
#ifdef CONFIG_PL011_SERIAL_RLCR
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Program receive line control register after waiting
|
||||
* 10 bus cycles. Delay be writing to readonly register
|
||||
* 10 times
|
||||
*/
|
||||
for (i = 0; i < 10; i++)
|
||||
writel(lcr, ®s->fr);
|
||||
|
||||
writel(lcr, ®s->pl011_rlcr);
|
||||
/* lcrh needs to be set again for change to be effective */
|
||||
writel(lcr, ®s->pl011_lcrh);
|
||||
}
|
||||
#endif
|
||||
/* Finally, enable the UART */
|
||||
writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE |
|
||||
UART_PL011_CR_RTS, ®s->pl011_cr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PL011_SERIAL */
|
||||
|
||||
static void pl01x_serial_putc(const char c)
|
||||
static int pl01x_putc(struct pl01x_regs *regs, char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
pl01x_putc (CONSOLE_PORT, '\r');
|
||||
|
||||
pl01x_putc (CONSOLE_PORT, c);
|
||||
}
|
||||
|
||||
static int pl01x_serial_getc(void)
|
||||
{
|
||||
return pl01x_getc (CONSOLE_PORT);
|
||||
}
|
||||
|
||||
static int pl01x_serial_tstc(void)
|
||||
{
|
||||
return pl01x_tstc (CONSOLE_PORT);
|
||||
}
|
||||
|
||||
static void pl01x_serial_setbrg(void)
|
||||
{
|
||||
struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
|
||||
|
||||
baudrate = gd->baudrate;
|
||||
/*
|
||||
* Flush FIFO and wait for non-busy before changing baudrate to avoid
|
||||
* crap in console
|
||||
*/
|
||||
while (!(readl(®s->fr) & UART_PL01x_FR_TXFE))
|
||||
WATCHDOG_RESET();
|
||||
while (readl(®s->fr) & UART_PL01x_FR_BUSY)
|
||||
WATCHDOG_RESET();
|
||||
serial_init();
|
||||
}
|
||||
|
||||
static void pl01x_putc (int portnum, char c)
|
||||
{
|
||||
struct pl01x_regs *regs = pl01x_get_regs(portnum);
|
||||
|
||||
/* Wait until there is space in the FIFO */
|
||||
while (readl(®s->fr) & UART_PL01x_FR_TXFF)
|
||||
WATCHDOG_RESET();
|
||||
if (readl(®s->fr) & UART_PL01x_FR_TXFF)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Send the character */
|
||||
writel(c, ®s->dr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl01x_getc (int portnum)
|
||||
static int pl01x_getc(struct pl01x_regs *regs)
|
||||
{
|
||||
struct pl01x_regs *regs = pl01x_get_regs(portnum);
|
||||
unsigned int data;
|
||||
|
||||
/* Wait until there is data in the FIFO */
|
||||
while (readl(®s->fr) & UART_PL01x_FR_RXFE)
|
||||
WATCHDOG_RESET();
|
||||
if (readl(®s->fr) & UART_PL01x_FR_RXFE)
|
||||
return -EAGAIN;
|
||||
|
||||
data = readl(®s->dr);
|
||||
|
||||
|
@ -222,14 +63,199 @@ static int pl01x_getc (int portnum)
|
|||
return (int) data;
|
||||
}
|
||||
|
||||
static int pl01x_tstc (int portnum)
|
||||
static int pl01x_tstc(struct pl01x_regs *regs)
|
||||
{
|
||||
struct pl01x_regs *regs = pl01x_get_regs(portnum);
|
||||
|
||||
WATCHDOG_RESET();
|
||||
return !(readl(®s->fr) & UART_PL01x_FR_RXFE);
|
||||
}
|
||||
|
||||
static int pl01x_generic_serial_init(struct pl01x_regs *regs,
|
||||
enum pl01x_type type)
|
||||
{
|
||||
unsigned int lcr;
|
||||
|
||||
#ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT
|
||||
if (type == TYPE_PL011) {
|
||||
/* Empty RX fifo if necessary */
|
||||
if (readl(®s->pl011_cr) & UART_PL011_CR_UARTEN) {
|
||||
while (!(readl(®s->fr) & UART_PL01x_FR_RXFE))
|
||||
readl(®s->dr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* First, disable everything */
|
||||
writel(0, ®s->pl010_cr);
|
||||
|
||||
/* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */
|
||||
lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN;
|
||||
writel(lcr, ®s->pl011_lcrh);
|
||||
|
||||
switch (type) {
|
||||
case TYPE_PL010:
|
||||
break;
|
||||
case TYPE_PL011: {
|
||||
#ifdef CONFIG_PL011_SERIAL_RLCR
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Program receive line control register after waiting
|
||||
* 10 bus cycles. Delay be writing to readonly register
|
||||
* 10 times
|
||||
*/
|
||||
for (i = 0; i < 10; i++)
|
||||
writel(lcr, ®s->fr);
|
||||
|
||||
writel(lcr, ®s->pl011_rlcr);
|
||||
/* lcrh needs to be set again for change to be effective */
|
||||
writel(lcr, ®s->pl011_lcrh);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type,
|
||||
int clock, int baudrate)
|
||||
{
|
||||
switch (type) {
|
||||
case TYPE_PL010: {
|
||||
unsigned int divisor;
|
||||
|
||||
switch (baudrate) {
|
||||
case 9600:
|
||||
divisor = UART_PL010_BAUD_9600;
|
||||
break;
|
||||
case 19200:
|
||||
divisor = UART_PL010_BAUD_9600;
|
||||
break;
|
||||
case 38400:
|
||||
divisor = UART_PL010_BAUD_38400;
|
||||
break;
|
||||
case 57600:
|
||||
divisor = UART_PL010_BAUD_57600;
|
||||
break;
|
||||
case 115200:
|
||||
divisor = UART_PL010_BAUD_115200;
|
||||
break;
|
||||
default:
|
||||
divisor = UART_PL010_BAUD_38400;
|
||||
}
|
||||
|
||||
writel((divisor & 0xf00) >> 8, ®s->pl010_lcrm);
|
||||
writel(divisor & 0xff, ®s->pl010_lcrl);
|
||||
|
||||
/* Finally, enable the UART */
|
||||
writel(UART_PL010_CR_UARTEN, ®s->pl010_cr);
|
||||
break;
|
||||
}
|
||||
case TYPE_PL011: {
|
||||
unsigned int temp;
|
||||
unsigned int divider;
|
||||
unsigned int remainder;
|
||||
unsigned int fraction;
|
||||
|
||||
/*
|
||||
* Set baud rate
|
||||
*
|
||||
* IBRD = UART_CLK / (16 * BAUD_RATE)
|
||||
* FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
|
||||
* / (16 * BAUD_RATE))
|
||||
*/
|
||||
temp = 16 * baudrate;
|
||||
divider = clock / temp;
|
||||
remainder = clock % temp;
|
||||
temp = (8 * remainder) / baudrate;
|
||||
fraction = (temp >> 1) + (temp & 1);
|
||||
|
||||
writel(divider, ®s->pl011_ibrd);
|
||||
writel(fraction, ®s->pl011_fbrd);
|
||||
|
||||
/* Finally, enable the UART */
|
||||
writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
|
||||
UART_PL011_CR_RXE | UART_PL011_CR_RTS, ®s->pl011_cr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
static void pl01x_serial_init_baud(int baudrate)
|
||||
{
|
||||
int clock = 0;
|
||||
|
||||
#if defined(CONFIG_PL010_SERIAL)
|
||||
pl01x_type = TYPE_PL010;
|
||||
#elif defined(CONFIG_PL011_SERIAL)
|
||||
pl01x_type = TYPE_PL011;
|
||||
clock = CONFIG_PL011_CLOCK;
|
||||
#endif
|
||||
base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX];
|
||||
|
||||
pl01x_generic_serial_init(base_regs, pl01x_type);
|
||||
pl01x_generic_setbrg(base_regs, TYPE_PL010, clock, baudrate);
|
||||
}
|
||||
|
||||
/*
|
||||
* Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
|
||||
* Integrator CP has two UARTs, use the first one, at 38400-8-N-1
|
||||
* Versatile PB has four UARTs.
|
||||
*/
|
||||
int pl01x_serial_init(void)
|
||||
{
|
||||
pl01x_serial_init_baud(CONFIG_BAUDRATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pl01x_serial_putc(const char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
while (pl01x_putc(base_regs, '\r') == -EAGAIN);
|
||||
|
||||
while (pl01x_putc(base_regs, c) == -EAGAIN);
|
||||
}
|
||||
|
||||
static int pl01x_serial_getc(void)
|
||||
{
|
||||
while (1) {
|
||||
int ch = pl01x_getc(base_regs);
|
||||
|
||||
if (ch == -EAGAIN) {
|
||||
WATCHDOG_RESET();
|
||||
continue;
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
static int pl01x_serial_tstc(void)
|
||||
{
|
||||
return pl01x_tstc(base_regs);
|
||||
}
|
||||
|
||||
static void pl01x_serial_setbrg(void)
|
||||
{
|
||||
/*
|
||||
* Flush FIFO and wait for non-busy before changing baudrate to avoid
|
||||
* crap in console
|
||||
*/
|
||||
while (!(readl(&base_regs->fr) & UART_PL01x_FR_TXFE))
|
||||
WATCHDOG_RESET();
|
||||
while (readl(&base_regs->fr) & UART_PL01x_FR_BUSY)
|
||||
WATCHDOG_RESET();
|
||||
pl01x_serial_init_baud(gd->baudrate);
|
||||
}
|
||||
|
||||
static struct serial_device pl01x_serial_drv = {
|
||||
.name = "pl01x_serial",
|
||||
.start = pl01x_serial_init,
|
||||
|
@ -250,3 +276,74 @@ __weak struct serial_device *default_serial_console(void)
|
|||
{
|
||||
return &pl01x_serial_drv;
|
||||
}
|
||||
|
||||
#endif /* nCONFIG_DM_SERIAL */
|
||||
|
||||
#ifdef CONFIG_DM_SERIAL
|
||||
|
||||
struct pl01x_priv {
|
||||
struct pl01x_regs *regs;
|
||||
enum pl01x_type type;
|
||||
};
|
||||
|
||||
static int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
|
||||
struct pl01x_priv *priv = dev_get_priv(dev);
|
||||
|
||||
pl01x_generic_setbrg(priv->regs, priv->type, plat->clock, baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl01x_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
|
||||
struct pl01x_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->regs = (struct pl01x_regs *)plat->base;
|
||||
priv->type = plat->type;
|
||||
return pl01x_generic_serial_init(priv->regs, priv->type);
|
||||
}
|
||||
|
||||
static int pl01x_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct pl01x_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return pl01x_getc(priv->regs);
|
||||
}
|
||||
|
||||
static int pl01x_serial_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct pl01x_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return pl01x_putc(priv->regs, ch);
|
||||
}
|
||||
|
||||
static int pl01x_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct pl01x_priv *priv = dev_get_priv(dev);
|
||||
unsigned int fr = readl(&priv->regs->fr);
|
||||
|
||||
if (input)
|
||||
return pl01x_tstc(priv->regs);
|
||||
else
|
||||
return fr & UART_PL01x_FR_TXFF ? 0 : 1;
|
||||
}
|
||||
|
||||
static const struct dm_serial_ops pl01x_serial_ops = {
|
||||
.putc = pl01x_serial_putc,
|
||||
.pending = pl01x_serial_pending,
|
||||
.getc = pl01x_serial_getc,
|
||||
.setbrg = pl01x_serial_setbrg,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_pl01x) = {
|
||||
.name = "serial_pl01x",
|
||||
.id = UCLASS_SERIAL,
|
||||
.probe = pl01x_serial_probe,
|
||||
.ops = &pl01x_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue