Merge git://git.denx.de/u-boot-dm
authorTom Rini <trini@ti.com>
Fri, 12 Dec 2014 01:47:34 +0000 (20:47 -0500)
committerTom Rini <trini@ti.com>
Fri, 12 Dec 2014 01:47:34 +0000 (20:47 -0500)
73 files changed:
arch/arm/cpu/armv7/tegra124/Kconfig
arch/arm/cpu/tegra20-common/pmu.c
arch/arm/dts/Makefile
arch/arm/dts/cros-ec-keyboard.dtsi [new file with mode: 0644]
arch/arm/dts/tegra124-jetson-tk1.dts
arch/arm/dts/tegra124-nyan-big.dts [new file with mode: 0644]
arch/arm/dts/tegra124.dtsi
arch/arm/dts/tegra30-tec-ng.dts
arch/arm/include/asm/arch-tegra/tegra_i2c.h
arch/sandbox/dts/sandbox.dts
arch/sandbox/include/asm/test.h [new file with mode: 0644]
board/avionic-design/common/tamonten-ng.c
board/nvidia/cardhu/cardhu.c
board/nvidia/common/board.c
board/nvidia/dalmore/dalmore.c
board/nvidia/nyan-big/Kconfig [new file with mode: 0644]
board/nvidia/nyan-big/MAINTAINERS [new file with mode: 0644]
board/nvidia/nyan-big/Makefile [new file with mode: 0644]
board/nvidia/nyan-big/nyan-big.c [new file with mode: 0644]
board/nvidia/nyan-big/pinmux-config-nyan-big.h [new file with mode: 0644]
board/nvidia/venice2/as3722_init.h
board/nvidia/whistler/whistler.c
board/raspberrypi/rpi/rpi.c
board/toradex/apalis_t30/apalis_t30.c
common/cmd_i2c.c
configs/nyan-big_defconfig [new file with mode: 0644]
drivers/core/device.c
drivers/i2c/Makefile
drivers/i2c/i2c-emul-uclass.c [new file with mode: 0644]
drivers/i2c/i2c-uclass.c [new file with mode: 0644]
drivers/i2c/sandbox_i2c.c [new file with mode: 0644]
drivers/i2c/tegra_i2c.c
drivers/misc/Makefile
drivers/misc/i2c_eeprom.c [new file with mode: 0644]
drivers/misc/i2c_eeprom_emul.c [new file with mode: 0644]
drivers/power/tps6586x.c
drivers/serial/serial_pl01x.c
drivers/usb/gadget/ether.c
include/config_fallbacks.h
include/configs/apalis_t30.h
include/configs/beaver.h
include/configs/cardhu.h
include/configs/colibri_t30.h
include/configs/dalmore.h
include/configs/jetson-tk1.h
include/configs/nyan-big.h [new file with mode: 0644]
include/configs/rpi.h
include/configs/sandbox.h
include/configs/seaboard.h
include/configs/tec-ng.h
include/configs/tegra-common.h
include/configs/tegra114-common.h
include/configs/tegra124-common.h
include/configs/tegra20-common.h
include/configs/tegra30-common.h
include/configs/trimslice.h
include/configs/venice2.h
include/configs/whistler.h
include/dm/uclass-id.h
include/dm/ut.h
include/dt-bindings/pinctrl/pinctrl-tegra.h [new file with mode: 0644]
include/errno.h
include/i2c.h
include/i2c_eeprom.h [new file with mode: 0644]
include/linux/string.h
include/tps6586x.h
lib/Makefile
lib/errno_str.c [new file with mode: 0644]
lib/string.c
test/dm/Makefile
test/dm/cmd_dm.c
test/dm/i2c.c [new file with mode: 0644]
test/dm/test.dts

index 6a1c83a27ba65631e3fa01a1fb4b9b06bf667294..88f627c9326cd432d3948bd06d4404e2fe34c670 100644 (file)
@@ -6,6 +6,15 @@ choice
 config TARGET_JETSON_TK1
        bool "NVIDIA Tegra124 Jetson TK1 board"
 
+config TARGET_NYAN_BIG
+       bool "Google/NVIDIA Nyan-big Chrombook"
+       help
+         Nyan Big is a Tegra124 clamshell board that is very similar
+         to venice2, but it has a different panel, the sdcard CD and WP
+         sense are flipped, and it has a different revision of the AS3722
+         PMIC. The retail name is the Acer Chromebook 13 CB5-311-T7NN
+         (13.3-inch HD, NVIDIA Tegra K1, 2GB).
+
 config TARGET_VENICE2
        bool "NVIDIA Tegra124 Venice2"
 
@@ -15,6 +24,7 @@ config SYS_SOC
        default "tegra124"
 
 source "board/nvidia/jetson-tk1/Kconfig"
+source "board/nvidia/nyan-big/Kconfig"
 source "board/nvidia/venice2/Kconfig"
 
 endif
index c595f70e939931359f08d7b8f0184c054baeab8d..36a76a24d971e7d012570cc7ad7e3c16a2a1a4f5 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <i2c.h>
 #include <tps6586x.h>
 #include <asm/io.h>
 #include <asm/arch/tegra.h>
 #define VDD_TRANSITION_STEP    0x06    /* 150mv */
 #define VDD_TRANSITION_RATE    0x06    /* 3.52mv/us */
 
+#define PMI_I2C_ADDRESS        0x34    /* chip requires this address */
+
 int pmu_set_nominal(void)
 {
-       int core, cpu, bus;
+       struct udevice *bus, *dev;
+       int core, cpu;
+       int ret;
 
        /* by default, the table has been filled with T25 settings */
        switch (tegra_get_chip_sku()) {
@@ -42,12 +47,18 @@ int pmu_set_nominal(void)
                return -1;
        }
 
-       bus = tegra_i2c_get_dvc_bus_num();
-       if (bus == -1) {
+       ret = tegra_i2c_get_dvc_bus(&bus);
+       if (ret) {
                debug("%s: Cannot find DVC I2C bus\n", __func__);
-               return -1;
+               return ret;
        }
-       tps6586x_init(bus);
+       ret = i2c_get_chip(bus, PMI_I2C_ADDRESS, &dev);
+       if (ret) {
+               debug("%s: Cannot find DVC I2C chip\n", __func__);
+               return ret;
+       }
+
+       tps6586x_init(dev);
        tps6586x_set_pwm_mode(TPS6586X_PWM_SM1);
        return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP,
                                VDD_TRANSITION_RATE, VDD_RELATION);
index 187d58c498be88c27496b458d43bb50afa958f19..e6a495cb0dc549bfb1adb64302bbe52c60fab2e9 100644 (file)
@@ -31,6 +31,7 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
        tegra30-tec-ng.dtb \
        tegra114-dalmore.dtb \
        tegra124-jetson-tk1.dtb \
+       tegra124-nyan-big.dtb \
        tegra124-venice2.dtb
 dtb-$(CONFIG_ARCH_UNIPHIER) += \
        uniphier-ph1-sld3-ref.dtb \
diff --git a/arch/arm/dts/cros-ec-keyboard.dtsi b/arch/arm/dts/cros-ec-keyboard.dtsi
new file mode 100644 (file)
index 0000000..9c7fb0a
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Keyboard dts fragment for devices that use cros-ec-keyboard
+ *
+ * Copyright (c) 2014 Google, Inc
+ *
+ * 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 <dt-bindings/input/input.h>
+
+&cros_ec {
+       keyboard-controller {
+               compatible = "google,cros-ec-keyb";
+               keypad,num-rows = <8>;
+               keypad,num-columns = <13>;
+               google,needs-ghost-filter;
+
+               linux,keymap = <
+                       MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
+                       MATRIX_KEY(0x00, 0x02, KEY_F1)
+                       MATRIX_KEY(0x00, 0x03, KEY_B)
+                       MATRIX_KEY(0x00, 0x04, KEY_F10)
+                       MATRIX_KEY(0x00, 0x06, KEY_N)
+                       MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
+                       MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
+
+                       MATRIX_KEY(0x01, 0x01, KEY_ESC)
+                       MATRIX_KEY(0x01, 0x02, KEY_F4)
+                       MATRIX_KEY(0x01, 0x03, KEY_G)
+                       MATRIX_KEY(0x01, 0x04, KEY_F7)
+                       MATRIX_KEY(0x01, 0x06, KEY_H)
+                       MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
+                       MATRIX_KEY(0x01, 0x09, KEY_F9)
+                       MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
+
+                       MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
+                       MATRIX_KEY(0x02, 0x01, KEY_TAB)
+                       MATRIX_KEY(0x02, 0x02, KEY_F3)
+                       MATRIX_KEY(0x02, 0x03, KEY_T)
+                       MATRIX_KEY(0x02, 0x04, KEY_F6)
+                       MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
+                       MATRIX_KEY(0x02, 0x06, KEY_Y)
+                       MATRIX_KEY(0x02, 0x07, KEY_102ND)
+                       MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
+                       MATRIX_KEY(0x02, 0x09, KEY_F8)
+
+                       MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
+                       MATRIX_KEY(0x03, 0x02, KEY_F2)
+                       MATRIX_KEY(0x03, 0x03, KEY_5)
+                       MATRIX_KEY(0x03, 0x04, KEY_F5)
+                       MATRIX_KEY(0x03, 0x06, KEY_6)
+                       MATRIX_KEY(0x03, 0x08, KEY_MINUS)
+                       MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
+
+                       MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
+                       MATRIX_KEY(0x04, 0x01, KEY_A)
+                       MATRIX_KEY(0x04, 0x02, KEY_D)
+                       MATRIX_KEY(0x04, 0x03, KEY_F)
+                       MATRIX_KEY(0x04, 0x04, KEY_S)
+                       MATRIX_KEY(0x04, 0x05, KEY_K)
+                       MATRIX_KEY(0x04, 0x06, KEY_J)
+                       MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
+                       MATRIX_KEY(0x04, 0x09, KEY_L)
+                       MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
+                       MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
+
+                       MATRIX_KEY(0x05, 0x01, KEY_Z)
+                       MATRIX_KEY(0x05, 0x02, KEY_C)
+                       MATRIX_KEY(0x05, 0x03, KEY_V)
+                       MATRIX_KEY(0x05, 0x04, KEY_X)
+                       MATRIX_KEY(0x05, 0x05, KEY_COMMA)
+                       MATRIX_KEY(0x05, 0x06, KEY_M)
+                       MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
+                       MATRIX_KEY(0x05, 0x08, KEY_SLASH)
+                       MATRIX_KEY(0x05, 0x09, KEY_DOT)
+                       MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
+
+                       MATRIX_KEY(0x06, 0x01, KEY_1)
+                       MATRIX_KEY(0x06, 0x02, KEY_3)
+                       MATRIX_KEY(0x06, 0x03, KEY_4)
+                       MATRIX_KEY(0x06, 0x04, KEY_2)
+                       MATRIX_KEY(0x06, 0x05, KEY_8)
+                       MATRIX_KEY(0x06, 0x06, KEY_7)
+                       MATRIX_KEY(0x06, 0x08, KEY_0)
+                       MATRIX_KEY(0x06, 0x09, KEY_9)
+                       MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
+                       MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
+                       MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
+
+                       MATRIX_KEY(0x07, 0x01, KEY_Q)
+                       MATRIX_KEY(0x07, 0x02, KEY_E)
+                       MATRIX_KEY(0x07, 0x03, KEY_R)
+                       MATRIX_KEY(0x07, 0x04, KEY_W)
+                       MATRIX_KEY(0x07, 0x05, KEY_I)
+                       MATRIX_KEY(0x07, 0x06, KEY_U)
+                       MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
+                       MATRIX_KEY(0x07, 0x08, KEY_P)
+                       MATRIX_KEY(0x07, 0x09, KEY_O)
+                       MATRIX_KEY(0x07, 0x0b, KEY_UP)
+                       MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
+               >;
+       };
+};
index ffad1160cd92015bba208aec89d5848b7fa07e8a..f6fe9a050f511c05b963af7dc7217ff8b01e16f0 100644 (file)
@@ -16,7 +16,6 @@
                i2c2 = "/i2c@7000c400";
                i2c3 = "/i2c@7000c500";
                i2c4 = "/i2c@7000c700";
-               i2c5 = "/i2c@7000d100";
                sdhci0 = "/sdhci@700b0600";
                sdhci1 = "/sdhci@700b0400";
                spi0 = "/spi@7000d400";
diff --git a/arch/arm/dts/tegra124-nyan-big.dts b/arch/arm/dts/tegra124-nyan-big.dts
new file mode 100644 (file)
index 0000000..c1f35a0
--- /dev/null
@@ -0,0 +1,365 @@
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "tegra124.dtsi"
+
+/ {
+       model = "Acer Chromebook 13 CB5-311";
+       compatible = "google,nyan-big", "nvidia,tegra124";
+
+       aliases {
+               console = &uarta;
+               i2c0 = "/i2c@7000d000";
+               i2c1 = "/i2c@7000c000";
+               i2c2 = "/i2c@7000c400";
+               i2c3 = "/i2c@7000c500";
+               i2c4 = "/i2c@7000c700";
+               i2c5 = "/i2c@7000d100";
+               rtc0 = "/i2c@0,7000d000/pmic@40";
+               rtc1 = "/rtc@0,7000e000";
+               sdhci0 = "/sdhci@700b0600";
+               sdhci1 = "/sdhci@700b0400";
+               spi0 = "/spi@7000d400";
+               spi1 = "/spi@7000da00";
+               usb0 = "/usb@7d000000";
+               usb1 = "/usb@7d008000";
+       };
+
+       memory {
+               reg = <0x80000000 0x80000000>;
+       };
+
+       serial@70006000 {
+               /* Debug connector on the bottom of the board near SD card. */
+               status = "okay";
+       };
+
+       pwm@7000a000 {
+               status = "okay";
+       };
+
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               acodec: audio-codec@10 {
+                       compatible = "maxim,max98090";
+                       reg = <0x10>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
+               };
+
+               temperature-sensor@4c {
+                       compatible = "ti,tmp451";
+                       reg = <0x4c>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
+
+                       #thermal-sensor-cells = <1>;
+               };
+       };
+
+       i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2c@7000c500 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               tpm@20 {
+                       compatible = "infineon,slb9645tt";
+                       reg = <0x20>;
+               };
+       };
+
+       hdmi_ddc: i2c@7000c700 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               pmic: pmic@40 {
+                       compatible = "ams,as3722";
+                       reg = <0x40>;
+                       interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+
+                       ams,system-power-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&as3722_default>;
+
+                       as3722_default: pinmux {
+                               gpio0 {
+                                       pins = "gpio0";
+                                       function = "gpio";
+                                       bias-pull-down;
+                               };
+
+                               gpio1 {
+                                       pins = "gpio1";
+                                       function = "gpio";
+                                       bias-pull-up;
+                               };
+
+                               gpio2_4_7 {
+                                       pins = "gpio2", "gpio4", "gpio7";
+                                       function = "gpio";
+                                       bias-pull-up;
+                               };
+
+                               gpio3_6 {
+                                       pins = "gpio3", "gpio6";
+                                       bias-high-impedance;
+                               };
+
+                               gpio5 {
+                                       pins = "gpio5";
+                                       function = "clk32k-out";
+                                       bias-pull-down;
+                               };
+                       };
+               };
+       };
+
+       spi@7000d400 {
+               status = "okay";
+
+               cros_ec: cros-ec@0 {
+                       compatible = "google,cros-ec-spi";
+                       spi-max-frequency = <3000000>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_GPIO(C, 7) IRQ_TYPE_LEVEL_LOW>;
+                       reg = <0>;
+
+                       google,cros-ec-spi-msg-delay = <2000>;
+
+                       i2c-tunnel {
+                               compatible = "google,cros-ec-i2c-tunnel";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               google,remote-bus = <0>;
+
+                               charger: bq24735@9 {
+                                       compatible = "ti,bq24735";
+                                       reg = <0x9>;
+                                       interrupt-parent = <&gpio>;
+                                       interrupts = <TEGRA_GPIO(J, 0)
+                                                       GPIO_ACTIVE_HIGH>;
+                                       ti,ac-detect-gpios = <&gpio
+                                                       TEGRA_GPIO(J, 0)
+                                                       GPIO_ACTIVE_HIGH>;
+                               };
+
+                               battery: sbs-battery@b {
+                                       compatible = "sbs,sbs-battery";
+                                       reg = <0xb>;
+                                       sbs,i2c-retry-count = <2>;
+                                       sbs,poll-retry-count = <10>;
+                                       power-supplies = <&charger>;
+                               };
+                       };
+               };
+       };
+
+       spi@7000da00 {
+               status = "okay";
+               spi-max-frequency = <25000000>;
+
+               flash@0 {
+                       compatible = "winbond,w25q32dw";
+                       reg = <0>;
+               };
+       };
+
+       pmc@7000e400 {
+               nvidia,invert-interrupt;
+               nvidia,suspend-mode = <0>;
+               nvidia,cpu-pwr-good-time = <500>;
+               nvidia,cpu-pwr-off-time = <300>;
+               nvidia,core-pwr-good-time = <641 3845>;
+               nvidia,core-pwr-off-time = <61036>;
+               nvidia,core-power-req-active-high;
+               nvidia,sys-clock-req-active-high;
+       };
+
+       hda@70030000 {
+               status = "okay";
+       };
+
+       sdhci@700b0000 { /* WiFi/BT on this bus */
+               status = "okay";
+               power-gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_HIGH>;
+               bus-width = <4>;
+               no-1-8-v;
+               non-removable;
+       };
+
+       sdhci@700b0400 { /* SD Card on this bus */
+               status = "okay";
+               cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
+               power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
+               wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_LOW>;
+               bus-width = <4>;
+               no-1-8-v;
+       };
+
+       sdhci@700b0600 { /* eMMC on this bus */
+               status = "okay";
+               bus-width = <8>;
+               no-1-8-v;
+               non-removable;
+       };
+
+       ahub@70300000 {
+               i2s@70301100 {
+                       status = "okay";
+               };
+       };
+
+       usb@7d000000 { /* Rear external USB port. */
+               status = "okay";
+       };
+
+       usb-phy@7d000000 {
+               status = "okay";
+       };
+
+       usb@7d004000 { /* Internal webcam. */
+               status = "okay";
+       };
+
+       usb-phy@7d004000 {
+               status = "okay";
+       };
+
+       usb@7d008000 { /* Left external USB port. */
+               status = "okay";
+       };
+
+       usb-phy@7d008000 {
+               status = "okay";
+       };
+
+       backlight: backlight {
+               compatible = "pwm-backlight";
+
+               enable-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>;
+               pwms = <&pwm 1 1000000>;
+
+               default-brightness-level = <224>;
+               brightness-levels =
+                       <  0   1   2   3   4   5   6   7
+                          8   9  10  11  12  13  14  15
+                         16  17  18  19  20  21  22  23
+                         24  25  26  27  28  29  30  31
+                         32  33  34  35  36  37  38  39
+                         40  41  42  43  44  45  46  47
+                         48  49  50  51  52  53  54  55
+                         56  57  58  59  60  61  62  63
+                         64  65  66  67  68  69  70  71
+                         72  73  74  75  76  77  78  79
+                         80  81  82  83  84  85  86  87
+                         88  89  90  91  92  93  94  95
+                         96  97  98  99 100 101 102 103
+                        104 105 106 107 108 109 110 111
+                        112 113 114 115 116 117 118 119
+                        120 121 122 123 124 125 126 127
+                        128 129 130 131 132 133 134 135
+                        136 137 138 139 140 141 142 143
+                        144 145 146 147 148 149 150 151
+                        152 153 154 155 156 157 158 159
+                        160 161 162 163 164 165 166 167
+                        168 169 170 171 172 173 174 175
+                        176 177 178 179 180 181 182 183
+                        184 185 186 187 188 189 190 191
+                        192 193 194 195 196 197 198 199
+                        200 201 202 203 204 205 206 207
+                        208 209 210 211 212 213 214 215
+                        216 217 218 219 220 221 222 223
+                        224 225 226 227 228 229 230 231
+                        232 233 234 235 236 237 238 239
+                        240 241 242 243 244 245 246 247
+                        248 249 250 251 252 253 254 255
+                        256>;
+       };
+
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock@0 {
+                       compatible = "fixed-clock";
+                       reg = <0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               lid {
+                       label = "Lid";
+                       gpios = <&gpio TEGRA_GPIO(R, 4) GPIO_ACTIVE_LOW>;
+                       linux,input-type = <5>;
+                       linux,code = <KEY_RESERVED>;
+                       debounce-interval = <1>;
+                       gpio-key,wakeup;
+               };
+
+               power {
+                       label = "Power";
+                       gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+                       debounce-interval = <30>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       panel: panel {
+               compatible = "auo,b133xtn01";
+
+               backlight = <&backlight>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-max98090-nyan-big",
+                            "nvidia,tegra-audio-max98090";
+               nvidia,model = "Acer Chromebook 13";
+
+               nvidia,audio-routing =
+                       "Headphones", "HPR",
+                       "Headphones", "HPL",
+                       "Speakers", "SPKR",
+                       "Speakers", "SPKL",
+                       "Mic Jack", "MICBIAS",
+                       "DMICL", "Int Mic",
+                       "DMICR", "Int Mic",
+                       "IN34", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&acodec>;
+
+               clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
+                        <&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
+                        <&tegra_car TEGRA124_CLK_EXTERN1>;
+               clock-names = "pll_a", "pll_a_out0", "mclk";
+
+               nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(I, 7) GPIO_ACTIVE_HIGH>;
+       };
+};
+
+#include "cros-ec-keyboard.dtsi"
index 3288f28daeb069fb9584451aec5449e1fdf6cf5b..6b5c2bea63da610c00a655b9cca9d104f1eadb78 100644 (file)
@@ -1,5 +1,6 @@
 #include <dt-bindings/clock/tegra124-car.h>
 #include <dt-bindings/gpio/tegra-gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-tegra.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 #include "skeleton.dtsi"
                status = "disabled";
        };
 
+       pwm: pwm@7000a000 {
+               compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm";
+               reg = <0x7000a000 0x100>;
+               #pwm-cells = <2>;
+               clocks = <&tegra_car TEGRA124_CLK_PWM>;
+               resets = <&tegra_car 17>;
+               reset-names = "pwm";
+               status = "disabled";
+       };
+
        spi@7000d400 {
                compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
                reg = <0x7000d400 0x200>;
                status = "disabled";
        };
 
+       ahub@70300000 {
+               compatible = "nvidia,tegra124-ahub";
+               reg = <0x70300000 0x200>,
+                     <0x70300800 0x800>,
+                     <0x70300200 0x600>;
+               interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&tegra_car TEGRA124_CLK_D_AUDIO>,
+                        <&tegra_car TEGRA124_CLK_APBIF>;
+               clock-names = "d_audio", "apbif";
+               resets = <&tegra_car 106>, /* d_audio */
+                        <&tegra_car 107>, /* apbif */
+                        <&tegra_car 30>,  /* i2s0 */
+                        <&tegra_car 11>,  /* i2s1 */
+                        <&tegra_car 18>,  /* i2s2 */
+                        <&tegra_car 101>, /* i2s3 */
+                        <&tegra_car 102>, /* i2s4 */
+                        <&tegra_car 108>, /* dam0 */
+                        <&tegra_car 109>, /* dam1 */
+                        <&tegra_car 110>, /* dam2 */
+                        <&tegra_car 10>,  /* spdif */
+                        <&tegra_car 153>, /* amx */
+                        <&tegra_car 185>, /* amx1 */
+                        <&tegra_car 154>, /* adx */
+                        <&tegra_car 180>, /* adx1 */
+                        <&tegra_car 186>, /* afc0 */
+                        <&tegra_car 187>, /* afc1 */
+                        <&tegra_car 188>, /* afc2 */
+                        <&tegra_car 189>, /* afc3 */
+                        <&tegra_car 190>, /* afc4 */
+                        <&tegra_car 191>; /* afc5 */
+               reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
+                             "i2s3", "i2s4", "dam0", "dam1", "dam2",
+                             "spdif", "amx", "amx1", "adx", "adx1",
+                             "afc0", "afc1", "afc2", "afc3", "afc4", "afc5";
+               dmas = <&apbdma 1>, <&apbdma 1>,
+                      <&apbdma 2>, <&apbdma 2>,
+                      <&apbdma 3>, <&apbdma 3>,
+                      <&apbdma 4>, <&apbdma 4>,
+                      <&apbdma 6>, <&apbdma 6>,
+                      <&apbdma 7>, <&apbdma 7>,
+                      <&apbdma 12>, <&apbdma 12>,
+                      <&apbdma 13>, <&apbdma 13>,
+                      <&apbdma 14>, <&apbdma 14>,
+                      <&apbdma 29>, <&apbdma 29>;
+               dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2",
+                           "rx3", "tx3", "rx4", "tx4", "rx5", "tx5",
+                           "rx6", "tx6", "rx7", "tx7", "rx8", "tx8",
+                           "rx9", "tx9";
+               ranges;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               tegra_i2s0: i2s@70301000 {
+                       compatible = "nvidia,tegra124-i2s";
+                       reg = <0x70301000 0x100>;
+                       nvidia,ahub-cif-ids = <4 4>;
+                       clocks = <&tegra_car TEGRA124_CLK_I2S0>;
+                       resets = <&tegra_car 30>;
+                       reset-names = "i2s";
+                       status = "disabled";
+               };
+
+               tegra_i2s1: i2s@70301100 {
+                       compatible = "nvidia,tegra124-i2s";
+                       reg = <0x70301100 0x100>;
+                       nvidia,ahub-cif-ids = <5 5>;
+                       clocks = <&tegra_car TEGRA124_CLK_I2S1>;
+                       resets = <&tegra_car 11>;
+                       reset-names = "i2s";
+                       status = "disabled";
+               };
+
+               tegra_i2s2: i2s@70301200 {
+                       compatible = "nvidia,tegra124-i2s";
+                       reg = <0x70301200 0x100>;
+                       nvidia,ahub-cif-ids = <6 6>;
+                       clocks = <&tegra_car TEGRA124_CLK_I2S2>;
+                       resets = <&tegra_car 18>;
+                       reset-names = "i2s";
+                       status = "disabled";
+               };
+
+               tegra_i2s3: i2s@70301300 {
+                       compatible = "nvidia,tegra124-i2s";
+                       reg = <0x70301300 0x100>;
+                       nvidia,ahub-cif-ids = <7 7>;
+                       clocks = <&tegra_car TEGRA124_CLK_I2S3>;
+                       resets = <&tegra_car 101>;
+                       reset-names = "i2s";
+                       status = "disabled";
+               };
+
+               tegra_i2s4: i2s@70301400 {
+                       compatible = "nvidia,tegra124-i2s";
+                       reg = <0x70301400 0x100>;
+                       nvidia,ahub-cif-ids = <8 8>;
+                       clocks = <&tegra_car TEGRA124_CLK_I2S4>;
+                       resets = <&tegra_car 102>;
+                       reset-names = "i2s";
+                       status = "disabled";
+               };
+       };
+
        usb@7d000000 {
                compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci";
                reg = <0x7d000000 0x4000>;
index 8a69e818ca35166571c0588232a29732f0410d3d..e924acc35c93f2e6c8df318d0b3a672ce97ee35c 100644 (file)
@@ -6,6 +6,10 @@
        model = "Avionic Design Tamontenâ„¢ NG Evaluation Carrier";
        compatible = "ad,tec-ng", "nvidia,tegra30";
 
+       aliases {
+               i2c0 = "/i2c@7000c400";
+       };
+
        /* GEN2 */
        i2c@7000c400 {
                status = "okay";
index 7ca690700cb48bb7110ea5c3443f78ba0b2db5cb..eeeb247d5d5836159f99cd3d70254ec41e70c68f 100644 (file)
@@ -167,6 +167,6 @@ struct i2c_ctlr {
  *
  * @return number of bus, or -1 if there is no DVC active
  */
-int tegra_i2c_get_dvc_bus_num(void);
+int tegra_i2c_get_dvc_bus(struct udevice **busp);
 
 #endif /* _TEGRA_I2C_H_ */
index 76147154c22366b7f70e5a95e83c8ea8ee3dfbe1..11748aec7990e1ff40f9d625842a154d8d278cc1 100644 (file)
                num-gpios = <20>;
        };
 
+       i2c@0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0>;
+               compatible = "sandbox,i2c";
+               clock-frequency = <400000>;
+               eeprom@2c {
+                       reg = <0x2c>;
+                       compatible = "i2c-eeprom";
+                       emul {
+                               compatible = "sandbox,i2c-eeprom";
+                               sandbox,filename = "i2c.bin";
+                               sandbox,size = <128>;
+                       };
+               };
+       };
+
        spi@0 {
                #address-cells = <1>;
                #size-cells = <0>;
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
new file mode 100644 (file)
index 0000000..25a0c85
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Test-related constants for sandbox
+ *
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __ASM_TEST_H
+#define __ASM_TEST_H
+
+/* The sandbox driver always permits an I2C device with this address */
+#define SANDBOX_I2C_TEST_ADDR  0x59
+
+enum sandbox_i2c_eeprom_test_mode {
+       SIE_TEST_MODE_NONE,
+       /* Permits read/write of only one byte per I2C transaction */
+       SIE_TEST_MODE_SINGLE_BYTE,
+};
+
+void sandbox_i2c_eeprom_set_test_mode(struct udevice *dev,
+                                     enum sandbox_i2c_eeprom_test_mode mode);
+
+void sandbox_i2c_eeprom_set_offset_len(struct udevice *dev, int offset_len);
+
+#endif
index 5870b95afbf861c07475afc5faae6f73faac7589..86a0844273d64a28bb361709ed1107871c9d6c99 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/gp_padctrl.h>
 #include <asm/arch/gpio.h>
@@ -51,8 +52,15 @@ void gpio_early_init(void)
 
 void pmu_write(uchar reg, uchar data)
 {
-       i2c_set_bus_num(4);     /* PMU is on bus 4 */
-       i2c_write(PMU_I2C_ADDRESS, reg, 1, &data, 1);
+       struct udevice *dev;
+       int ret;
+
+       ret = i2c_get_chip_for_busnum(4, PMU_I2C_ADDRESS, &dev);
+       if (ret) {
+               debug("%s: Cannot find PMIC I2C chip\n", __func__);
+               return;
+       }
+       i2c_write(dev, reg, &data, 1);
 }
 
 /*
index cc0e5e130fda30209db2f8341a1fbcf461f2f39b..026f45c6c686da054603d908989604f2fd78301b 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/gp_padctrl.h>
 #include "pinmux-config-cardhu.h"
@@ -37,17 +38,23 @@ void pinmux_init(void)
  */
 void board_sdmmc_voltage_init(void)
 {
+       struct udevice *dev;
        uchar reg, data_buffer[1];
+       int ret;
        int i;
 
-       i2c_set_bus_num(0);     /* PMU is on bus 0 */
+       ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+       if (ret) {
+               debug("%s: Cannot find PMIC I2C chip\n", __func__);
+               return;
+       }
 
        /* TPS659110: LDO5_REG = 3.3v, ACTIVE to SDMMC1 */
        data_buffer[0] = 0x65;
        reg = 0x32;
 
        for (i = 0; i < MAX_I2C_RETRY; ++i) {
-               if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1))
+               if (i2c_write(dev, reg, data_buffer, 1))
                        udelay(100);
        }
 
@@ -56,7 +63,7 @@ void board_sdmmc_voltage_init(void)
        reg = 0x67;
 
        for (i = 0; i < MAX_I2C_RETRY; ++i) {
-               if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1))
+               if (i2c_write(dev, reg, data_buffer, 1))
                        udelay(100);
        }
 }
index 0e4a65ad059424ac6bea8aff10821e259ba18432..4bdbf0194ab54f5df0921b3d70613a0fb634e39d 100644 (file)
@@ -113,10 +113,6 @@ int board_init(void)
        power_det_init();
 
 #ifdef CONFIG_SYS_I2C_TEGRA
-#ifndef CONFIG_SYS_I2C_INIT_BOARD
-#error "You must define CONFIG_SYS_I2C_INIT_BOARD to use i2c on Nvidia boards"
-#endif
-       i2c_init_board();
 # ifdef CONFIG_TEGRA_PMU
        if (pmu_set_nominal())
                debug("Failed to select nominal voltages\n");
index f2d05afac791662932a54b82ee9359d3ff279f75..2a737468ddc4fce7411f2f9d183596c9edadf6c6 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/gp_padctrl.h>
 #include "pinmux-config-dalmore.h"
@@ -50,18 +51,21 @@ void pinmux_init(void)
  */
 void board_sdmmc_voltage_init(void)
 {
+       struct udevice *dev;
        uchar reg, data_buffer[1];
        int ret;
 
-       ret = i2c_set_bus_num(0);/* PMU is on bus 0 */
-       if (ret)
-               printf("%s: i2c_set_bus_num returned %d\n", __func__, ret);
+       ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+       if (ret) {
+               debug("%s: Cannot find PMIC I2C chip\n", __func__);
+               return;
+       }
 
        /* TPS65913: LDO9_VOLTAGE = 3.3V */
        data_buffer[0] = 0x31;
        reg = 0x61;
 
-       ret = i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1);
+       ret = i2c_write(dev, reg, data_buffer, 1);
        if (ret)
                printf("%s: PMU i2c_write %02X<-%02X returned %d\n",
                        __func__, reg, data_buffer[0], ret);
@@ -70,7 +74,7 @@ void board_sdmmc_voltage_init(void)
        data_buffer[0] = 0x01;
        reg = 0x60;
 
-       ret = i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1);
+       ret = i2c_write(dev, reg, data_buffer, 1);
        if (ret)
                printf("%s: PMU i2c_write %02X<-%02X returned %d\n",
                        __func__, reg, data_buffer[0], ret);
@@ -79,7 +83,12 @@ void board_sdmmc_voltage_init(void)
        data_buffer[0] = 0x03;
        reg = 0x14;
 
-       ret = i2c_write(BAT_I2C_ADDRESS, reg, 1, data_buffer, 1);
+       ret = i2c_get_chip_for_busnum(0, BAT_I2C_ADDRESS, &dev);
+       if (ret) {
+               debug("%s: Cannot find charger I2C chip\n", __func__);
+               return;
+       }
+       ret = i2c_write(dev, reg, data_buffer, 1);
        if (ret)
                printf("%s: BAT i2c_write %02X<-%02X returned %d\n",
                        __func__, reg, data_buffer[0], ret);
diff --git a/board/nvidia/nyan-big/Kconfig b/board/nvidia/nyan-big/Kconfig
new file mode 100644 (file)
index 0000000..6c42bb9
--- /dev/null
@@ -0,0 +1,24 @@
+if TARGET_NYAN_BIG
+
+config SYS_CPU
+       string
+       default "arm720t" if SPL_BUILD
+       default "armv7" if !SPL_BUILD
+
+config SYS_BOARD
+       string
+       default "nyan-big"
+
+config SYS_VENDOR
+       string
+       default "nvidia"
+
+config SYS_SOC
+       string
+       default "tegra124"
+
+config SYS_CONFIG_NAME
+       string
+       default "nyan-big"
+
+endif
diff --git a/board/nvidia/nyan-big/MAINTAINERS b/board/nvidia/nyan-big/MAINTAINERS
new file mode 100644 (file)
index 0000000..ff74627
--- /dev/null
@@ -0,0 +1,6 @@
+NORRIN BOARD
+M:     Allen Martin <amartin@nvidia.com>
+S:     Maintained
+F:     board/nvidia/nyan-big/
+F:     include/configs/nyan-big.h
+F:     configs/nyan-big_defconfig
diff --git a/board/nvidia/nyan-big/Makefile b/board/nvidia/nyan-big/Makefile
new file mode 100644 (file)
index 0000000..cd2f61d
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2014
+# NVIDIA Corporation <www.nvidia.com>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += ../venice2/as3722_init.o
+obj-y  += nyan-big.o
diff --git a/board/nvidia/nyan-big/nyan-big.c b/board/nvidia/nyan-big/nyan-big.c
new file mode 100644 (file)
index 0000000..d4d2496
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright 2014
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pinmux.h>
+#include "pinmux-config-nyan-big.h"
+
+/*
+ * Routine: pinmux_init
+ * Description: Do individual peripheral pinmux configs
+ */
+void pinmux_init(void)
+{
+       gpio_config_table(nyan_big_gpio_inits,
+                         ARRAY_SIZE(nyan_big_gpio_inits));
+
+       pinmux_config_pingrp_table(nyan_big_pingrps,
+                                  ARRAY_SIZE(nyan_big_pingrps));
+
+       pinmux_config_drvgrp_table(nyan_big_drvgrps,
+                                  ARRAY_SIZE(nyan_big_drvgrps));
+}
diff --git a/board/nvidia/nyan-big/pinmux-config-nyan-big.h b/board/nvidia/nyan-big/pinmux-config-nyan-big.h
new file mode 100644 (file)
index 0000000..9c5fbaa
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _PINMUX_CONFIG_NYAN_BIG_H_
+#define _PINMUX_CONFIG_NYAN_BIG_H_
+
+#define GPIO_INIT(_gpio, _init)                                \
+       {                                               \
+               .gpio   = GPIO_P##_gpio,                \
+               .init   = TEGRA_GPIO_INIT_##_init,      \
+       }
+
+static const struct tegra_gpio_config nyan_big_gpio_inits[] = {
+       /*        gpio, init_val */
+       GPIO_INIT(A0,   IN),
+       GPIO_INIT(C7,   IN),
+       GPIO_INIT(G0,   IN),
+       GPIO_INIT(G1,   IN),
+       GPIO_INIT(G2,   IN),
+       GPIO_INIT(G3,   IN),
+       GPIO_INIT(H2,   IN),
+       GPIO_INIT(H4,   IN),
+       GPIO_INIT(H6,   IN),
+       GPIO_INIT(H7,   OUT1),
+       GPIO_INIT(I0,   IN),
+       GPIO_INIT(I1,   IN),
+       GPIO_INIT(I5,   OUT1),
+       GPIO_INIT(I6,   IN),
+       GPIO_INIT(I7,   IN),
+       GPIO_INIT(J0,   IN),
+       GPIO_INIT(J7,   IN),
+       GPIO_INIT(K1,   OUT0),
+       GPIO_INIT(K2,   IN),
+       GPIO_INIT(K4,   OUT0),
+       GPIO_INIT(K6,   OUT0),
+       GPIO_INIT(K7,   IN),
+       GPIO_INIT(N7,   IN),
+       GPIO_INIT(P2,   OUT0),
+       GPIO_INIT(Q0,   IN),
+       GPIO_INIT(Q2,   IN),
+       GPIO_INIT(Q3,   IN),
+       GPIO_INIT(Q6,   IN),
+       GPIO_INIT(Q7,   IN),
+       GPIO_INIT(R0,   OUT0),
+       GPIO_INIT(R1,   IN),
+       GPIO_INIT(R4,   IN),
+       GPIO_INIT(R7,   IN),
+       GPIO_INIT(S3,   OUT0),
+       GPIO_INIT(S4,   OUT0),
+       GPIO_INIT(S7,   IN),
+       GPIO_INIT(T1,   IN),
+       GPIO_INIT(U4,   IN),
+       GPIO_INIT(U5,   IN),
+       GPIO_INIT(U6,   IN),
+       GPIO_INIT(V0,   IN),
+       GPIO_INIT(W3,   IN),
+       GPIO_INIT(X1,   IN),
+       GPIO_INIT(X4,   IN),
+       GPIO_INIT(X7,   OUT0),
+};
+
+#define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _rcv_sel) \
+       {                                                       \
+               .pingrp         = PMUX_PINGRP_##_pingrp,        \
+               .func           = PMUX_FUNC_##_mux,             \
+               .pull           = PMUX_PULL_##_pull,            \
+               .tristate       = PMUX_TRI_##_tri,              \
+               .io             = PMUX_PIN_##_io,               \
+               .od             = PMUX_PIN_OD_##_od,            \
+               .rcv_sel        = PMUX_PIN_RCV_SEL_##_rcv_sel,  \
+               .lock           = PMUX_PIN_LOCK_DEFAULT,        \
+               .ioreset        = PMUX_PIN_IO_RESET_DEFAULT,    \
+       }
+
+static const struct pmux_pingrp_config nyan_big_pingrps[] = {
+       /*     pingrp,                 mux,         pull,   tri,      e_input, od,      rcv_sel */
+       PINCFG(CLK_32K_OUT_PA0,        DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(UART3_CTS_N_PA1,        GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP2_FS_PA2,            I2S1,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(DAP2_SCLK_PA3,          I2S1,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(DAP2_DIN_PA4,           I2S1,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(DAP2_DOUT_PA5,          I2S1,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_CLK_PA6,         SDMMC3,      NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_CMD_PA7,         SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PB0,                    RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PB1,                    RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_DAT3_PB4,        SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_DAT2_PB5,        SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_DAT1_PB6,        SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_DAT0_PB7,        SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(UART3_RTS_N_PC0,        GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(UART2_TXD_PC2,          IRDA,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(UART2_RXD_PC3,          IRDA,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(GEN1_I2C_SCL_PC4,       I2C1,        NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(GEN1_I2C_SDA_PC5,       I2C1,        NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(PC7,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PG0,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PG1,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PG2,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PG3,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PG4,                    SPI4,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PG5,                    SPI4,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PG6,                    SPI4,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PG7,                    SPI4,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PH0,                    GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PH1,                    PWM1,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PH2,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PH3,                    GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PH4,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PH5,                    RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PH6,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PH7,                    DEFAULT,     NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PI0,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PI1,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PI2,                    RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PI3,                    SPI4,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PI4,                    GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PI5,                    DEFAULT,     UP,     NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PI6,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PI7,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PJ0,                    DEFAULT,     UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PJ2,                    RSVD1,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(UART2_CTS_N_PJ5,        GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(UART2_RTS_N_PJ6,        GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PJ7,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PK0,                    RSVD1,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PK1,                    DEFAULT,     NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PK2,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PK3,                    GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PK4,                    DEFAULT,     UP,     NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SPDIF_OUT_PK5,          RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SPDIF_IN_PK6,           DEFAULT,     DOWN,   NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PK7,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(DAP1_FS_PN0,            RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP1_DIN_PN1,           RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP1_DOUT_PN2,          I2S0,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP1_SCLK_PN3,          RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(USB_VBUS_EN0_PN4,       USB,         NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(USB_VBUS_EN1_PN5,       USB,         NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(HDMI_INT_PN7,           DEFAULT,     DOWN,   NORMAL,   INPUT,   DEFAULT, NORMAL),
+       PINCFG(ULPI_DATA7_PO0,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DATA0_PO1,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DATA1_PO2,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DATA2_PO3,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DATA3_PO4,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DATA4_PO5,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DATA5_PO6,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DATA6_PO7,         ULPI,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP3_FS_PP0,            I2S2,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP3_DIN_PP1,           I2S2,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP3_DOUT_PP2,          DEFAULT,     NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP3_SCLK_PP3,          RSVD3,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP4_FS_PP4,            RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP4_DIN_PP5,           RSVD3,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP4_DOUT_PP6,          RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP4_SCLK_PP7,          RSVD3,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_COL0_PQ0,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_COL1_PQ1,            RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_COL2_PQ2,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_COL3_PQ3,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_COL4_PQ4,            SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_COL5_PQ5,            RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_COL6_PQ6,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_COL7_PQ7,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_ROW0_PR0,            DEFAULT,     NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW1_PR1,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_ROW2_PR2,            RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW3_PR3,            KBC,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW4_PR4,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_ROW5_PR5,            RSVD3,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW6_PR6,            KBC,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW7_PR7,            DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_ROW8_PS0,            RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW9_PS1,            UARTA,       DOWN,   NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW10_PS2,           UARTA,       NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_ROW11_PS3,           DEFAULT,     NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW12_PS4,           DEFAULT,     NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW13_PS5,           RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW14_PS6,           RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW15_PS7,           DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(KB_ROW16_PT0,           RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(KB_ROW17_PT1,           DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(GEN2_I2C_SCL_PT5,       I2C2,        NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(GEN2_I2C_SDA_PT6,       I2C2,        NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(SDMMC4_CMD_PT7,         SDMMC4,      NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PU0,                    RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PU1,                    RSVD1,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PU2,                    RSVD1,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PU3,                    GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PU4,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PU5,                    DEFAULT,     UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PU6,                    DEFAULT,     UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PV0,                    DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PV1,                    RSVD1,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_CD_N_PV2,        SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC1_WP_N_PV3,        SDMMC1,      DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DDC_SCL_PV4,            I2C4,        NORMAL, NORMAL,   INPUT,   DEFAULT, NORMAL),
+       PINCFG(DDC_SDA_PV5,            I2C4,        NORMAL, NORMAL,   INPUT,   DEFAULT, NORMAL),
+       PINCFG(GPIO_W2_AUD_PW2,        RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(GPIO_W3_AUD_PW3,        DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(DAP_MCLK1_PW4,          EXTPERIPH1,  NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(CLK2_OUT_PW5,           RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(UART3_TXD_PW6,          RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(UART3_RXD_PW7,          RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DVFS_PWM_PX0,           CLDVFS,      NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(GPIO_X1_AUD_PX1,        DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(DVFS_CLK_PX2,           CLDVFS,      NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(GPIO_X3_AUD_PX3,        RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(GPIO_X4_AUD_PX4,        DEFAULT,     NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(GPIO_X5_AUD_PX5,        RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(GPIO_X6_AUD_PX6,        GMI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(GPIO_X7_AUD_PX7,        DEFAULT,     NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_CLK_PY0,           SPI1,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_DIR_PY1,           SPI1,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(ULPI_NXT_PY2,           SPI1,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(ULPI_STP_PY3,           SPI1,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SDMMC1_DAT3_PY4,        SDMMC1,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC1_DAT2_PY5,        SDMMC1,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC1_DAT1_PY6,        SDMMC1,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC1_DAT0_PY7,        SDMMC1,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC1_CLK_PZ0,         SDMMC1,      NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC1_CMD_PZ1,         SDMMC1,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PWR_I2C_SCL_PZ6,        I2CPWR,      NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(PWR_I2C_SDA_PZ7,        I2CPWR,      NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(SDMMC4_DAT0_PAA0,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_DAT1_PAA1,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_DAT2_PAA2,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_DAT3_PAA3,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_DAT4_PAA4,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_DAT5_PAA5,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_DAT6_PAA6,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_DAT7_PAA7,       SDMMC4,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PBB0,                   VGP6,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(CAM_I2C_SCL_PBB1,       RSVD3,       DOWN,   TRISTATE, OUTPUT,  DISABLE, DEFAULT),
+       PINCFG(CAM_I2C_SDA_PBB2,       RSVD3,       DOWN,   TRISTATE, OUTPUT,  DISABLE, DEFAULT),
+       PINCFG(PBB3,                   VGP3,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PBB4,                   VGP4,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PBB5,                   RSVD3,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PBB6,                   RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PBB7,                   RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(CAM_MCLK_PCC0,          VI,          DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PCC1,                   RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PCC2,                   RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SDMMC4_CLK_PCC4,        SDMMC4,      NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(CLK2_REQ_PCC5,          RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_L0_RST_N_PDD1,      RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_L0_CLKREQ_N_PDD2,   RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_WAKE_N_PDD3,        RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_L1_RST_N_PDD5,      RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_L1_CLKREQ_N_PDD6,   RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(CLK3_OUT_PEE0,          RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(CLK3_REQ_PEE1,          RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(DAP_MCLK1_REQ_PEE2,     RSVD4,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(HDMI_CEC_PEE3,          CEC,         NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+       PINCFG(SDMMC3_CLK_LB_OUT_PEE4, SDMMC3,      NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(SDMMC3_CLK_LB_IN_PEE5,  SDMMC3,      UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(DP_HPD_PFF0,            DP,          UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(USB_VBUS_EN2_PFF1,      RSVD2,       DOWN,   TRISTATE, OUTPUT,  DISABLE, DEFAULT),
+       PINCFG(PFF2,                   RSVD2,       DOWN,   TRISTATE, OUTPUT,  DISABLE, DEFAULT),
+       PINCFG(CORE_PWR_REQ,           PWRON,       NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(CPU_PWR_REQ,            CPU,         NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PWR_INT_N,              PMI,         NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(RESET_OUT_N,            RESET_OUT_N, NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(OWR,                    RSVD2,       DOWN,   TRISTATE, OUTPUT,  DEFAULT, NORMAL),
+       PINCFG(CLK_32K_IN,             CLK,         NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(JTAG_RTCK,              RTCK,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+};
+
+#define DRVCFG(_drvgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) \
+       {                                               \
+               .drvgrp = PMUX_DRVGRP_##_drvgrp,        \
+               .slwf   = _slwf,                        \
+               .slwr   = _slwr,                        \
+               .drvup  = _drvup,                       \
+               .drvdn  = _drvdn,                       \
+               .lpmd   = PMUX_LPMD_##_lpmd,            \
+               .schmt  = PMUX_SCHMT_##_schmt,          \
+               .hsm    = PMUX_HSM_##_hsm,              \
+       }
+
+static const struct pmux_drvgrp_config nyan_big_drvgrps[] = {
+};
+
+#endif /* PINMUX_CONFIG_NYAN_BIG_H */
index 06c366e0d0d85ea63564457d89c0a39de360cef2..992b11f64351b5ca0be24194d7853a9c87dc28e1 100644 (file)
@@ -18,7 +18,7 @@
 #define AS3722_LDO6VOLTAGE_REG 0x16    /* VDD_SDMMC */
 #define AS3722_LDCONTROL_REG   0x4E
 
-#ifdef CONFIG_TARGET_JETSON_TK1
+#if defined(CONFIG_TARGET_JETSON_TK1) || defined(CONFIG_TARGET_NYAN_BIG)
 #define AS3722_SD0VOLTAGE_DATA (0x3C00 | AS3722_SD0VOLTAGE_REG)
 #else
 #define AS3722_SD0VOLTAGE_DATA (0x2800 | AS3722_SD0VOLTAGE_REG)
index 3e9d3d9f10ae8edcca42708abc975ba8a978f2c5..3114b20be0245602db4c6e7a46d55107b1a0258a 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch/clock.h>
  */
 void pin_mux_mmc(void)
 {
+       struct udevice *dev;
        uchar val;
        int ret;
 
        /* Turn on MAX8907B LDO12 to 2.8V for J40 power */
-       ret = i2c_set_bus_num(0);
-       if (ret)
-               printf("i2c_set_bus_num failed: %d\n", ret);
+       ret = i2c_get_chip_for_busnum(0, 0x3c, &dev);
+       if (ret) {
+               printf("%s: Cannot find MAX8907B I2C chip\n", __func__);
+               return;
+       }
        val = 0x29;
-       ret = i2c_write(0x3c, 0x46, 1, &val, 1);
+       ret = i2c_write(dev, 0x46, &val, 1);
        if (ret)
                printf("i2c_write 0 0x3c 0x46 failed: %d\n", ret);
        val = 0x00;
-       ret = i2c_write(0x3c, 0x45, 1, &val, 1);
+       ret = i2c_write(dev, 0x45, &val, 1);
        if (ret)
                printf("i2c_write 0 0x3c 0x45 failed: %d\n", ret);
        val = 0x1f;
-       ret = i2c_write(0x3c, 0x44, 1, &val, 1);
+       ret = i2c_write(dev, 0x44, &val, 1);
        if (ret)
                printf("i2c_write 0 0x3c 0x44 failed: %d\n", ret);
 
@@ -49,6 +53,7 @@ void pin_mux_mmc(void)
 /* this is a weak define that we are overriding */
 void pin_mux_usb(void)
 {
+       struct udevice *dev;
        uchar val;
        int ret;
 
@@ -59,15 +64,17 @@ void pin_mux_usb(void)
         */
 
        /* Turn on TAC6416's GPIO 0+1 for USB1/3's VBUS */
-       ret = i2c_set_bus_num(0);
-       if (ret)
-               printf("i2c_set_bus_num failed: %d\n", ret);
+       ret = i2c_get_chip_for_busnum(0, 0x20, &dev);
+       if (ret) {
+               printf("%s: Cannot find TAC6416 I2C chip\n", __func__);
+               return;
+       }
        val = 0x03;
-       ret = i2c_write(0x20, 2, 1, &val, 1);
+       ret = i2c_write(dev, 2, &val, 1);
        if (ret)
                printf("i2c_write 0 0x20 2 failed: %d\n", ret);
        val = 0xfc;
-       ret = i2c_write(0x20, 6, 1, &val, 1);
+       ret = i2c_write(dev, 6, &val, 1);
        if (ret)
                printf("i2c_write 0 0x20 6 failed: %d\n", ret);
 }
index 51a4fa103061911c06596b81506d3bba3c1975cf..7dbd40ecf872bab2dacc12fb1931646fb64964eb 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/arch/mbox.h>
 #include <asm/arch/sdhci.h>
 #include <asm/global_data.h>
+#include <dm/platform_data/serial_pl01x.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -36,6 +37,17 @@ U_BOOT_DEVICE(bcm2835_gpios) = {
        .platdata = &gpio_platdata,
 };
 
+static const struct pl01x_serial_platdata serial_platdata = {
+       .base = 0x20201000,
+       .type = TYPE_PL011,
+       .clock = 3000000,
+};
+
+U_BOOT_DEVICE(bcm2835_serials) = {
+       .name = "serial_pl01x",
+       .platdata = &serial_platdata,
+};
+
 struct msg_get_arm_mem {
        struct bcm2835_mbox_hdr hdr;
        struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
index b9d694a2688a832db433033a7d1fa9b5ccaef6e6..5d2c024e890b9ffab6401517ce75bd33a759b70a 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include <common.h>
-
+#include <dm.h>
 #include <asm/arch/gp_padctrl.h>
 #include <asm/arch/pinmux.h>
 #include <asm/gpio.h>
@@ -38,23 +38,20 @@ void pinmux_init(void)
 #ifdef CONFIG_PCI_TEGRA
 int tegra_pcie_board_init(void)
 {
-       unsigned int old_bus;
+       struct udevice *dev;
        u8 addr, data[1];
        int err;
 
-       old_bus = i2c_get_bus_num();
-
-       err = i2c_set_bus_num(0);
+       err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
        if (err) {
-               debug("failed to set I2C bus\n");
+               debug("%s: Cannot find PMIC I2C chip\n", __func__);
                return err;
        }
-
        /* TPS659110: VDD2_OP_REG = 1.05V */
        data[0] = 0x27;
        addr = 0x25;
 
-       err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1);
+       err = i2c_write(dev, addr, data, 1);
        if (err) {
                debug("failed to set VDD supply\n");
                return err;
@@ -64,7 +61,7 @@ int tegra_pcie_board_init(void)
        data[0] = 0x0D;
        addr = 0x24;
 
-       err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1);
+       err = i2c_write(dev, addr, data, 1);
        if (err) {
                debug("failed to enable VDD supply\n");
                return err;
@@ -74,14 +71,12 @@ int tegra_pcie_board_init(void)
        data[0] = 0x0D;
        addr = 0x35;
 
-       err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1);
+       err = i2c_write(dev, addr, data, 1);
        if (err) {
                debug("failed to set AVDD supply\n");
                return err;
        }
 
-       i2c_set_bus_num(old_bus);
-
        return 0;
 }
 
index c266b88e5b272a1d4e728a362194b17c1993ea8b..22db1bb47c137fd4fe08fc20e3e2f75fba72f16f 100644 (file)
 #include <bootretry.h>
 #include <cli.h>
 #include <command.h>
+#include <dm.h>
 #include <edid.h>
 #include <environment.h>
+#include <errno.h>
 #include <i2c.h>
 #include <malloc.h>
 #include <asm/byteorder.h>
@@ -117,6 +119,60 @@ static uchar i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES;
 
 #define DISP_LINE_LEN  16
 
+/*
+ * Default for driver model is to use the chip's existing address length.
+ * For legacy code, this is not stored, so we need to use a suitable
+ * default.
+ */
+#ifdef CONFIG_DM_I2C
+#define DEFAULT_ADDR_LEN       (-1)
+#else
+#define DEFAULT_ADDR_LEN       1
+#endif
+
+#ifdef CONFIG_DM_I2C
+static struct udevice *i2c_cur_bus;
+
+static int i2c_set_bus_num(unsigned int busnum)
+{
+       struct udevice *bus;
+       int ret;
+
+       ret = uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus);
+       if (ret) {
+               debug("%s: No bus %d\n", __func__, busnum);
+               return ret;
+       }
+       i2c_cur_bus = bus;
+
+       return 0;
+}
+
+static int i2c_get_cur_bus(struct udevice **busp)
+{
+       if (!i2c_cur_bus) {
+               puts("No I2C bus selected\n");
+               return -ENODEV;
+       }
+       *busp = i2c_cur_bus;
+
+       return 0;
+}
+
+static int i2c_get_cur_bus_chip(uint chip_addr, struct udevice **devp)
+{
+       struct udevice *bus;
+       int ret;
+
+       ret = i2c_get_cur_bus(&bus);
+       if (ret)
+               return ret;
+
+       return i2c_get_chip(bus, chip_addr, devp);
+}
+
+#endif
+
 /**
  * i2c_init_board() - Board-specific I2C bus init
  *
@@ -143,7 +199,7 @@ void i2c_init_board(void)
  *
  * Returns I2C bus speed in Hz.
  */
-#if !defined(CONFIG_SYS_I2C)
+#if !defined(CONFIG_SYS_I2C) && !defined(CONFIG_DM_I2C)
 /*
  * TODO: Implement architecture-specific get/set functions
  * Should go away, if we switched completely to new multibus support
@@ -182,12 +238,12 @@ int i2c_set_bus_speed(unsigned int speed)
  *
  * Returns the address length.
  */
-static uint get_alen(char *arg)
+static uint get_alen(char *arg, int default_len)
 {
        int     j;
        int     alen;
 
-       alen = 1;
+       alen = default_len;
        for (j = 0; j < 8; j++) {
                if (arg[j] == '.') {
                        alen = arg[j+1] - '0';
@@ -227,8 +283,13 @@ static int i2c_report_err(int ret, enum i2c_err_op op)
 static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        u_char  chip;
-       uint    devaddr, alen, length;
+       uint    devaddr, length;
+       int alen;
        u_char  *memaddr;
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        if (argc != 5)
                return CMD_RET_USAGE;
@@ -243,7 +304,7 @@ static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
         * 2 bytes long.  Some day it might be 3 bytes long :-).
         */
        devaddr = simple_strtoul(argv[2], NULL, 16);
-       alen = get_alen(argv[2]);
+       alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
        if (alen > 3)
                return CMD_RET_USAGE;
 
@@ -257,18 +318,31 @@ static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
         */
        memaddr = (u_char *)simple_strtoul(argv[4], NULL, 16);
 
-       if (i2c_read(chip, devaddr, alen, memaddr, length) != 0) {
-               i2c_report_err(-1, I2C_ERR_READ);
-               return 1;
-       }
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret && alen != -1)
+               ret = i2c_set_chip_offset_len(dev, alen);
+       if (!ret)
+               ret = i2c_read(dev, devaddr, memaddr, length);
+#else
+       ret = i2c_read(chip, devaddr, alen, memaddr, length);
+#endif
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_READ);
+
        return 0;
 }
 
 static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        u_char  chip;
-       uint    devaddr, alen, length;
+       uint    devaddr, length;
+       int alen;
        u_char  *memaddr;
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        if (argc != 5)
                return cmd_usage(cmdtp);
@@ -288,7 +362,7 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
         * 2 bytes long.  Some day it might be 3 bytes long :-).
         */
        devaddr = simple_strtoul(argv[3], NULL, 16);
-       alen = get_alen(argv[3]);
+       alen = get_alen(argv[3], DEFAULT_ADDR_LEN);
        if (alen > 3)
                return cmd_usage(cmdtp);
 
@@ -297,10 +371,22 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
         */
        length = simple_strtoul(argv[4], NULL, 16);
 
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret && alen != -1)
+               ret = i2c_set_chip_offset_len(dev, alen);
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
+
        while (length-- > 0) {
-               if (i2c_write(chip, devaddr++, alen, memaddr++, 1) != 0) {
-                       return i2c_report_err(-1, I2C_ERR_WRITE);
-               }
+#ifdef CONFIG_DM_I2C
+               ret = i2c_write(dev, devaddr++, memaddr++, 1);
+#else
+               ret = i2c_write(chip, devaddr++, alen, memaddr++, 1);
+#endif
+               if (ret)
+                       return i2c_report_err(ret, I2C_ERR_WRITE);
 /*
  * No write delay with FRAM devices.
  */
@@ -311,6 +397,38 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
        return 0;
 }
 
+#ifdef CONFIG_DM_I2C
+static int do_i2c_flags(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       struct udevice *dev;
+       uint flags;
+       int chip;
+       int ret;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       chip = simple_strtoul(argv[1], NULL, 16);
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_READ);
+
+       if (argc > 2) {
+               flags = simple_strtoul(argv[2], NULL, 16);
+               ret = i2c_set_chip_flags(dev, flags);
+       } else  {
+               ret = i2c_get_chip_flags(dev, &flags);
+               if (!ret)
+                       printf("%x\n", flags);
+       }
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_READ);
+
+       return 0;
+}
+#endif
+
 /**
  * do_i2c_md() - Handle the "i2c md" command-line command
  * @cmdtp:     Command data struct pointer
@@ -327,8 +445,13 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
 static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        u_char  chip;
-       uint    addr, alen, length;
+       uint    addr, length;
+       int alen;
        int     j, nbytes, linebytes;
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        /* We use the last specified parameters, unless new ones are
         * entered.
@@ -356,7 +479,7 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
                 * 2 bytes long.  Some day it might be 3 bytes long :-).
                 */
                addr = simple_strtoul(argv[2], NULL, 16);
-               alen = get_alen(argv[2]);
+               alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
                if (alen > 3)
                        return CMD_RET_USAGE;
 
@@ -368,6 +491,14 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
                        length = simple_strtoul(argv[3], NULL, 16);
        }
 
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret && alen != -1)
+               ret = i2c_set_chip_offset_len(dev, alen);
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_READ);
+#endif
+
        /*
         * Print the lines.
         *
@@ -381,8 +512,13 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 
                linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
 
-               if (i2c_read(chip, addr, alen, linebuf, linebytes) != 0)
-                       i2c_report_err(-1, I2C_ERR_READ);
+#ifdef CONFIG_DM_I2C
+               ret = i2c_read(dev, addr, linebuf, linebytes);
+#else
+               ret = i2c_read(chip, addr, alen, linebuf, linebytes);
+#endif
+               if (ret)
+                       i2c_report_err(ret, I2C_ERR_READ);
                else {
                        printf("%04x:", addr);
                        cp = linebuf;
@@ -429,9 +565,13 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 {
        uchar   chip;
        ulong   addr;
-       uint    alen;
+       int     alen;
        uchar   byte;
        int     count;
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        if ((argc < 4) || (argc > 5))
                return CMD_RET_USAGE;
@@ -445,10 +585,17 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
         * Address is always specified.
         */
        addr = simple_strtoul(argv[2], NULL, 16);
-       alen = get_alen(argv[2]);
+       alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
        if (alen > 3)
                return CMD_RET_USAGE;
 
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret && alen != -1)
+               ret = i2c_set_chip_offset_len(dev, alen);
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
        /*
         * Value to write is always specified.
         */
@@ -463,8 +610,13 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
                count = 1;
 
        while (count-- > 0) {
-               if (i2c_write(chip, addr++, alen, &byte, 1) != 0)
-                       i2c_report_err(-1, I2C_ERR_WRITE);
+#ifdef CONFIG_DM_I2C
+               ret = i2c_write(dev, addr++, &byte, 1);
+#else
+               ret = i2c_write(chip, addr++, alen, &byte, 1);
+#endif
+               if (ret)
+                       i2c_report_err(ret, I2C_ERR_WRITE);
                /*
                 * Wait for the write to complete.  The write can take
                 * up to 10mSec (we allow a little more time).
@@ -499,11 +651,15 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 {
        uchar   chip;
        ulong   addr;
-       uint    alen;
+       int     alen;
        int     count;
        uchar   byte;
        ulong   crc;
        ulong   err;
+       int ret = 0;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        if (argc < 4)
                return CMD_RET_USAGE;
@@ -517,10 +673,17 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
         * Address is always specified.
         */
        addr = simple_strtoul(argv[2], NULL, 16);
-       alen = get_alen(argv[2]);
+       alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
        if (alen > 3)
                return CMD_RET_USAGE;
 
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret && alen != -1)
+               ret = i2c_set_chip_offset_len(dev, alen);
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_READ);
+#endif
        /*
         * Count is always specified
         */
@@ -534,13 +697,18 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
        crc = 0;
        err = 0;
        while (count-- > 0) {
-               if (i2c_read(chip, addr, alen, &byte, 1) != 0)
+#ifdef CONFIG_DM_I2C
+               ret = i2c_read(dev, addr, &byte, 1);
+#else
+               ret = i2c_read(chip, addr, alen, &byte, 1);
+#endif
+               if (ret)
                        err++;
                crc = crc32 (crc, &byte, 1);
                addr++;
        }
        if (err > 0)
-               i2c_report_err(-1, I2C_ERR_READ);
+               i2c_report_err(ret, I2C_ERR_READ);
        else
                printf ("%08lx\n", crc);
 
@@ -568,10 +736,14 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
 {
        uchar   chip;
        ulong   addr;
-       uint    alen;
+       int     alen;
        ulong   data;
        int     size = 1;
        int     nbytes;
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        if (argc != 3)
                return CMD_RET_USAGE;
@@ -601,19 +773,32 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
                 * Address is always specified.
                 */
                addr = simple_strtoul(argv[2], NULL, 16);
-               alen = get_alen(argv[2]);
+               alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
                if (alen > 3)
                        return CMD_RET_USAGE;
        }
 
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret && alen != -1)
+               ret = i2c_set_chip_offset_len(dev, alen);
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
+
        /*
         * Print the address, followed by value.  Then accept input for
         * the next value.  A non-converted value exits.
         */
        do {
                printf("%08lx:", addr);
-               if (i2c_read(chip, addr, alen, (uchar *)&data, size) != 0)
-                       i2c_report_err(-1, I2C_ERR_READ);
+#ifdef CONFIG_DM_I2C
+               ret = i2c_read(dev, addr, (uchar *)&data, size);
+#else
+               ret = i2c_read(chip, addr, alen, (uchar *)&data, size);
+#endif
+               if (ret)
+                       i2c_report_err(ret, I2C_ERR_READ);
                else {
                        data = cpu_to_be32(data);
                        if (size == 1)
@@ -655,8 +840,15 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
                                 * good enough to not time out
                                 */
                                bootretry_reset_cmd_timeout();
-                               if (i2c_write(chip, addr, alen, (uchar *)&data, size) != 0)
-                                       i2c_report_err(-1, I2C_ERR_WRITE);
+#ifdef CONFIG_DM_I2C
+                               ret = i2c_write(dev, addr, (uchar *)&data,
+                                               size);
+#else
+                               ret = i2c_write(chip, addr, alen,
+                                               (uchar *)&data, size);
+#endif
+                               if (ret)
+                                       i2c_report_err(ret, I2C_ERR_WRITE);
 #ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
                                udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 #endif
@@ -697,6 +889,13 @@ static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
        int k, skip;
        unsigned int bus = GET_BUS_NUM;
 #endif /* NOPROBES */
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *bus, *dev;
+
+       if (i2c_get_cur_bus(&bus))
+               return CMD_RET_FAILURE;
+#endif
 
        if (argc == 2)
                addr = simple_strtol(argv[1], 0, 16);
@@ -717,7 +916,12 @@ static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
                if (skip)
                        continue;
 #endif
-               if (i2c_probe(j) == 0) {
+#ifdef CONFIG_DM_I2C
+               ret = i2c_probe(bus, j, 0, &dev);
+#else
+               ret = i2c_probe(j);
+#endif
+               if (ret == 0) {
                        printf(" %02X", j);
                        found++;
                }
@@ -754,11 +958,15 @@ static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
 static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        u_char  chip;
-       ulong   alen;
+       int alen;
        uint    addr;
        uint    length;
        u_char  bytes[16];
        int     delay;
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        if (argc < 3)
                return CMD_RET_USAGE;
@@ -772,9 +980,16 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
         * Address is always specified.
         */
        addr = simple_strtoul(argv[2], NULL, 16);
-       alen = get_alen(argv[2]);
+       alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
        if (alen > 3)
                return CMD_RET_USAGE;
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret && alen != -1)
+               ret = i2c_set_chip_offset_len(dev, alen);
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
 
        /*
         * Length is the number of objects, not number of bytes.
@@ -794,8 +1009,13 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
         * Run the loop...
         */
        while (1) {
-               if (i2c_read(chip, addr, alen, bytes, length) != 0)
-                       i2c_report_err(-1, I2C_ERR_READ);
+#ifdef CONFIG_DM_I2C
+               ret = i2c_read(dev, addr, bytes, length);
+#else
+               ret = i2c_read(chip, addr, alen, bytes, length);
+#endif
+               if (ret)
+                       i2c_report_err(ret, I2C_ERR_READ);
                udelay(delay);
        }
 
@@ -1345,6 +1565,10 @@ int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
        u_char chip;
        struct edid1_info edid;
+       int ret;
+#ifdef CONFIG_DM_I2C
+       struct udevice *dev;
+#endif
 
        if (argc < 2) {
                cmd_usage(cmdtp);
@@ -1352,10 +1576,15 @@ int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        }
 
        chip = simple_strtoul(argv[1], NULL, 16);
-       if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
-               i2c_report_err(-1, I2C_ERR_READ);
-               return 1;
-       }
+#ifdef CONFIG_DM_I2C
+       ret = i2c_get_cur_bus_chip(chip, &dev);
+       if (!ret)
+               ret = i2c_read(dev, 0, (uchar *)&edid, sizeof(edid));
+#else
+       ret = i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid));
+#endif
+       if (ret)
+               return i2c_report_err(ret, I2C_ERR_READ);
 
        if (edid_check_info(&edid)) {
                puts("Content isn't valid EDID.\n");
@@ -1437,17 +1666,28 @@ static int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc,
  * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
  * on error.
  */
-#if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS)
+#if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS) || \
+               defined(CONFIG_DM_I2C)
 static int do_i2c_bus_num(cmd_tbl_t *cmdtp, int flag, int argc,
                                char * const argv[])
 {
        int             ret = 0;
-       unsigned int    bus_no;
+       int     bus_no;
 
-       if (argc == 1)
+       if (argc == 1) {
                /* querying current setting */
-               printf("Current bus is %d\n", i2c_get_bus_num());
-       else {
+#ifdef CONFIG_DM_I2C
+               struct udevice *bus;
+
+               if (!i2c_get_cur_bus(&bus))
+                       bus_no = bus->seq;
+               else
+                       bus_no = -1;
+#else
+               bus_no = i2c_get_bus_num();
+#endif
+               printf("Current bus is %d\n", bus_no);
+       } else {
                bus_no = simple_strtoul(argv[1], NULL, 10);
 #if defined(CONFIG_SYS_I2C)
                if (bus_no >= CONFIG_SYS_NUM_I2C_BUSES) {
@@ -1478,13 +1718,28 @@ static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const
 {
        int speed, ret=0;
 
-       if (argc == 1)
+#ifdef CONFIG_DM_I2C
+       struct udevice *bus;
+
+       if (i2c_get_cur_bus(&bus))
+               return 1;
+#endif
+       if (argc == 1) {
+#ifdef CONFIG_DM_I2C
+               speed = i2c_get_bus_speed(bus);
+#else
+               speed = i2c_get_bus_speed();
+#endif
                /* querying current speed */
-               printf("Current bus speed=%d\n", i2c_get_bus_speed());
-       else {
+               printf("Current bus speed=%d\n", speed);
+       else {
                speed = simple_strtoul(argv[1], NULL, 10);
                printf("Setting bus speed to %d Hz\n", speed);
+#ifdef CONFIG_DM_I2C
+               ret = i2c_set_bus_speed(bus, speed);
+#else
                ret = i2c_set_bus_speed(speed);
+#endif
                if (ret)
                        printf("Failure changing bus speed (%d)\n", ret);
        }
@@ -1532,7 +1787,16 @@ static int do_i2c_nm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
  */
 static int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
-#if defined(CONFIG_SYS_I2C)
+#if defined(CONFIG_DM_I2C)
+       struct udevice *bus;
+
+       if (i2c_get_cur_bus(&bus))
+               return CMD_RET_FAILURE;
+       if (i2c_deblock(bus)) {
+               printf("Error: Not supported by the driver\n");
+               return CMD_RET_FAILURE;
+       }
+#elif defined(CONFIG_SYS_I2C)
        i2c_init(I2C_ADAP->speed, I2C_ADAP->slaveaddr);
 #else
        i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
@@ -1546,7 +1810,7 @@ static cmd_tbl_t cmd_i2c_sub[] = {
 #endif
        U_BOOT_CMD_MKENT(crc32, 3, 1, do_i2c_crc, "", ""),
 #if defined(CONFIG_SYS_I2C) || \
-       defined(CONFIG_I2C_MULTI_BUS)
+       defined(CONFIG_I2C_MULTI_BUS) || defined(CONFIG_DM_I2C)
        U_BOOT_CMD_MKENT(dev, 1, 1, do_i2c_bus_num, "", ""),
 #endif  /* CONFIG_I2C_MULTI_BUS */
 #if defined(CONFIG_I2C_EDID)
@@ -1560,6 +1824,9 @@ static cmd_tbl_t cmd_i2c_sub[] = {
        U_BOOT_CMD_MKENT(probe, 0, 1, do_i2c_probe, "", ""),
        U_BOOT_CMD_MKENT(read, 5, 1, do_i2c_read, "", ""),
        U_BOOT_CMD_MKENT(write, 5, 0, do_i2c_write, "", ""),
+#ifdef CONFIG_DM_I2C
+       U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""),
+#endif
        U_BOOT_CMD_MKENT(reset, 0, 1, do_i2c_reset, "", ""),
 #if defined(CONFIG_CMD_SDRAM)
        U_BOOT_CMD_MKENT(sdram, 1, 1, do_sdram, "", ""),
@@ -1610,7 +1877,7 @@ static char i2c_help_text[] =
 #endif
        "crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n"
 #if defined(CONFIG_SYS_I2C) || \
-       defined(CONFIG_I2C_MULTI_BUS)
+       defined(CONFIG_I2C_MULTI_BUS) || defined(CONFIG_DM_I2C)
        "i2c dev [dev] - show or set current I2C bus\n"
 #endif  /* CONFIG_I2C_MULTI_BUS */
 #if defined(CONFIG_I2C_EDID)
@@ -1622,8 +1889,11 @@ static char i2c_help_text[] =
        "i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)\n"
        "i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)\n"
        "i2c probe [address] - test for and show device(s) on the I2C bus\n"
-       "i2c read chip address[.0, .1, .2] length memaddress - read to memory \n"
+       "i2c read chip address[.0, .1, .2] length memaddress - read to memory\n"
        "i2c write memaddress chip address[.0, .1, .2] length - write memory to i2c\n"
+#ifdef CONFIG_DM_I2C
+       "i2c flags chip [flags] - set or get chip flags\n"
+#endif
        "i2c reset - re-init the I2C Controller\n"
 #if defined(CONFIG_CMD_SDRAM)
        "i2c sdram chip - print SDRAM configuration information\n"
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig
new file mode 100644 (file)
index 0000000..ec79b5b
--- /dev/null
@@ -0,0 +1,5 @@
++S:CONFIG_ARM=y
++S:CONFIG_TEGRA=y
++S:CONFIG_TEGRA124=y
++S:CONFIG_TARGET_NYAN_BIG=y
+CONFIG_DEFAULT_DEVICE_TREE="tegra124-nyan-big"
index 6793e1c4f944b9db600687669a222728f19feafd..963b16f26f0dc015a7f676891e0d845b42ec6594 100644 (file)
@@ -234,7 +234,7 @@ int device_probe(struct udevice *dev)
 void *dev_get_platdata(struct udevice *dev)
 {
        if (!dev) {
-               dm_warn("%s: null device", __func__);
+               dm_warn("%s: null device\n", __func__);
                return NULL;
        }
 
@@ -244,7 +244,7 @@ void *dev_get_platdata(struct udevice *dev)
 void *dev_get_priv(struct udevice *dev)
 {
        if (!dev) {
-               dm_warn("%s: null device", __func__);
+               dm_warn("%s: null device\n", __func__);
                return NULL;
        }
 
@@ -254,7 +254,7 @@ void *dev_get_priv(struct udevice *dev)
 void *dev_get_parentdata(struct udevice *dev)
 {
        if (!dev) {
-               dm_warn("%s: null device", __func__);
+               dm_warn("%s: null device\n", __func__);
                return NULL;
        }
 
index dae3d71d2bbcc7aee289f640e9978d684518846a..6f3c86c03859171f940305801f564ff0c2b9e1cd 100644 (file)
@@ -4,6 +4,7 @@
 #
 # SPDX-License-Identifier:     GPL-2.0+
 #
+obj-$(CONFIG_DM_I2C) += i2c-uclass.o
 
 obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o
 obj-$(CONFIG_I2C_MV) += mv_i2c.o
@@ -26,6 +27,7 @@ obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o
 obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o
 obj-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o
 obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o
+obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
 obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
 obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
 obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c
new file mode 100644 (file)
index 0000000..aa89f95
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+
+UCLASS_DRIVER(i2c_emul) = {
+       .id             = UCLASS_I2C_EMUL,
+       .name           = "i2c_emul",
+};
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
new file mode 100644 (file)
index 0000000..005bf86
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <malloc.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define I2C_MAX_OFFSET_LEN     4
+
+/**
+ * i2c_setup_offset() - Set up a new message with a chip offset
+ *
+ * @chip:      Chip to use
+ * @offset:    Byte offset within chip
+ * @offset_buf:        Place to put byte offset
+ * @msg:       Message buffer
+ * @return 0 if OK, -EADDRNOTAVAIL if the offset length is 0. In that case the
+ * message is still set up but will not contain an offset.
+ */
+static int i2c_setup_offset(struct dm_i2c_chip *chip, uint offset,
+                           uint8_t offset_buf[], struct i2c_msg *msg)
+{
+       int offset_len;
+
+       msg->addr = chip->chip_addr;
+       msg->flags = chip->flags & DM_I2C_CHIP_10BIT ? I2C_M_TEN : 0;
+       msg->len = chip->offset_len;
+       msg->buf = offset_buf;
+       if (!chip->offset_len)
+               return -EADDRNOTAVAIL;
+       assert(chip->offset_len <= I2C_MAX_OFFSET_LEN);
+       offset_len = chip->offset_len;
+       while (offset_len--)
+               *offset_buf++ = offset >> (8 * offset_len);
+
+       return 0;
+}
+
+static int i2c_read_bytewise(struct udevice *dev, uint offset,
+                            uint8_t *buffer, int len)
+{
+       struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+       struct udevice *bus = dev_get_parent(dev);
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       struct i2c_msg msg[2], *ptr;
+       uint8_t offset_buf[I2C_MAX_OFFSET_LEN];
+       int ret;
+       int i;
+
+       for (i = 0; i < len; i++) {
+               if (i2c_setup_offset(chip, offset + i, offset_buf, msg))
+                       return -EINVAL;
+               ptr = msg + 1;
+               ptr->addr = chip->chip_addr;
+               ptr->flags = msg->flags | I2C_M_RD;
+               ptr->len = 1;
+               ptr->buf = &buffer[i];
+               ptr++;
+
+               ret = ops->xfer(bus, msg, ptr - msg);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int i2c_write_bytewise(struct udevice *dev, uint offset,
+                            const uint8_t *buffer, int len)
+{
+       struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+       struct udevice *bus = dev_get_parent(dev);
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       struct i2c_msg msg[1];
+       uint8_t buf[I2C_MAX_OFFSET_LEN + 1];
+       int ret;
+       int i;
+
+       for (i = 0; i < len; i++) {
+               if (i2c_setup_offset(chip, offset + i, buf, msg))
+                       return -EINVAL;
+               buf[msg->len++] = buffer[i];
+
+               ret = ops->xfer(bus, msg, 1);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
+{
+       struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+       struct udevice *bus = dev_get_parent(dev);
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       struct i2c_msg msg[2], *ptr;
+       uint8_t offset_buf[I2C_MAX_OFFSET_LEN];
+       int msg_count;
+
+       if (!ops->xfer)
+               return -ENOSYS;
+       if (chip->flags & DM_I2C_CHIP_RD_ADDRESS)
+               return i2c_read_bytewise(dev, offset, buffer, len);
+       ptr = msg;
+       if (!i2c_setup_offset(chip, offset, offset_buf, ptr))
+               ptr++;
+
+       if (len) {
+               ptr->addr = chip->chip_addr;
+               ptr->flags = chip->flags & DM_I2C_CHIP_10BIT ? I2C_M_TEN : 0;
+               ptr->flags |= I2C_M_RD;
+               ptr->len = len;
+               ptr->buf = buffer;
+               ptr++;
+       }
+       msg_count = ptr - msg;
+
+       return ops->xfer(bus, msg, msg_count);
+}
+
+int i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer, int len)
+{
+       struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+       struct udevice *bus = dev_get_parent(dev);
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       struct i2c_msg msg[1];
+
+       if (!ops->xfer)
+               return -ENOSYS;
+
+       if (chip->flags & DM_I2C_CHIP_WR_ADDRESS)
+               return i2c_write_bytewise(dev, offset, buffer, len);
+       /*
+        * The simple approach would be to send two messages here: one to
+        * set the offset and one to write the bytes. However some drivers
+        * will not be expecting this, and some chips won't like how the
+        * driver presents this on the I2C bus.
+        *
+        * The API does not support separate offset and data. We could extend
+        * it with a flag indicating that there is data in the next message
+        * that needs to be processed in the same transaction. We could
+        * instead add an additional buffer to each message. For now, handle
+        * this in the uclass since it isn't clear what the impact on drivers
+        * would be with this extra complication. Unfortunately this means
+        * copying the message.
+        *
+        * Use the stack for small messages, malloc() for larger ones. We
+        * need to allow space for the offset (up to 4 bytes) and the message
+        * itself.
+        */
+       if (len < 64) {
+               uint8_t buf[I2C_MAX_OFFSET_LEN + len];
+
+               i2c_setup_offset(chip, offset, buf, msg);
+               msg->len += len;
+               memcpy(buf + chip->offset_len, buffer, len);
+
+               return ops->xfer(bus, msg, 1);
+       } else {
+               uint8_t *buf;
+               int ret;
+
+               buf = malloc(I2C_MAX_OFFSET_LEN + len);
+               if (!buf)
+                       return -ENOMEM;
+               i2c_setup_offset(chip, offset, buf, msg);
+               msg->len += len;
+               memcpy(buf + chip->offset_len, buffer, len);
+
+               ret = ops->xfer(bus, msg, 1);
+               free(buf);
+               return ret;
+       }
+}
+
+/**
+ * i2c_probe_chip() - probe for a chip on a bus
+ *
+ * @bus:       Bus to probe
+ * @chip_addr: Chip address to probe
+ * @flags:     Flags for the chip
+ * @return 0 if found, -ENOSYS if the driver is invalid, -EREMOTEIO if the chip
+ * does not respond to probe
+ */
+static int i2c_probe_chip(struct udevice *bus, uint chip_addr,
+                         enum dm_i2c_chip_flags chip_flags)
+{
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       struct i2c_msg msg[1];
+       int ret;
+
+       if (ops->probe_chip) {
+               ret = ops->probe_chip(bus, chip_addr, chip_flags);
+               if (!ret || ret != -ENOSYS)
+                       return ret;
+       }
+
+       if (!ops->xfer)
+               return -ENOSYS;
+
+       /* Probe with a zero-length message */
+       msg->addr = chip_addr;
+       msg->flags = chip_flags & DM_I2C_CHIP_10BIT ? I2C_M_TEN : 0;
+       msg->len = 0;
+       msg->buf = NULL;
+
+       return ops->xfer(bus, msg, 1);
+}
+
+static int i2c_bind_driver(struct udevice *bus, uint chip_addr,
+                          struct udevice **devp)
+{
+       struct dm_i2c_chip chip;
+       char name[30], *str;
+       struct udevice *dev;
+       int ret;
+
+       snprintf(name, sizeof(name), "generic_%x", chip_addr);
+       str = strdup(name);
+       ret = device_bind_driver(bus, "i2c_generic_chip_drv", str, &dev);
+       debug("%s:  device_bind_driver: ret=%d\n", __func__, ret);
+       if (ret)
+               goto err_bind;
+
+       /* Tell the device what we know about it */
+       memset(&chip, '\0', sizeof(chip));
+       chip.chip_addr = chip_addr;
+       chip.offset_len = 1;    /* we assume */
+       ret = device_probe_child(dev, &chip);
+       debug("%s:  device_probe_child: ret=%d\n", __func__, ret);
+       if (ret)
+               goto err_probe;
+
+       *devp = dev;
+       return 0;
+
+err_probe:
+       device_unbind(dev);
+err_bind:
+       free(str);
+       return ret;
+}
+
+int i2c_get_chip(struct udevice *bus, uint chip_addr, struct udevice **devp)
+{
+       struct udevice *dev;
+
+       debug("%s: Searching bus '%s' for address %02x: ", __func__,
+             bus->name, chip_addr);
+       for (device_find_first_child(bus, &dev); dev;
+                       device_find_next_child(&dev)) {
+               struct dm_i2c_chip store;
+               struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+               int ret;
+
+               if (!chip) {
+                       chip = &store;
+                       i2c_chip_ofdata_to_platdata(gd->fdt_blob,
+                                                   dev->of_offset, chip);
+               }
+               if (chip->chip_addr == chip_addr) {
+                       ret = device_probe(dev);
+                       debug("found, ret=%d\n", ret);
+                       if (ret)
+                               return ret;
+                       *devp = dev;
+                       return 0;
+               }
+       }
+       debug("not found\n");
+       return i2c_bind_driver(bus, chip_addr, devp);
+}
+
+int i2c_get_chip_for_busnum(int busnum, int chip_addr, struct udevice **devp)
+{
+       struct udevice *bus;
+       int ret;
+
+       ret = uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus);
+       if (ret) {
+               debug("Cannot find I2C bus %d\n", busnum);
+               return ret;
+       }
+       ret = i2c_get_chip(bus, chip_addr, devp);
+       if (ret) {
+               debug("Cannot find I2C chip %02x on bus %d\n", chip_addr,
+                     busnum);
+               return ret;
+       }
+
+       return 0;
+}
+
+int i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
+             struct udevice **devp)
+{
+       int ret;
+
+       *devp = NULL;
+
+       /* First probe that chip */
+       ret = i2c_probe_chip(bus, chip_addr, chip_flags);
+       debug("%s: bus='%s', address %02x, ret=%d\n", __func__, bus->name,
+             chip_addr, ret);
+       if (ret)
+               return ret;
+
+       /* The chip was found, see if we have a driver, and probe it */
+       ret = i2c_get_chip(bus, chip_addr, devp);
+       debug("%s:  i2c_get_chip: ret=%d\n", __func__, ret);
+
+       return ret;
+}
+
+int i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       struct dm_i2c_bus *i2c = bus->uclass_priv;
+       int ret;
+
+       /*
+        * If we have a method, call it. If not then the driver probably wants
+        * to deal with speed changes on the next transfer. It can easily read
+        * the current speed from this uclass
+        */
+       if (ops->set_bus_speed) {
+               ret = ops->set_bus_speed(bus, speed);
+               if (ret)
+                       return ret;
+       }
+       i2c->speed_hz = speed;
+
+       return 0;
+}
+
+/*
+ * i2c_get_bus_speed:
+ *
+ *  Returns speed of selected I2C bus in Hz
+ */
+int i2c_get_bus_speed(struct udevice *bus)
+{
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       struct dm_i2c_bus *i2c = bus->uclass_priv;
+
+       if (!ops->get_bus_speed)
+               return i2c->speed_hz;
+
+       return ops->get_bus_speed(bus);
+}
+
+int i2c_set_chip_flags(struct udevice *dev, uint flags)
+{
+       struct udevice *bus = dev->parent;
+       struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+       int ret;
+
+       if (ops->set_flags) {
+               ret = ops->set_flags(dev, flags);
+               if (ret)
+                       return ret;
+       }
+       chip->flags = flags;
+
+       return 0;
+}
+
+int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
+{
+       struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+
+       *flagsp = chip->flags;
+
+       return 0;
+}
+
+int i2c_set_chip_offset_len(struct udevice *dev, uint offset_len)
+{
+       struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+
+       if (offset_len > I2C_MAX_OFFSET_LEN)
+               return -EINVAL;
+       chip->offset_len = offset_len;
+
+       return 0;
+}
+
+int i2c_deblock(struct udevice *bus)
+{
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+
+       /*
+        * We could implement a software deblocking here if we could get
+        * access to the GPIOs used by I2C, and switch them to GPIO mode
+        * and then back to I2C. This is somewhat beyond our powers in
+        * driver model at present, so for now just fail.
+        *
+        * See https://patchwork.ozlabs.org/patch/399040/
+        */
+       if (!ops->deblock)
+               return -ENOSYS;
+
+       return ops->deblock(bus);
+}
+
+int i2c_chip_ofdata_to_platdata(const void *blob, int node,
+                               struct dm_i2c_chip *chip)
+{
+       chip->offset_len = 1;   /* default */
+       chip->flags = 0;
+       chip->chip_addr = fdtdec_get_int(gd->fdt_blob, node, "reg", -1);
+       if (chip->chip_addr == -1) {
+               debug("%s: I2C Node '%s' has no 'reg' property\n", __func__,
+                     fdt_get_name(blob, node, NULL));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int i2c_post_probe(struct udevice *dev)
+{
+       struct dm_i2c_bus *i2c = dev->uclass_priv;
+
+       i2c->speed_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                    "clock-frequency", 100000);
+
+       return i2c_set_bus_speed(dev, i2c->speed_hz);
+}
+
+int i2c_post_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+UCLASS_DRIVER(i2c) = {
+       .id             = UCLASS_I2C,
+       .name           = "i2c",
+       .per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
+       .post_bind      = i2c_post_bind,
+       .post_probe     = i2c_post_probe,
+};
+
+UCLASS_DRIVER(i2c_generic) = {
+       .id             = UCLASS_I2C_GENERIC,
+       .name           = "i2c_generic",
+};
+
+U_BOOT_DRIVER(i2c_generic_chip_drv) = {
+       .name           = "i2c_generic_chip_drv",
+       .id             = UCLASS_I2C_GENERIC,
+};
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
new file mode 100644 (file)
index 0000000..f0e9f51
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Simulate an I2C port
+ *
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <asm/test.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct dm_sandbox_i2c_emul_priv {
+       struct udevice *emul;
+};
+
+static int get_emul(struct udevice *dev, struct udevice **devp,
+                   struct dm_i2c_ops **opsp)
+{
+       struct dm_i2c_chip *priv;
+       int ret;
+
+       *devp = NULL;
+       *opsp = NULL;
+       priv = dev_get_parentdata(dev);
+       if (!priv->emul) {
+               ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
+                                      false);
+               if (ret)
+                       return ret;
+
+               ret = device_get_child(dev, 0, &priv->emul);
+               if (ret)
+                       return ret;
+       }
+       *devp = priv->emul;
+       *opsp = i2c_get_ops(priv->emul);
+
+       return 0;
+}
+
+static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+                           int nmsgs)
+{
+       struct dm_i2c_bus *i2c = bus->uclass_priv;
+       struct dm_i2c_ops *ops;
+       struct udevice *emul, *dev;
+       bool is_read;
+       int ret;
+
+       /* Special test code to return success but with no emulation */
+       if (msg->addr == SANDBOX_I2C_TEST_ADDR)
+               return 0;
+
+       ret = i2c_get_chip(bus, msg->addr, &dev);
+       if (ret)
+               return ret;
+
+       ret = get_emul(dev, &emul, &ops);
+       if (ret)
+               return ret;
+
+       /*
+        * For testing, don't allow writing above 100KHz for writes and
+        * 400KHz for reads
+        */
+       is_read = nmsgs > 1;
+       if (i2c->speed_hz > (is_read ? 400000 : 100000))
+               return -EINVAL;
+       return ops->xfer(emul, msg, nmsgs);
+}
+
+static const struct dm_i2c_ops sandbox_i2c_ops = {
+       .xfer           = sandbox_i2c_xfer,
+};
+
+static int sandbox_i2c_child_pre_probe(struct udevice *dev)
+{
+       struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
+
+       /* Ignore our test address */
+       if (i2c_chip->chip_addr == SANDBOX_I2C_TEST_ADDR)
+               return 0;
+       if (dev->of_offset == -1)
+               return 0;
+
+       return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
+                                          i2c_chip);
+}
+
+static const struct udevice_id sandbox_i2c_ids[] = {
+       { .compatible = "sandbox,i2c" },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_sandbox) = {
+       .name   = "i2c_sandbox",
+       .id     = UCLASS_I2C,
+       .of_match = sandbox_i2c_ids,
+       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .child_pre_probe = sandbox_i2c_child_pre_probe,
+       .ops    = &sandbox_i2c_ops,
+};
index 562211e7deb6504b65a0a3a088ea7572e5cc93b0..87290c3127612c3369f8e98c383118f0e3229563 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <fdtdec.h>
 #include <i2c.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+enum i2c_type {
+       TYPE_114,
+       TYPE_STD,
+       TYPE_DVC,
+};
+
 /* Information about i2c controller */
 struct i2c_bus {
        int                     id;
@@ -27,20 +35,17 @@ struct i2c_bus {
        int                     pinmux_config;
        struct i2c_control      *control;
        struct i2c_ctlr         *regs;
-       int                     is_dvc; /* DVC type, rather than I2C */
-       int                     is_scs; /* single clock source (T114+) */
+       enum i2c_type           type;
        int                     inited; /* bus is inited */
 };
 
-static struct i2c_bus i2c_controllers[TEGRA_I2C_NUM_CONTROLLERS];
-
 static void set_packet_mode(struct i2c_bus *i2c_bus)
 {
        u32 config;
 
        config = I2C_CNFG_NEW_MASTER_FSM_MASK | I2C_CNFG_PACKET_MODE_MASK;
 
-       if (i2c_bus->is_dvc) {
+       if (i2c_bus->type == TYPE_DVC) {
                struct dvc_ctlr *dvc = (struct dvc_ctlr *)i2c_bus->regs;
 
                writel(config, &dvc->cnfg);
@@ -65,6 +70,9 @@ static void i2c_reset_controller(struct i2c_bus *i2c_bus)
 
 static void i2c_init_controller(struct i2c_bus *i2c_bus)
 {
+       if (!i2c_bus->speed)
+               return;
+       debug("%s: speed=%d\n", __func__, i2c_bus->speed);
        /*
         * Use PLLP - DP-04508-001_v06 datasheet indicates a divisor of 8
         * here, in section 23.3.1, but in fact we seem to need a factor of
@@ -73,7 +81,7 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
        clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
                i2c_bus->speed * 2 * 8);
 
-       if (i2c_bus->is_scs) {
+       if (i2c_bus->type == TYPE_114) {
                /*
                 * T114 I2C went to a single clock source for standard/fast and
                 * HS clock speeds. The new clock rate setting calculation is:
@@ -98,7 +106,7 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
        i2c_reset_controller(i2c_bus);
 
        /* Configure I2C controller. */
-       if (i2c_bus->is_dvc) {  /* only for DVC I2C */
+       if (i2c_bus->type == TYPE_DVC) {        /* only for DVC I2C */
                struct dvc_ctlr *dvc = (struct dvc_ctlr *)i2c_bus->regs;
 
                setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK);
@@ -272,7 +280,7 @@ exit:
        return error;
 }
 
-static int tegra_i2c_write_data(struct i2c_bus *bus, u32 addr, u8 *data,
+static int tegra_i2c_write_data(struct i2c_bus *i2c_bus, u32 addr, u8 *data,
                                u32 len, bool end_with_repeated_start)
 {
        int error;
@@ -286,14 +294,14 @@ static int tegra_i2c_write_data(struct i2c_bus *bus, u32 addr, u8 *data,
        trans_info.num_bytes = len;
        trans_info.is_10bit_address = 0;
 
-       error = send_recv_packets(bus, &trans_info);
+       error = send_recv_packets(i2c_bus, &trans_info);
        if (error)
                debug("tegra_i2c_write_data: Error (%d) !!!\n", error);
 
        return error;
 }
 
-static int tegra_i2c_read_data(struct i2c_bus *bus, u32 addr, u8 *data,
+static int tegra_i2c_read_data(struct i2c_bus *i2c_bus, u32 addr, u8 *data,
                               u32 len)
 {
        int error;
@@ -305,52 +313,32 @@ static int tegra_i2c_read_data(struct i2c_bus *bus, u32 addr, u8 *data,
        trans_info.num_bytes = len;
        trans_info.is_10bit_address = 0;
 
-       error = send_recv_packets(bus, &trans_info);
+       error = send_recv_packets(i2c_bus, &trans_info);
        if (error)
                debug("tegra_i2c_read_data: Error (%d) !!!\n", error);
 
        return error;
 }
 
-#ifndef CONFIG_OF_CONTROL
-#error "Please enable device tree support to use this driver"
-#endif
-
-/**
- * Check that a bus number is valid and return a pointer to it
- *
- * @param bus_num      Bus number to check / return
- * @return pointer to bus, if valid, else NULL
- */
-static struct i2c_bus *tegra_i2c_get_bus(struct i2c_adapter *adap)
+static int tegra_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
 {
-       struct i2c_bus *bus;
+       struct i2c_bus *i2c_bus = dev_get_priv(dev);
 
-       bus = &i2c_controllers[adap->hwadapnr];
-       if (!bus->inited) {
-               debug("%s: Bus %u not available\n", __func__, adap->hwadapnr);
-               return NULL;
-       }
-
-       return bus;
-}
-
-static unsigned int tegra_i2c_set_bus_speed(struct i2c_adapter *adap,
-                       unsigned int speed)
-{
-       struct i2c_bus *bus;
-
-       bus = tegra_i2c_get_bus(adap);
-       if (!bus)
-               return 0;
-       bus->speed = speed;
-       i2c_init_controller(bus);
+       i2c_bus->speed = speed;
+       i2c_init_controller(i2c_bus);
 
        return 0;
 }
 
-static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus)
+static int tegra_i2c_probe(struct udevice *dev)
 {
+       struct i2c_bus *i2c_bus = dev_get_priv(dev);
+       const void *blob = gd->fdt_blob;
+       int node = dev->of_offset;
+       bool is_dvc;
+
+       i2c_bus->id = dev->seq;
+       i2c_bus->type = dev_get_of_data(dev);
        i2c_bus->regs = (struct i2c_ctlr *)fdtdec_get_addr(blob, node, "reg");
 
        /*
@@ -358,7 +346,6 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus)
         * far no one needs anything other than the default.
         */
        i2c_bus->pinmux_config = FUNCMUX_DEFAULT;
-       i2c_bus->speed = fdtdec_get_int(blob, node, "clock-frequency", 0);
        i2c_bus->periph_id = clock_decode_periph_id(blob, node);
 
        /*
@@ -371,107 +358,25 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus)
         *              i2c_bus->pinmux_config = FUNCMUX_I2C2_PTA;
         */
        if (i2c_bus->periph_id == -1)
-               return -FDT_ERR_NOTFOUND;
+               return -EINVAL;
 
-       return 0;
-}
-
-/*
- * Process a list of nodes, adding them to our list of I2C ports.
- *
- * @param blob         fdt blob
- * @param node_list    list of nodes to process (any <=0 are ignored)
- * @param count                number of nodes to process
- * @param is_dvc       1 if these are DVC ports, 0 if standard I2C
- * @param is_scs       1 if this HW uses a single clock source (T114+)
- * @return 0 if ok, -1 on error
- */
-static int process_nodes(const void *blob, int node_list[], int count,
-                        int is_dvc, int is_scs)
-{
-       struct i2c_bus *i2c_bus;
-       int i;
-
-       /* build the i2c_controllers[] for each controller */
-       for (i = 0; i < count; i++) {
-               int node = node_list[i];
-
-               if (node <= 0)
-                       continue;
-
-               i2c_bus = &i2c_controllers[i];
-               i2c_bus->id = i;
-
-               if (i2c_get_config(blob, node, i2c_bus)) {
-                       printf("i2c_init_board: failed to decode bus %d\n", i);
-                       return -1;
-               }
-
-               i2c_bus->is_scs = is_scs;
-
-               i2c_bus->is_dvc = is_dvc;
-               if (is_dvc) {
-                       i2c_bus->control =
-                               &((struct dvc_ctlr *)i2c_bus->regs)->control;
-               } else {
-                       i2c_bus->control = &i2c_bus->regs->control;
-               }
-               debug("%s: controller bus %d at %p, periph_id %d, speed %d: ",
-                     is_dvc ? "dvc" : "i2c", i, i2c_bus->regs,
-                     i2c_bus->periph_id, i2c_bus->speed);
-               i2c_init_controller(i2c_bus);
-               debug("ok\n");
-               i2c_bus->inited = 1;
-
-               /* Mark position as used */
-               node_list[i] = -1;
+       is_dvc = dev_get_of_data(dev) == TYPE_DVC;
+       if (is_dvc) {
+               i2c_bus->control =
+                       &((struct dvc_ctlr *)i2c_bus->regs)->control;
+       } else {
+               i2c_bus->control = &i2c_bus->regs->control;
        }
+       i2c_init_controller(i2c_bus);
+       debug("%s: controller bus %d at %p, periph_id %d, speed %d: ",
+             is_dvc ? "dvc" : "i2c", dev->seq, i2c_bus->regs,
+             i2c_bus->periph_id, i2c_bus->speed);
 
        return 0;
 }
 
-/* Sadly there is no error return from this function */
-void i2c_init_board(void)
-{
-       int node_list[TEGRA_I2C_NUM_CONTROLLERS];
-       const void *blob = gd->fdt_blob;
-       int count;
-
-       /* First check for newer (T114+) I2C ports */
-       count = fdtdec_find_aliases_for_id(blob, "i2c",
-                       COMPAT_NVIDIA_TEGRA114_I2C, node_list,
-                       TEGRA_I2C_NUM_CONTROLLERS);
-       if (process_nodes(blob, node_list, count, 0, 1))
-               return;
-
-       /* Now get the older (T20/T30) normal I2C ports */
-       count = fdtdec_find_aliases_for_id(blob, "i2c",
-                       COMPAT_NVIDIA_TEGRA20_I2C, node_list,
-                       TEGRA_I2C_NUM_CONTROLLERS);
-       if (process_nodes(blob, node_list, count, 0, 0))
-               return;
-
-       /* Now look for dvc ports */
-       count = fdtdec_add_aliases_for_id(blob, "i2c",
-                       COMPAT_NVIDIA_TEGRA20_DVC, node_list,
-                       TEGRA_I2C_NUM_CONTROLLERS);
-       if (process_nodes(blob, node_list, count, 1, 0))
-               return;
-}
-
-static void tegra_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
-{
-       /* No i2c support prior to relocation */
-       if (!(gd->flags & GD_FLG_RELOC))
-               return;
-
-       /* This will override the speed selected in the fdt for that port */
-       debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
-       i2c_set_bus_speed(speed);
-}
-
 /* i2c write version without the register address */
-static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
+static int i2c_write_data(struct i2c_bus *i2c_bus, uchar chip, uchar *buffer,
                          int len, bool end_with_repeated_start)
 {
        int rc;
@@ -484,7 +389,7 @@ static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
        debug("\n");
 
        /* Shift 7-bit address over for lower-level i2c functions */
-       rc = tegra_i2c_write_data(bus, chip << 1, buffer, len,
+       rc = tegra_i2c_write_data(i2c_bus, chip << 1, buffer, len,
                                  end_with_repeated_start);
        if (rc)
                debug("i2c_write_data(): rc=%d\n", rc);
@@ -493,14 +398,14 @@ static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
 }
 
 /* i2c read version without the register address */
-static int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
-                               int len)
+static int i2c_read_data(struct i2c_bus *i2c_bus, uchar chip, uchar *buffer,
+                        int len)
 {
        int rc;
 
        debug("inside i2c_read_data():\n");
        /* Shift 7-bit address over for lower-level i2c functions */
-       rc = tegra_i2c_read_data(bus, chip << 1, buffer, len);
+       rc = tegra_i2c_read_data(i2c_bus, chip << 1, buffer, len);
        if (rc) {
                debug("i2c_read_data(): rc=%d\n", rc);
                return rc;
@@ -516,132 +421,99 @@ static int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
 }
 
 /* Probe to see if a chip is present. */
-static int tegra_i2c_probe(struct i2c_adapter *adap, uchar chip)
+static int tegra_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+                               uint chip_flags)
 {
-       struct i2c_bus *bus;
+       struct i2c_bus *i2c_bus = dev_get_priv(bus);
        int rc;
-       uchar reg;
-
-       debug("i2c_probe: addr=0x%x\n", chip);
-       bus = tegra_i2c_get_bus(adap);
-       if (!bus)
-               return 1;
-       reg = 0;
-       rc = i2c_write_data(bus, chip, &reg, 1, false);
-       if (rc) {
-               debug("Error probing 0x%x.\n", chip);
-               return 1;
-       }
-       return 0;
-}
+       u8 reg;
 
-static int i2c_addr_ok(const uint addr, const int alen)
-{
-       /* We support 7 or 10 bit addresses, so one or two bytes each */
-       return alen == 1 || alen == 2;
+       /* Shift 7-bit address over for lower-level i2c functions */
+       rc = tegra_i2c_write_data(i2c_bus, chip_addr << 1, &reg, sizeof(reg),
+                                 false);
+
+       return rc;
 }
 
-/* Read bytes */
-static int tegra_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
-                       int alen, uchar *buffer, int len)
+static int tegra_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+                         int nmsgs)
 {
-       struct i2c_bus *bus;
-       uint offset;
-       int i;
-
-       debug("i2c_read: chip=0x%x, addr=0x%x, alen=0x%x len=0x%x\n",
-             chip, addr, alen, len);
-       bus = tegra_i2c_get_bus(adap);
-       if (!bus)
-               return 1;
-       if (!i2c_addr_ok(addr, alen)) {
-               debug("i2c_read: Bad address %x.%d.\n", addr, alen);
-               return 1;
-       }
-       for (offset = 0; offset < len; offset++) {
-               if (alen) {
-                       uchar data[alen];
-                       for (i = 0; i < alen; i++) {
-                               data[alen - i - 1] =
-                                       (addr + offset) >> (8 * i);
-                       }
-                       if (i2c_write_data(bus, chip, data, alen, true)) {
-                               debug("i2c_read: error sending (0x%x)\n",
-                                       addr);
-                               return 1;
-                       }
+       struct i2c_bus *i2c_bus = dev_get_priv(bus);
+       int ret;
+
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
+
+               debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
+               if (msg->flags & I2C_M_RD) {
+                       ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                           msg->len);
+               } else {
+                       ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                            msg->len, next_is_read);
                }
-               if (i2c_read_data(bus, chip, buffer + offset, 1)) {
-                       debug("i2c_read: error reading (0x%x)\n", addr);
-                       return 1;
+               if (ret) {
+                       debug("i2c_write: error sending\n");
+                       return -EREMOTEIO;
                }
        }
 
        return 0;
 }
 
-/* Write bytes */
-static int tegra_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
-                       int alen, uchar *buffer, int len)
+int tegra_i2c_get_dvc_bus(struct udevice **busp)
 {
-       struct i2c_bus *bus;
-       uint offset;
-       int i;
-
-       debug("i2c_write: chip=0x%x, addr=0x%x, alen=0x%x len=0x%x\n",
-             chip, addr, alen, len);
-       bus = tegra_i2c_get_bus(adap);
-       if (!bus)
-               return 1;
-       if (!i2c_addr_ok(addr, alen)) {
-               debug("i2c_write: Bad address %x.%d.\n", addr, alen);
-               return 1;
-       }
-       for (offset = 0; offset < len; offset++) {
-               uchar data[alen + 1];
-               for (i = 0; i < alen; i++)
-                       data[alen - i - 1] = (addr + offset) >> (8 * i);
-               data[alen] = buffer[offset];
-               if (i2c_write_data(bus, chip, data, alen + 1, false)) {
-                       debug("i2c_write: error sending (0x%x)\n", addr);
-                       return 1;
+       struct udevice *bus;
+
+       for (uclass_first_device(UCLASS_I2C, &bus);
+            bus;
+            uclass_next_device(&bus)) {
+               if (dev_get_of_data(bus) == TYPE_DVC) {
+                       *busp = bus;
+                       return 0;
                }
        }
 
-       return 0;
+       return -ENODEV;
 }
 
-int tegra_i2c_get_dvc_bus_num(void)
-{
-       int i;
+static const struct dm_i2c_ops tegra_i2c_ops = {
+       .xfer           = tegra_i2c_xfer,
+       .probe_chip     = tegra_i2c_probe_chip,
+       .set_bus_speed  = tegra_i2c_set_bus_speed,
+};
 
-       for (i = 0; i < TEGRA_I2C_NUM_CONTROLLERS; i++) {
-               struct i2c_bus *bus = &i2c_controllers[i];
+static int tegra_i2c_child_pre_probe(struct udevice *dev)
+{
+       struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
 
-               if (bus->inited && bus->is_dvc)
-                       return i;
-       }
+       if (dev->of_offset == -1)
+               return 0;
+       return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
+                                          i2c_chip);
+}
 
-       return -1;
+static int tegra_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+       return 0;
 }
 
-/*
- * Register soft i2c adapters
- */
-U_BOOT_I2C_ADAP_COMPLETE(tegra0, tegra_i2c_init, tegra_i2c_probe,
-                        tegra_i2c_read, tegra_i2c_write,
-                        tegra_i2c_set_bus_speed, 100000, 0, 0)
-U_BOOT_I2C_ADAP_COMPLETE(tegra1, tegra_i2c_init, tegra_i2c_probe,
-                        tegra_i2c_read, tegra_i2c_write,
-                        tegra_i2c_set_bus_speed, 100000, 0, 1)
-U_BOOT_I2C_ADAP_COMPLETE(tegra2, tegra_i2c_init, tegra_i2c_probe,
-                        tegra_i2c_read, tegra_i2c_write,
-                        tegra_i2c_set_bus_speed, 100000, 0, 2)
-U_BOOT_I2C_ADAP_COMPLETE(tegra3, tegra_i2c_init, tegra_i2c_probe,
-                        tegra_i2c_read, tegra_i2c_write,
-                        tegra_i2c_set_bus_speed, 100000, 0, 3)
-#if TEGRA_I2C_NUM_CONTROLLERS > 4
-U_BOOT_I2C_ADAP_COMPLETE(tegra4, tegra_i2c_init, tegra_i2c_probe,
-                        tegra_i2c_read, tegra_i2c_write,
-                        tegra_i2c_set_bus_speed, 100000, 0, 4)
-#endif
+static const struct udevice_id tegra_i2c_ids[] = {
+       { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+       { .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD },
+       { .compatible = "nvidia,tegra20-i2c-dvc", .data = TYPE_DVC },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_tegra) = {
+       .name   = "i2c_tegra",
+       .id     = UCLASS_I2C,
+       .of_match = tegra_i2c_ids,
+       .ofdata_to_platdata = tegra_i2c_ofdata_to_platdata,
+       .probe  = tegra_i2c_probe,
+       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .child_pre_probe = tegra_i2c_child_pre_probe,
+       .priv_auto_alloc_size = sizeof(struct i2c_bus),
+       .ops    = &tegra_i2c_ops,
+};
index 2f2e48f9790484b9be39a83138f502dd7ebf9877..6fa836f2063c257fb1e267170c7043138f9dbad3 100644 (file)
@@ -15,11 +15,15 @@ obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o
 obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
 obj-$(CONFIG_FSL_IIM) += fsl_iim.o
 obj-$(CONFIG_GPIO_LED) += gpio_led.o
+obj-$(CONFIG_I2C_EEPROM) += i2c_eeprom.o
 obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
 obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
 obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
 obj-$(CONFIG_NS87308) += ns87308.o
 obj-$(CONFIG_PDSP188x) += pdsp188x.o
+ifdef CONFIG_DM_I2C
+obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
+endif
 obj-$(CONFIG_STATUS_LED) += status_led.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c
new file mode 100644 (file)
index 0000000..d0548ec
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <i2c_eeprom.h>
+
+static int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf,
+                          int size)
+{
+       return -ENODEV;
+}
+
+static int i2c_eeprom_write(struct udevice *dev, int offset,
+                           const uint8_t *buf, int size)
+{
+       return -ENODEV;
+}
+
+struct i2c_eeprom_ops i2c_eeprom_std_ops = {
+       .read   = i2c_eeprom_read,
+       .write  = i2c_eeprom_write,
+};
+
+int i2c_eeprom_std_probe(struct udevice *dev)
+{
+       return 0;
+}
+
+static const struct udevice_id i2c_eeprom_std_ids[] = {
+       { .compatible = "i2c-eeprom" },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_eeprom_std) = {
+       .name           = "i2c_eeprom",
+       .id             = UCLASS_I2C_EEPROM,
+       .of_match       = i2c_eeprom_std_ids,
+       .probe          = i2c_eeprom_std_probe,
+       .priv_auto_alloc_size = sizeof(struct i2c_eeprom),
+       .ops            = &i2c_eeprom_std_ops,
+};
+
+UCLASS_DRIVER(i2c_eeprom) = {
+       .id             = UCLASS_I2C_EEPROM,
+       .name           = "i2c_eeprom",
+};
diff --git a/drivers/misc/i2c_eeprom_emul.c b/drivers/misc/i2c_eeprom_emul.c
new file mode 100644 (file)
index 0000000..7343445
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Simulate an I2C eeprom
+ *
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <malloc.h>
+#include <asm/test.h>
+
+#ifdef DEBUG
+#define debug_buffer print_buffer
+#else
+#define debug_buffer(x, ...)
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct sandbox_i2c_flash_plat_data {
+       enum sandbox_i2c_eeprom_test_mode test_mode;
+       const char *filename;
+       int offset_len;         /* Length of an offset in bytes */
+       int size;               /* Size of data buffer */
+};
+
+struct sandbox_i2c_flash {
+       uint8_t *data;
+};
+
+void sandbox_i2c_eeprom_set_test_mode(struct udevice *dev,
+                                     enum sandbox_i2c_eeprom_test_mode mode)
+{
+       struct sandbox_i2c_flash_plat_data *plat = dev_get_platdata(dev);
+
+       plat->test_mode = mode;
+}
+
+void sandbox_i2c_eeprom_set_offset_len(struct udevice *dev, int offset_len)
+{
+       struct sandbox_i2c_flash_plat_data *plat = dev_get_platdata(dev);
+
+       plat->offset_len = offset_len;
+}
+
+static int sandbox_i2c_eeprom_xfer(struct udevice *emul, struct i2c_msg *msg,
+                                 int nmsgs)
+{
+       struct sandbox_i2c_flash *priv = dev_get_priv(emul);
+       uint offset = 0;
+
+       debug("\n%s\n", __func__);
+       debug_buffer(0, priv->data, 1, 16, 0);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               struct sandbox_i2c_flash_plat_data *plat =
+                               dev_get_platdata(emul);
+               int len;
+               u8 *ptr;
+
+               if (!plat->size)
+                       return -ENODEV;
+               if (msg->addr + msg->len > plat->size) {
+                       debug("%s: Address %x, len %x is outside range 0..%x\n",
+                             __func__, msg->addr, msg->len, plat->size);
+                       return -EINVAL;
+               }
+               len = msg->len;
+               debug("   %s: msg->len=%d",
+                     msg->flags & I2C_M_RD ? "read" : "write",
+                     msg->len);
+               if (msg->flags & I2C_M_RD) {
+                       if (plat->test_mode == SIE_TEST_MODE_SINGLE_BYTE)
+                               len = 1;
+                       debug(", offset %x, len %x: ", offset, len);
+                       memcpy(msg->buf, priv->data + offset, len);
+                       memset(msg->buf + len, '\xff', msg->len - len);
+                       debug_buffer(0, msg->buf, 1, msg->len, 0);
+               } else if (len >= plat->offset_len) {
+                       int i;
+
+                       ptr = msg->buf;
+                       for (i = 0; i < plat->offset_len; i++, len--)
+                               offset = (offset << 8) | *ptr++;
+                       debug(", set offset %x: ", offset);
+                       debug_buffer(0, msg->buf, 1, msg->len, 0);
+                       if (plat->test_mode == SIE_TEST_MODE_SINGLE_BYTE)
+                               len = min(len, 1);
+
+                       /* For testing, map offsets into our limited buffer */
+                       for (i = 24; i > 0; i -= 8) {
+                               if (offset > (1 << i)) {
+                                       offset = (offset >> i) |
+                                               (offset & ((1 << i) - 1));
+                                       offset += i;
+                               }
+                       }
+                       memcpy(priv->data + offset, ptr, len);
+               }
+       }
+       debug_buffer(0, priv->data, 1, 16, 0);
+
+       return 0;
+}
+
+struct dm_i2c_ops sandbox_i2c_emul_ops = {
+       .xfer = sandbox_i2c_eeprom_xfer,
+};
+
+static int sandbox_i2c_eeprom_ofdata_to_platdata(struct udevice *dev)
+{
+       struct sandbox_i2c_flash_plat_data *plat = dev_get_platdata(dev);
+
+       plat->size = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                   "sandbox,size", 32);
+       plat->filename = fdt_getprop(gd->fdt_blob, dev->of_offset,
+                                    "sandbox,filename", NULL);
+       if (!plat->filename) {
+               debug("%s: No filename for device '%s'\n", __func__,
+                     dev->name);
+               return -EINVAL;
+       }
+       plat->test_mode = SIE_TEST_MODE_NONE;
+       plat->offset_len = 1;
+
+       return 0;
+}
+
+static int sandbox_i2c_eeprom_probe(struct udevice *dev)
+{
+       struct sandbox_i2c_flash_plat_data *plat = dev_get_platdata(dev);
+       struct sandbox_i2c_flash *priv = dev_get_priv(dev);
+
+       priv->data = calloc(1, plat->size);
+       if (!priv->data)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int sandbox_i2c_eeprom_remove(struct udevice *dev)
+{
+       struct sandbox_i2c_flash *priv = dev_get_priv(dev);
+
+       free(priv->data);
+
+       return 0;
+}
+
+static const struct udevice_id sandbox_i2c_ids[] = {
+       { .compatible = "sandbox,i2c-eeprom" },
+       { }
+};
+
+U_BOOT_DRIVER(sandbox_i2c_emul) = {
+       .name           = "sandbox_i2c_eeprom_emul",
+       .id             = UCLASS_I2C_EMUL,
+       .of_match       = sandbox_i2c_ids,
+       .ofdata_to_platdata = sandbox_i2c_eeprom_ofdata_to_platdata,
+       .probe          = sandbox_i2c_eeprom_probe,
+       .remove         = sandbox_i2c_eeprom_remove,
+       .priv_auto_alloc_size = sizeof(struct sandbox_i2c_flash),
+       .platdata_auto_alloc_size = sizeof(struct sandbox_i2c_flash_plat_data),
+       .ops            = &sandbox_i2c_emul_ops,
+};
index d29d969533d53cfd4841ac2195508e21392f7b42..29bab4cc00dc7683121fc3302d65c660b9190a3f 100644 (file)
@@ -10,9 +10,7 @@
 #include <asm/io.h>
 #include <i2c.h>
 
-static int bus_num;            /* I2C bus we are on */
-#define I2C_ADDRESS            0x34    /* chip requires this address */
-static char inited;            /* 1 if we have been inited */
+static struct udevice *tps6586x_dev;
 
 enum {
        /* Registers that we access */
@@ -37,13 +35,9 @@ static int tps6586x_read(int reg)
        int     i;
        uchar   data;
        int     retval = -1;
-       int     old_bus_num;
-
-       old_bus_num = i2c_get_bus_num();
-       i2c_set_bus_num(bus_num);
 
        for (i = 0; i < MAX_I2C_RETRY; ++i) {
-               if (!i2c_read(I2C_ADDRESS, reg, 1, &data, 1)) {
+               if (!i2c_read(tps6586x_dev, reg,  &data, 1)) {
                        retval = (int)data;
                        goto exit;
                }
@@ -53,7 +47,6 @@ static int tps6586x_read(int reg)
        }
 
 exit:
-       i2c_set_bus_num(old_bus_num);
        debug("pmu_read %x=%x\n", reg, retval);
        if (retval < 0)
                debug("%s: failed to read register %#x: %d\n", __func__, reg,
@@ -65,13 +58,9 @@ static int tps6586x_write(int reg, uchar *data, uint len)
 {
        int     i;
        int     retval = -1;
-       int     old_bus_num;
-
-       old_bus_num = i2c_get_bus_num();
-       i2c_set_bus_num(bus_num);
 
        for (i = 0; i < MAX_I2C_RETRY; ++i) {
-               if (!i2c_write(I2C_ADDRESS, reg, 1, data, len)) {
+               if (!i2c_write(tps6586x_dev, reg, data, len)) {
                        retval = 0;
                        goto exit;
                }
@@ -81,7 +70,6 @@ static int tps6586x_write(int reg, uchar *data, uint len)
        }
 
 exit:
-       i2c_set_bus_num(old_bus_num);
        debug("pmu_write %x=%x: ", reg, retval);
        for (i = 0; i < len; i++)
                debug("%x ", data[i]);
@@ -163,7 +151,7 @@ int tps6586x_set_pwm_mode(int mask)
        uchar val;
        int ret;
 
-       assert(inited);
+       assert(tps6586x_dev);
        ret = tps6586x_read(PFM_MODE);
        if (ret != -1) {
                val = (uchar)ret;
@@ -184,7 +172,7 @@ int tps6586x_adjust_sm0_sm1(int sm0_target, int sm1_target, int step, int rate,
        int sm0, sm1;
        int bad;
 
-       assert(inited);
+       assert(tps6586x_dev);
 
        /* get current voltage settings */
        if (read_voltages(&sm0, &sm1)) {
@@ -255,10 +243,9 @@ int tps6586x_adjust_sm0_sm1(int sm0_target, int sm1_target, int step, int rate,
        return bad ? -1 : 0;
 }
 
-int tps6586x_init(int bus)
+int tps6586x_init(struct udevice *dev)
 {
-       bus_num = bus;
-       inited = 1;
+       tps6586x_dev = dev;
 
        return 0;
 }
index e1bf4965f92123ce0605cbc93d02f0a1d56da1f2..75eb6bd729e1614033f1bd110fb602358cfb5e46 100644 (file)
@@ -348,6 +348,7 @@ U_BOOT_DRIVER(serial_pl01x) = {
        .probe = pl01x_serial_probe,
        .ops    = &pl01x_serial_ops,
        .flags = DM_FLAG_PRE_RELOC,
+       .priv_auto_alloc_size = sizeof(struct pl01x_priv),
 };
 
 #endif
index d0dd29ffb25d9493efd0dc1a3eb96248c0a66f5e..ba442d5ed529bb04a88a41e630477b4a46b32d46 100644 (file)
@@ -852,30 +852,6 @@ DEFINE_CACHE_ALIGN_BUFFER(u8, control_req, USB_BUFSIZ);
 DEFINE_CACHE_ALIGN_BUFFER(u8, status_req, STATUS_BYTECOUNT);
 #endif
 
-
-/**
- * strlcpy - Copy a %NUL terminated string into a sized buffer
- * @dest: Where to copy the string to
- * @src: Where to copy the string from
- * @size: size of destination buffer
- *
- * Compatible with *BSD: the result is always a valid
- * NUL-terminated string that fits in the buffer (unless,
- * of course, the buffer size is zero). It does not pad
- * out the result like strncpy() does.
- */
-size_t strlcpy(char *dest, const char *src, size_t size)
-{
-       size_t ret = strlen(src);
-
-       if (size) {
-               size_t len = (ret >= size) ? size - 1 : ret;
-               memcpy(dest, src, len);
-               dest[len] = '\0';
-       }
-       return ret;
-}
-
 /*============================================================================*/
 
 /*
index 508db5626bbeb9fa533ce2ee0ee3731e664659d5..ddfe0450d21c780e44cacf4f26b91d1e15a059a9 100644 (file)
 #undef CONFIG_IMAGE_FORMAT_LEGACY
 #endif
 
+#ifdef CONFIG_DM_I2C
+# ifdef CONFIG_SYS_I2C
+#  error "Cannot define CONFIG_SYS_I2C when CONFIG_DM_I2C is used"
+# endif
+#endif
+
 #endif /* __CONFIG_FALLBACKS_H */
index 3cde923b5f952d42623ea45fd4e9ee75e2f6748c..61809fcdbea79f0b75fc7b3c0ca1aa3d8f9eca9c 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index 164b2dd9518ecd3b8f8aaad30be083ac3740bc18..5d765f3d36fa10ada3d5c86151e0dfe7de7f9e5e 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index 09129c77673a9b98dfe47d63fde1307279fd8afa..758b7ad392dc9f7f13e68f12e0ffe7c11fb5b01f 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_SYS_MAX_I2C_BUS         TEGRA_I2C_NUM_CONTROLLERS
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index a582e255169c8188cdcd3aac8416b530191bf2c3..ce6f23b8c4f12ee73e2164357b3f2c7fdab17bd6 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index ff7ec4a93bb79b0b9de7229b6f864dc314828c23..0b04ee67b36acbba63b0c3b64095da78acf8c1d7 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_SYS_MAX_I2C_BUS         TEGRA_I2C_NUM_CONTROLLERS
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index d67c025b9c61cd75c254ab6fd7cba867da7ae3e6..a7d76650ce6e0d26098eefb50a8187d332947678 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_SYS_MAX_I2C_BUS         TEGRA_I2C_NUM_CONTROLLERS
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
diff --git a/include/configs/nyan-big.h b/include/configs/nyan-big.h
new file mode 100644 (file)
index 0000000..cf331ab
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2014
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <linux/sizes.h>
+
+#include "tegra124-common.h"
+
+/* High-level configuration options */
+#define V_PROMPT                       "Tegra124 (Nyan-big) # "
+#define CONFIG_TEGRA_BOARD_STRING      "Google/NVIDIA Nyan-big"
+
+/* Board-specific serial config */
+#define CONFIG_SERIAL_MULTI
+#define CONFIG_TEGRA_ENABLE_UARTA
+#define CONFIG_SYS_NS16550_COM1                NV_PA_APB_UARTA_BASE
+
+#define CONFIG_BOARD_EARLY_INIT_F
+
+/* I2C */
+#define CONFIG_SYS_I2C_TEGRA
+#define CONFIG_CMD_I2C
+
+/* SD/MMC */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_TEGRA_MMC
+#define CONFIG_CMD_MMC
+
+/* Environment in eMMC, at the end of 2nd "boot sector" */
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV         0
+#define CONFIG_SYS_MMC_ENV_PART                2
+#define CONFIG_ENV_OFFSET              (-CONFIG_ENV_SIZE)
+
+/* SPI */
+#define CONFIG_TEGRA114_SPI            /* Compatible w/ Tegra114 SPI */
+#define CONFIG_TEGRA114_SPI_CTRLS      6
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
+#define CONFIG_SF_DEFAULT_SPEED        24000000
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_SF
+#define CONFIG_SPI_FLASH_SIZE          (4 << 20)
+
+/* USB Host support */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_TEGRA
+#define CONFIG_USB_MAX_CONTROLLER_COUNT        2
+#define CONFIG_USB_STORAGE
+#define CONFIG_CMD_USB
+
+/* USB networking support */
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+
+/* General networking support */
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_DHCP
+
+#define CONFIG_FIT
+#define CONFIG_OF_LIBFDT
+
+#include "tegra-common-usb-gadget.h"
+#include "tegra-common-post.h"
+
+#endif /* __CONFIG_H */
index 4d5426e501dd043d6762c8cd5fdbc15a2267229d..c94f4112026e890f1e668356dda86fc7d9b15dfd 100644 (file)
@@ -34,6 +34,7 @@
 #define CONFIG_DM
 #define CONFIG_CMD_DM
 #define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
 
 /* Memory layout */
 #define CONFIG_NR_DRAM_BANKS           1
@@ -51,6 +52,7 @@
                                         CONFIG_SYS_SDRAM_SIZE - \
                                         GENERATED_GBL_DATA_SIZE)
 #define CONFIG_SYS_MALLOC_LEN          SZ_4M
+#define CONFIG_SYS_MALLOC_F_LEN                (1 << 10)
 #define CONFIG_SYS_MEMTEST_START       0x00100000
 #define CONFIG_SYS_MEMTEST_END         0x00200000
 #define CONFIG_LOADADDR                        0x00200000
@@ -92,9 +94,7 @@
 #endif
 
 /* Console UART */
-#define CONFIG_PL011_SERIAL
-#define CONFIG_PL011_CLOCK             3000000
-#define CONFIG_PL01x_PORTS             { (void *)0x20201000 }
+#define CONFIG_PL01X_SERIAL
 #define CONFIG_CONS_INDEX              0
 #define CONFIG_BAUDRATE                        115200
 
index 2b03841d9d5ae3cc7bf5a801879976d94640b86d..657f751f3c21bb9c4de81c996695a7371fd3427d 100644 (file)
 #define CONFIG_SPI_FLASH_STMICRO
 #define CONFIG_SPI_FLASH_WINBOND
 
+#define CONFIG_DM_I2C
+#define CONFIG_CMD_I2C
+#define CONFIG_SYS_I2C_SANDBOX
+#define CONFIG_I2C_EDID
+#define CONFIG_I2C_EEPROM
+
 /* Memory things - we don't really want a memory test */
 #define CONFIG_SYS_LOAD_ADDR           0x00000000
 #define CONFIG_SYS_MEMTEST_START       0x00100000
index 04e4f82759fb780150958033fc3eadd2bc19026c..5f77051d13f889c117f5cf4d180548eeb2c95eaa 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index 51f87dacdbedf826119c24d8a8435223a7938021..e37b23359b544147f9798d46823c5c5b8b3c2b37 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_SYS_MAX_I2C_BUS         TEGRA_I2C_NUM_CONTROLLERS
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index d690045eb046bb7d20cf9e10da1a1bab3cefe435..06853285a25d70648d6b9f989d1706987773158b 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 #define CONFIG_DM_SPI
 #define CONFIG_DM_SPI_FLASH
+#define CONFIG_DM_I2C
 
 #define CONFIG_SYS_TIMER_RATE          1000000
 #define CONFIG_SYS_TIMER_COUNTER       NV_PA_TMRUS_BASE
index 555c237cbf1c56bd29ed4283b5cb8391a841ba7b..9eba5d517db7b3f926ee25d7cffc85ae9c87ff93 100644 (file)
@@ -76,9 +76,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START    0x80090000
 #define CONFIG_SPL_STACK               0x800ffffc
 
-/* Total I2C ports on Tegra114 */
-#define TEGRA_I2C_NUM_CONTROLLERS      5
-
 /* For USB EHCI controller */
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_USB_EHCI_TXFIFO_THRESH  0x10
index 61e50265740dfd2d6d8f662c787865d531353121..f2b3774da8ff5c90394735faab4db308a9b34a1b 100644 (file)
@@ -68,9 +68,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START    0x80090000
 #define CONFIG_SPL_STACK               0x800ffffc
 
-/* Total I2C ports on Tegra124 */
-#define TEGRA_I2C_NUM_CONTROLLERS      5
-
 /* For USB EHCI controller */
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_USB_EHCI_TXFIFO_THRESH  0x10
index 21bf9771742424dcf4da509e8550a2964b585b0a..6330281df71b6db51f9c04962915bb3ba42c44b9 100644 (file)
@@ -97,9 +97,6 @@
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1
 
-/* Total I2C ports on Tegra20 */
-#define TEGRA_I2C_NUM_CONTROLLERS      4
-
 #define CONFIG_SYS_NAND_SELF_INIT
 #define CONFIG_SYS_NAND_ONFI_DETECTION
 
index 443c842240ede89b0e7cba4fd51b278877e95886..bfdbeb70d296691c2f3c087eca4e74f40aa4a04a 100644 (file)
@@ -73,9 +73,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START    0x80090000
 #define CONFIG_SPL_STACK               0x800ffffc
 
-/* Total I2C ports on Tegra30 */
-#define TEGRA_I2C_NUM_CONTROLLERS      5
-
 /* For USB EHCI controller */
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_USB_EHCI_TXFIFO_THRESH  0x10
index 7c0064267dabec1f53beaa14c12fd0d4998b5d32..a254f864097f7c2dffd8118c4cdc78183c1750ae 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index 6897aa8aa3d81bfe780ffdbf1999ccad2b1c1e97..8880de86c42d7c6eb128e68cd7a0a2a74930ef7b 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_SYS_MAX_I2C_BUS         TEGRA_I2C_NUM_CONTROLLERS
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index 10e70d28b1ae3823330e8e7d2a3ff87984b33ba2..e083cbd07f17753fbf734902e03b2607944667d0 100644 (file)
 
 /* I2C */
 #define CONFIG_SYS_I2C_TEGRA
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_SYS_I2C_SPEED           100000
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 
 /* SD/MMC */
 #define CONFIG_MMC
index 202f59b505d34848a250afff2ebc4b4c4f25c840..f17c3c2b384dfc8aa782583fa0734cb31a77d222 100644 (file)
@@ -19,6 +19,7 @@ enum uclass_id {
        UCLASS_TEST_FDT,
        UCLASS_TEST_BUS,
        UCLASS_SPI_EMUL,        /* sandbox SPI device emulator */
+       UCLASS_I2C_EMUL,        /* sandbox I2C device emulator */
        UCLASS_SIMPLE_BUS,
 
        /* U-Boot uclasses start here */
@@ -29,6 +30,9 @@ enum uclass_id {
        UCLASS_SPI_FLASH,       /* SPI flash */
        UCLASS_CROS_EC, /* Chrome OS EC */
        UCLASS_THERMAL,         /* Thermal sensor */
+       UCLASS_I2C,             /* I2C bus */
+       UCLASS_I2C_GENERIC,     /* Generic I2C device */
+       UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
 
        UCLASS_COUNT,
        UCLASS_INVALID = -1,
index fa9eac0226537a542cc0a711473b9e7f1c5b8c5c..ec6146545b2e371a8b97f2da5615ff7aa8e22ba6 100644 (file)
@@ -89,6 +89,18 @@ void ut_failf(struct dm_test_state *dms, const char *fname, int line,
        }                                                               \
 }
 
+/* Assert that a pointer is not NULL */
+#define ut_assertnonnull(expr) {                                       \
+       const void *val = (expr);                                       \
+                                                                       \
+       if (val == NULL) {                                              \
+               ut_failf(dms, __FILE__, __LINE__, __func__,             \
+                        #expr " = NULL",                               \
+                        "Expected non-null, got NULL");                \
+               return -1;                                              \
+       }                                                               \
+}
+
 /* Assert that an operation succeeds (returns 0) */
 #define ut_assertok(cond)      ut_asserteq(0, cond)
 
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra.h b/include/dt-bindings/pinctrl/pinctrl-tegra.h
new file mode 100644 (file)
index 0000000..ebafa49
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This header provides constants for Tegra pinctrl bindings.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#ifndef _DT_BINDINGS_PINCTRL_TEGRA_H
+#define _DT_BINDINGS_PINCTRL_TEGRA_H
+
+/*
+ * Enable/disable for diffeent dt properties. This is applicable for
+ * properties nvidia,enable-input, nvidia,tristate, nvidia,open-drain,
+ * nvidia,lock, nvidia,rcv-sel, nvidia,high-speed-mode, nvidia,schmitt.
+ */
+#define TEGRA_PIN_DISABLE                              0
+#define TEGRA_PIN_ENABLE                               1
+
+#define TEGRA_PIN_PULL_NONE                            0
+#define TEGRA_PIN_PULL_DOWN                            1
+#define TEGRA_PIN_PULL_UP                              2
+
+/* Low power mode driver */
+#define TEGRA_PIN_LP_DRIVE_DIV_8                       0
+#define TEGRA_PIN_LP_DRIVE_DIV_4                       1
+#define TEGRA_PIN_LP_DRIVE_DIV_2                       2
+#define TEGRA_PIN_LP_DRIVE_DIV_1                       3
+
+/* Rising/Falling slew rate */
+#define TEGRA_PIN_SLEW_RATE_FASTEST                    0
+#define TEGRA_PIN_SLEW_RATE_FAST                       1
+#define TEGRA_PIN_SLEW_RATE_SLOW                       2
+#define TEGRA_PIN_SLEW_RATE_SLOWEST                    3
+
+#endif
index e24a33b386fefbbcb0bf24f742cccf32b4adc006..14ac3cb10b00bab70a6916fe15adae6af0b838f3 100644 (file)
@@ -6,4 +6,7 @@ extern int errno;
 
 #define __set_errno(val) do { errno = val; } while (0)
 
+#ifdef CONFIG_ERRNO_STR
+const char *errno_str(int errno);
+#endif
 #endif /* _ERRNO_H */
index 1b4078ed62fe43c8c3ac37b1ff732da0d431d37f..9c6a60cf9ae89e50e2a4d2dfaa94874a56774e1f 100644 (file)
 #ifndef _I2C_H_
 #define _I2C_H_
 
+/*
+ * For now there are essentially two parts to this file - driver model
+ * here at the top, and the older code below (with CONFIG_SYS_I2C being
+ * most recent). The plan is to migrate everything to driver model.
+ * The driver model structures and API are separate as they are different
+ * enough as to be incompatible for compilation purposes.
+ */
+
+#ifdef CONFIG_DM_I2C
+
+enum dm_i2c_chip_flags {
+       DM_I2C_CHIP_10BIT       = 1 << 0, /* Use 10-bit addressing */
+       DM_I2C_CHIP_RD_ADDRESS  = 1 << 1, /* Send address for each read byte */
+       DM_I2C_CHIP_WR_ADDRESS  = 1 << 2, /* Send address for each write byte */
+};
+
+/**
+ * struct dm_i2c_chip - information about an i2c chip
+ *
+ * An I2C chip is a device on the I2C bus. It sits at a particular address
+ * and normally supports 7-bit or 10-bit addressing.
+ *
+ * To obtain this structure, use dev_get_parentdata(dev) where dev is the
+ * chip to examine.
+ *
+ * @chip_addr: Chip address on bus
+ * @offset_len: Length of offset in bytes. A single byte offset can
+ *             represent up to 256 bytes. A value larger than 1 may be
+ *             needed for larger devices.
+ * @flags:     Flags for this chip (dm_i2c_chip_flags)
+ * @emul: Emulator for this chip address (only used for emulation)
+ */
+struct dm_i2c_chip {
+       uint chip_addr;
+       uint offset_len;
+       uint flags;
+#ifdef CONFIG_SANDBOX
+       struct udevice *emul;
+#endif
+};
+
+/**
+ * struct dm_i2c_bus- information about an i2c bus
+ *
+ * An I2C bus contains 0 or more chips on it, each at its own address. The
+ * bus can operate at different speeds (measured in Hz, typically 100KHz
+ * or 400KHz).
+ *
+ * To obtain this structure, use bus->uclass_priv where bus is the I2C
+ * bus udevice.
+ *
+ * @speed_hz: Bus speed in hertz (typically 100000)
+ */
+struct dm_i2c_bus {
+       int speed_hz;
+};
+
+/**
+ * i2c_read() - read bytes from an I2C chip
+ *
+ * To obtain an I2C device (called a 'chip') given the I2C bus address you
+ * can use i2c_get_chip(). To obtain a bus by bus number use
+ * uclass_get_device_by_seq(UCLASS_I2C, <bus number>).
+ *
+ * To set the address length of a devce use i2c_set_addr_len(). It
+ * defaults to 1.
+ *
+ * @dev:       Chip to read from
+ * @offset:    Offset within chip to start reading
+ * @buffer:    Place to put data
+ * @len:       Number of bytes to read
+ *
+ * @return 0 on success, -ve on failure
+ */
+int i2c_read(struct udevice *dev, uint offset, uint8_t *buffer,
+            int len);
+
+/**
+ * i2c_write() - write bytes to an I2C chip
+ *
+ * See notes for i2c_read() above.
+ *
+ * @dev:       Chip to write to
+ * @offset:    Offset within chip to start writing
+ * @buffer:    Buffer containing data to write
+ * @len:       Number of bytes to write
+ *
+ * @return 0 on success, -ve on failure
+ */
+int i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
+             int len);
+
+/**
+ * i2c_probe() - probe a particular chip address
+ *
+ * This can be useful to check for the existence of a chip on the bus.
+ * It is typically implemented by writing the chip address to the bus
+ * and checking that the chip replies with an ACK.
+ *
+ * @bus:       Bus to probe
+ * @chip_addr: 7-bit address to probe (10-bit and others are not supported)
+ * @chip_flags:        Flags for the probe (see enum dm_i2c_chip_flags)
+ * @devp:      Returns the device found, or NULL if none
+ * @return 0 if a chip was found at that address, -ve if not
+ */
+int i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
+             struct udevice **devp);
+
+/**
+ * i2c_set_bus_speed() - set the speed of a bus
+ *
+ * @bus:       Bus to adjust
+ * @speed:     Requested speed in Hz
+ * @return 0 if OK, -EINVAL for invalid values
+ */
+int i2c_set_bus_speed(struct udevice *bus, unsigned int speed);
+
+/**
+ * i2c_get_bus_speed() - get the speed of a bus
+ *
+ * @bus:       Bus to check
+ * @return speed of selected I2C bus in Hz, -ve on error
+ */
+int i2c_get_bus_speed(struct udevice *bus);
+
+/**
+ * i2c_set_chip_flags() - set flags for a chip
+ *
+ * Typically addresses are 7 bits, but for 10-bit addresses you should set
+ * flags to DM_I2C_CHIP_10BIT. All accesses will then use 10-bit addressing.
+ *
+ * @dev:       Chip to adjust
+ * @flags:     New flags
+ * @return 0 if OK, -EINVAL if value is unsupported, other -ve value on error
+ */
+int i2c_set_chip_flags(struct udevice *dev, uint flags);
+
+/**
+ * i2c_get_chip_flags() - get flags for a chip
+ *
+ * @dev:       Chip to check
+ * @flagsp:    Place to put flags
+ * @return 0 if OK, other -ve value on error
+ */
+int i2c_get_chip_flags(struct udevice *dev, uint *flagsp);
+
+/**
+ * i2c_set_offset_len() - set the offset length for a chip
+ *
+ * The offset used to access a chip may be up to 4 bytes long. Typically it
+ * is only 1 byte, which is enough for chips with 256 bytes of memory or
+ * registers. The default value is 1, but you can call this function to
+ * change it.
+ *
+ * @offset_len:        New offset length value (typically 1 or 2)
+ */
+
+int i2c_set_chip_offset_len(struct udevice *dev, uint offset_len);
+/**
+ * i2c_deblock() - recover a bus that is in an unknown state
+ *
+ * See the deblock() method in 'struct dm_i2c_ops' for full information
+ *
+ * @bus:       Bus to recover
+ * @return 0 if OK, -ve on error
+ */
+int i2c_deblock(struct udevice *bus);
+
+/*
+ * Not all of these flags are implemented in the U-Boot API
+ */
+enum dm_i2c_msg_flags {
+       I2C_M_TEN               = 0x0010, /* ten-bit chip address */
+       I2C_M_RD                = 0x0001, /* read data, from slave to master */
+       I2C_M_STOP              = 0x8000, /* send stop after this message */
+       I2C_M_NOSTART           = 0x4000, /* no start before this message */
+       I2C_M_REV_DIR_ADDR      = 0x2000, /* invert polarity of R/W bit */
+       I2C_M_IGNORE_NAK        = 0x1000, /* continue after NAK */
+       I2C_M_NO_RD_ACK         = 0x0800, /* skip the Ack bit on reads */
+       I2C_M_RECV_LEN          = 0x0400, /* length is first received byte */
+};
+
+/**
+ * struct i2c_msg - an I2C message
+ *
+ * @addr:      Slave address
+ * @flags:     Flags (see enum dm_i2c_msg_flags)
+ * @len:       Length of buffer in bytes, may be 0 for a probe
+ * @buf:       Buffer to send/receive, or NULL if no data
+ */
+struct i2c_msg {
+       uint addr;
+       uint flags;
+       uint len;
+       u8 *buf;
+};
+
+/**
+ * struct i2c_msg_list - a list of I2C messages
+ *
+ * This is called i2c_rdwr_ioctl_data in Linux but the name does not seem
+ * appropriate in U-Boot.
+ *
+ * @msg:       Pointer to i2c_msg array
+ * @nmsgs:     Number of elements in the array
+ */
+struct i2c_msg_list {
+       struct i2c_msg *msgs;
+       uint nmsgs;
+};
+
+/**
+ * struct dm_i2c_ops - driver operations for I2C uclass
+ *
+ * Drivers should support these operations unless otherwise noted. These
+ * operations are intended to be used by uclass code, not directly from
+ * other code.
+ */
+struct dm_i2c_ops {
+       /**
+        * xfer() - transfer a list of I2C messages
+        *
+        * @bus:        Bus to read from
+        * @msg:        List of messages to transfer
+        * @nmsgs:      Number of messages in the list
+        * @return 0 if OK, -EREMOTEIO if the slave did not ACK a byte,
+        *      -ECOMM if the speed cannot be supported, -EPROTO if the chip
+        *      flags cannot be supported, other -ve value on some other error
+        */
+       int (*xfer)(struct udevice *bus, struct i2c_msg *msg, int nmsgs);
+
+       /**
+        * probe_chip() - probe for the presense of a chip address
+        *
+        * This function is optional. If omitted, the uclass will send a zero
+        * length message instead.
+        *
+        * @bus:        Bus to probe
+        * @chip_addr:  Chip address to probe
+        * @chip_flags: Probe flags (enum dm_i2c_chip_flags)
+        * @return 0 if chip was found, -EREMOTEIO if not, -ENOSYS to fall back
+        * to default probem other -ve value on error
+        */
+       int (*probe_chip)(struct udevice *bus, uint chip_addr, uint chip_flags);
+
+       /**
+        * set_bus_speed() - set the speed of a bus (optional)
+        *
+        * The bus speed value will be updated by the uclass if this function
+        * does not return an error. This method is optional - if it is not
+        * provided then the driver can read the speed from
+        * bus->uclass_priv->speed_hz
+        *
+        * @bus:        Bus to adjust
+        * @speed:      Requested speed in Hz
+        * @return 0 if OK, -EINVAL for invalid values
+        */
+       int (*set_bus_speed)(struct udevice *bus, unsigned int speed);
+
+       /**
+        * get_bus_speed() - get the speed of a bus (optional)
+        *
+        * Normally this can be provided by the uclass, but if you want your
+        * driver to check the bus speed by looking at the hardware, you can
+        * implement that here. This method is optional. This method would
+        * normally be expected to return bus->uclass_priv->speed_hz.
+        *
+        * @bus:        Bus to check
+        * @return speed of selected I2C bus in Hz, -ve on error
+        */
+       int (*get_bus_speed)(struct udevice *bus);
+
+       /**
+        * set_flags() - set the flags for a chip (optional)
+        *
+        * This is generally implemented by the uclass, but drivers can
+        * check the value to ensure that unsupported options are not used.
+        * This method is optional. If provided, this method will always be
+        * called when the flags change.
+        *
+        * @dev:        Chip to adjust
+        * @flags:      New flags value
+        * @return 0 if OK, -EINVAL if value is unsupported
+        */
+       int (*set_flags)(struct udevice *dev, uint flags);
+
+       /**
+        * deblock() - recover a bus that is in an unknown state
+        *
+        * I2C is a synchronous protocol and resets of the processor in the
+        * middle of an access can block the I2C Bus until a powerdown of
+        * the full unit is done. This is because slaves can be stuck
+        * waiting for addition bus transitions for a transaction that will
+        * never complete. Resetting the I2C master does not help. The only
+        * way is to force the bus through a series of transitions to make
+        * sure that all slaves are done with the transaction. This method
+        * performs this 'deblocking' if support by the driver.
+        *
+        * This method is optional.
+        */
+       int (*deblock)(struct udevice *bus);
+};
+
+#define i2c_get_ops(dev)       ((struct dm_i2c_ops *)(dev)->driver->ops)
+
+/**
+ * i2c_get_chip() - get a device to use to access a chip on a bus
+ *
+ * This returns the device for the given chip address. The device can then
+ * be used with calls to i2c_read(), i2c_write(), i2c_probe(), etc.
+ *
+ * @bus:       Bus to examine
+ * @chip_addr: Chip address for the new device
+ * @devp:      Returns pointer to new device if found or -ENODEV if not
+ *             found
+ */
+int i2c_get_chip(struct udevice *bus, uint chip_addr, struct udevice **devp);
+
+/**
+ * i2c_get_chip() - get a device to use to access a chip on a bus number
+ *
+ * This returns the device for the given chip address on a particular bus
+ * number.
+ *
+ * @busnum:    Bus number to examine
+ * @chip_addr: Chip address for the new device
+ * @devp:      Returns pointer to new device if found or -ENODEV if not
+ *             found
+ */
+int i2c_get_chip_for_busnum(int busnum, int chip_addr, struct udevice **devp);
+
+/**
+ * i2c_chip_ofdata_to_platdata() - Decode standard I2C platform data
+ *
+ * This decodes the chip address from a device tree node and puts it into
+ * its dm_i2c_chip structure. This should be called in your driver's
+ * ofdata_to_platdata() method.
+ *
+ * @blob:      Device tree blob
+ * @node:      Node offset to read from
+ * @spi:       Place to put the decoded information
+ */
+int i2c_chip_ofdata_to_platdata(const void *blob, int node,
+                               struct dm_i2c_chip *chip);
+
+#endif
+
+#ifndef CONFIG_DM_I2C
+
 /*
  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  *
@@ -451,4 +800,7 @@ int i2c_get_bus_num_fdt(int node);
  * @return 0 if port was reset, -1 if not found
  */
 int i2c_reset_port_fdt(const void *blob, int node);
+
+#endif /* !CONFIG_DM_I2C */
+
 #endif /* _I2C_H_ */
diff --git a/include/i2c_eeprom.h b/include/i2c_eeprom.h
new file mode 100644 (file)
index 0000000..ea6c962
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __I2C_EEPROM
+#define __I2C_EEPROM
+
+struct i2c_eeprom_ops {
+       int (*read)(struct udevice *dev, int offset, uint8_t *buf, int size);
+       int (*write)(struct udevice *dev, int offset, const uint8_t *buf,
+                    int size);
+};
+
+struct i2c_eeprom {
+};
+
+#endif
index 96348d617fca34c4abfbf00759a84b8178d8aae9..c7047ba0bca6a8bd191013eae45aea7307b71552 100644 (file)
@@ -30,6 +30,9 @@ extern char * strcpy(char *,const char *);
 #ifndef __HAVE_ARCH_STRNCPY
 extern char * strncpy(char *,const char *, __kernel_size_t);
 #endif
+#ifndef __HAVE_ARCH_STRLCPY
+size_t strlcpy(char *, const char *, size_t);
+#endif
 #ifndef __HAVE_ARCH_STRCAT
 extern char * strcat(char *, const char *);
 #endif
index 78ce428767671c43c827828b455b70b969f38ec0..eefc95f22ea688d937b92f959cc9ef9887d6b29c 100644 (file)
@@ -44,9 +44,9 @@ int tps6586x_adjust_sm0_sm1(int sm0_target, int sm1_target, int step, int rate,
  * Set up the TPS6586X I2C bus number. This will be used for all operations
  * on the device. This function must be called before using other functions.
  *
- * @param bus  I2C bus number containing the TPS6586X chip
+ * @param bus  I2C bus containing the TPS6586X chip
  * @return 0 (always succeeds)
  */
-int tps6586x_init(int bus);
+int tps6586x_init(struct udevice *bus);
 
 #endif /* _TPS6586X_H_ */
index 3ceb69752c68a82ed7bde23909dfceabaeae4fe2..07d175f45e87987c659404aba8e5774bccaf2860 100644 (file)
@@ -51,6 +51,7 @@ endif
 obj-$(CONFIG_ADDR_MAP) += addr_map.o
 obj-y += hashtable.o
 obj-y += errno.o
+obj-$(CONFIG_ERRNO_STR) += errno_str.o
 obj-y += display_options.o
 obj-$(CONFIG_BCH) += bch.o
 obj-y += crc32.o
diff --git a/lib/errno_str.c b/lib/errno_str.c
new file mode 100644 (file)
index 0000000..0ba950e
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SDPX-License-Identifier:    GPL-2.0+
+ */
+#include <common.h>
+#include <errno.h>
+
+#define ERRNO_MSG(errno, msg)  msg
+#define SAME_AS(x)             (const char *)&errno_message[x]
+
+static const char * const errno_message[] = {
+       ERRNO_MSG(0, "Success"),
+       ERRNO_MSG(EPERM, "Operation not permitted"),
+       ERRNO_MSG(ENOEN, "No such file or directory"),
+       ERRNO_MSG(ESRCH, "No such process"),
+       ERRNO_MSG(EINTR, "Interrupted system call"),
+       ERRNO_MSG(EIO, "I/O error"),
+       ERRNO_MSG(ENXIO, "No such device or address"),
+       ERRNO_MSG(E2BIG, "Argument list too long"),
+       ERRNO_MSG(ENOEXEC, "Exec format error"),
+       ERRNO_MSG(EBADF, "Bad file number"),
+       ERRNO_MSG(ECHILD, "No child processes"),
+       ERRNO_MSG(EAGAIN, "Try again"),
+       ERRNO_MSG(ENOMEM, "Out of memory"),
+       ERRNO_MSG(EACCES, "Permission denied"),
+       ERRNO_MSG(EFAULT, "Bad address"),
+       ERRNO_MSG(ENOTBL, "Block device required"),
+       ERRNO_MSG(EBUSY, "Device or resource busy"),
+       ERRNO_MSG(EEXIST, "File exists"),
+       ERRNO_MSG(EXDEV, "Cross-device link"),
+       ERRNO_MSG(ENODEV, "No such device"),
+       ERRNO_MSG(ENOTDIR, "Not a directory"),
+       ERRNO_MSG(EISDIR, "Is a directory"),
+       ERRNO_MSG(EINVAL, "Invalid argument"),
+       ERRNO_MSG(ENFILE, "File table overflow"),
+       ERRNO_MSG(EMFILE, "Too many open files"),
+       ERRNO_MSG(ENOTTY, "Not a typewriter"),
+       ERRNO_MSG(ETXTBSY, "Text file busy"),
+       ERRNO_MSG(EFBIG, "File too large"),
+       ERRNO_MSG(ENOSPC, "No space left on device"),
+       ERRNO_MSG(ESPIPE, "Illegal seek"),
+       ERRNO_MSG(EROFS, "Read-only file system"),
+       ERRNO_MSG(EMLINK, "Too many links"),
+       ERRNO_MSG(EPIPE, "Broken pipe"),
+       ERRNO_MSG(EDOM, "Math argument out of domain of func"),
+       ERRNO_MSG(ERANGE, "Math result not representable"),
+       ERRNO_MSG(EDEADLK, "Resource deadlock would occur"),
+       ERRNO_MSG(ENAMETOOLONG, "File name too long"),
+       ERRNO_MSG(ENOLCK, "No record locks available"),
+       ERRNO_MSG(ENOSYS, "Function not implemented"),
+       ERRNO_MSG(ENOTEMPTY, "Directory not empty"),
+       ERRNO_MSG(ELOOP, "Too many symbolic links encountered"),
+       ERRNO_MSG(EWOULDBLOCK, SAME_AS(EAGAIN)),
+       ERRNO_MSG(ENOMSG, "No message of desired type"),
+       ERRNO_MSG(EIDRM, "Identifier removed"),
+       ERRNO_MSG(ECHRNG, "Channel number out of range"),
+       ERRNO_MSG(EL2NSYNC, "Level 2 not synchronized"),
+       ERRNO_MSG(EL3HLT, "Level 3 halted"),
+       ERRNO_MSG(EL3RST, "Level 3 reset"),
+       ERRNO_MSG(ELNRNG, "Link number out of range"),
+       ERRNO_MSG(EUNATCH, "Protocol driver not attached"),
+       ERRNO_MSG(ENOCSI, "No CSI structure available"),
+       ERRNO_MSG(EL2HLT, "Level 2 halted"),
+       ERRNO_MSG(EBADE, "Invalid exchange"),
+       ERRNO_MSG(EBADR, "Invalid request descriptor"),
+       ERRNO_MSG(EXFULL, "Exchange full"),
+       ERRNO_MSG(ENOANO, "No anode"),
+       ERRNO_MSG(EBADRQC, "Invalid request code"),
+       ERRNO_MSG(EBADSLT, "Invalid slot"),
+       ERRNO_MSG(EDEADLOCK, SAME_AS(EDEADLK)),
+       ERRNO_MSG(EBFONT, "Bad font file format"),
+       ERRNO_MSG(ENOSTR, "Device not a stream"),
+       ERRNO_MSG(ENODATA, "No data available"),
+       ERRNO_MSG(ETIME, "Timer expired"),
+       ERRNO_MSG(ENOSR, "Out of streams resources"),
+       ERRNO_MSG(ENONET, "Machine is not on the network"),
+       ERRNO_MSG(ENOPKG, "Package not installed"),
+       ERRNO_MSG(EREMOTE, "Object is remote"),
+       ERRNO_MSG(ENOLINK, "Link has been severed"),
+       ERRNO_MSG(EADV, "Advertise error"),
+       ERRNO_MSG(ESRMNT, "Srmount error"),
+       ERRNO_MSG(ECOMM, "Communication error on send"),
+       ERRNO_MSG(EPROTO, "Protocol error"),
+       ERRNO_MSG(EMULTIHOP, "Multihop attempted"),
+       ERRNO_MSG(EDOTDOT, "RFS specific error"),
+       ERRNO_MSG(EBADMSG, "Not a data message"),
+       ERRNO_MSG(EOVERFLOW, "Value too large for defined data type"),
+       ERRNO_MSG(ENOTUNIQ, "Name not unique on network"),
+       ERRNO_MSG(EBADFD, "File descriptor in bad state"),
+       ERRNO_MSG(EREMCHG, "Remote address changed"),
+       ERRNO_MSG(ELIBACC, "Can not access a needed shared library"),
+       ERRNO_MSG(ELIBBAD, "Accessing a corrupted shared library"),
+       ERRNO_MSG(ELIBSCN, ".lib section in a.out corrupted"),
+       ERRNO_MSG(ELIBMAX, "Attempting to link in too many shared libraries"),
+       ERRNO_MSG(ELIBEXEC, "Cannot exec a shared library directly"),
+       ERRNO_MSG(EILSEQ, "Illegal byte sequence"),
+       ERRNO_MSG(ERESTART, "Interrupted system call should be restarted"),
+       ERRNO_MSG(ESTRPIPE, "Streams pipe error"),
+       ERRNO_MSG(EUSERS, "Too many users"),
+       ERRNO_MSG(ENOTSOCK, "Socket operation on non-socket"),
+       ERRNO_MSG(EDESTADDRREQ, "Destination address required"),
+       ERRNO_MSG(EMSGSIZE, "Message too long"),
+       ERRNO_MSG(EPROTOTYPE, "Protocol wrong type for socket"),
+       ERRNO_MSG(ENOPROTOOPT, "Protocol not available"),
+       ERRNO_MSG(EPROTONOSUPPORT, "Protocol not supported"),
+       ERRNO_MSG(ESOCKTNOSUPPORT, "Socket type not supported"),
+       ERRNO_MSG(EOPNOTSUPP, "Operation not supported on transport endpoint"),
+       ERRNO_MSG(EPFNOSUPPORT, "Protocol family not supported"),
+       ERRNO_MSG(AFNOSUPPORT, "Address family not supported by protocol"),
+       ERRNO_MSG(EADDRINUSE, "Address already in use"),
+       ERRNO_MSG(EADDRNOTAVAIL, "Cannot assign requested address"),
+       ERRNO_MSG(ENETDOWN, "Network is down"),
+       ERRNO_MSG(ENETUNREACH, "Network is unreachable"),
+       ERRNO_MSG(ENETRESET, "Network dropped connection because of reset"),
+       ERRNO_MSG(ECONNABORTED, "Software caused connection abort"),
+       ERRNO_MSG(ECONNRESET, "Connection reset by peer"),
+       ERRNO_MSG(ENOBUFS, "No buffer space available"),
+       ERRNO_MSG(EISCONN, "Transport endpoint is already connected"),
+       ERRNO_MSG(ENOTCONN, "Transport endpoint is not connected"),
+       ERRNO_MSG(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
+       ERRNO_MSG(ETOOMANYREFS, "Too many references: cannot splice"),
+       ERRNO_MSG(ETIMEDOUT, "Connection timed out"),
+       ERRNO_MSG(ECONNREFUSED, "Connection refused"),
+       ERRNO_MSG(EHOSTDOWN, "Host is down"),
+       ERRNO_MSG(EHOSTUNREACH, "No route to host"),
+       ERRNO_MSG(EALREADY, "Operation already in progress"),
+       ERRNO_MSG(EINPROGRESS, "Operation now in progress"),
+       ERRNO_MSG(ESTALE, "Stale NFS file handle"),
+       ERRNO_MSG(EUCLEAN, "Structure needs cleaning"),
+       ERRNO_MSG(ENOTNAM, "Not a XENIX named type file"),
+       ERRNO_MSG(ENAVAIL, "No XENIX semaphores available"),
+       ERRNO_MSG(EISNAM, "Is a named type file"),
+       ERRNO_MSG(EREMOTEIO, "Remote I/O error"),
+       ERRNO_MSG(EDQUOT, "Quota exceeded"),
+       ERRNO_MSG(ENOMEDIUM, "No medium found"),
+       ERRNO_MSG(EMEDIUMTYPE, "Wrong medium type"),
+};
+
+const char *errno_str(int errno)
+{
+       if (errno >= 0)
+               return errno_message[0];
+
+       return errno_message[abs(errno)];
+}
index 29c2ca7ef6b12688ccfec0c4ec8451ad47f49e1f..87c9a408e625de435c1051ccfaa20074dca0ad15 100644 (file)
@@ -102,6 +102,31 @@ char * strncpy(char * dest,const char *src,size_t count)
 }
 #endif
 
+#ifndef __HAVE_ARCH_STRLCPY
+/**
+ * strlcpy - Copy a C-string into a sized buffer
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @size: size of destination buffer
+ *
+ * Compatible with *BSD: the result is always a valid
+ * NUL-terminated string that fits in the buffer (unless,
+ * of course, the buffer size is zero). It does not pad
+ * out the result like strncpy() does.
+ */
+size_t strlcpy(char *dest, const char *src, size_t size)
+{
+       size_t ret = strlen(src);
+
+       if (size) {
+               size_t len = (ret >= size) ? size - 1 : ret;
+               memcpy(dest, src, len);
+               dest[len] = '\0';
+       }
+       return ret;
+}
+#endif
+
 #ifndef __HAVE_ARCH_STRCAT
 /**
  * strcat - Append one %NUL-terminated string to another
index 75d3d41536bfb47079f37a284beca95bd982b425..612aa957fa2d9ccb832382c6f0e55d3d037b3c67 100644 (file)
@@ -20,4 +20,5 @@ ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_SPI) += spi.o
 obj-$(CONFIG_DM_SPI_FLASH) += sf.o
+obj-$(CONFIG_DM_I2C) += i2c.o
 endif
index 26980d209f4e8dede78d0d861f95a10ce0dd8232..79a674efcc5bc35559698cad5413723a7308d4dc 100644 (file)
 #include <dm/test.h>
 #include <dm/uclass-internal.h>
 
+static void show_devices(struct udevice *dev, int depth, int last_flag)
+{
+       int i, is_last;
+       struct udevice *child;
+       char class_name[12];
+
+       /* print the first 11 characters to not break the tree-format. */
+       strlcpy(class_name, dev->uclass->uc_drv->name, sizeof(class_name));
+       printf(" %-11s [ %c ]    ", class_name,
+              dev->flags & DM_FLAG_ACTIVATED ? '+' : ' ');
+
+       for (i = depth; i >= 0; i--) {
+               is_last = (last_flag >> i) & 1;
+               if (i) {
+                       if (is_last)
+                               printf("    ");
+                       else
+                               printf("|   ");
+               } else {
+                       if (is_last)
+                               printf("`-- ");
+                       else
+                               printf("|-- ");
+               }
+       }
+
+       printf("%s\n", dev->name);
+
+       list_for_each_entry(child, &dev->child_head, sibling_node) {
+               is_last = list_is_last(&child->sibling_node, &dev->child_head);
+               show_devices(child, depth + 1, (last_flag << 1) | is_last);
+       }
+}
+
+static int do_dm_dump_all(cmd_tbl_t *cmdtp, int flag, int argc,
+                         char * const argv[])
+{
+       struct udevice *root;
+
+       root = dm_root();
+       if (root) {
+               printf(" Class       Probed   Name\n");
+               printf("----------------------------------------\n");
+               show_devices(root, -1, 0);
+       }
+
+       return 0;
+}
+
 /**
  * dm_display_line() - Display information about a single device
  *
  * Displays a single line of information with an option prefix
  *
  * @dev:       Device to display
- * @buf:       Prefix to display at the start of the line
  */
-static void dm_display_line(struct udevice *dev, char *buf)
+static void dm_display_line(struct udevice *dev)
 {
-       printf("%s- %c %s @ %08lx", buf,
+       printf("- %c %s @ %08lx",
               dev->flags & DM_FLAG_ACTIVATED ? '*' : ' ',
               dev->name, (ulong)map_to_sysmem(dev));
        if (dev->req_seq != -1)
@@ -34,53 +82,6 @@ static void dm_display_line(struct udevice *dev, char *buf)
        puts("\n");
 }
 
-static int display_succ(struct udevice *in, char *buf)
-{
-       int len;
-       int ip = 0;
-       char local[16];
-       struct udevice *pos, *n, *prev = NULL;
-
-       dm_display_line(in, buf);
-
-       if (list_empty(&in->child_head))
-               return 0;
-
-       len = strlen(buf);
-       strncpy(local, buf, sizeof(local));
-       snprintf(local + len, 2, "|");
-       if (len && local[len - 1] == '`')
-               local[len - 1] = ' ';
-
-       list_for_each_entry_safe(pos, n, &in->child_head, sibling_node) {
-               if (ip++)
-                       display_succ(prev, local);
-               prev = pos;
-       }
-
-       snprintf(local + len, 2, "`");
-       display_succ(prev, local);
-
-       return 0;
-}
-
-static int dm_dump(struct udevice *dev)
-{
-       if (!dev)
-               return -EINVAL;
-       return display_succ(dev, "");
-}
-
-static int do_dm_dump_all(cmd_tbl_t *cmdtp, int flag, int argc,
-                         char * const argv[])
-{
-       struct udevice *root;
-
-       root = dm_root();
-       printf("ROOT %08lx\n", (ulong)map_to_sysmem(root));
-       return dm_dump(root);
-}
-
 static int do_dm_dump_uclass(cmd_tbl_t *cmdtp, int flag, int argc,
                             char * const argv[])
 {
@@ -99,7 +100,7 @@ static int do_dm_dump_uclass(cmd_tbl_t *cmdtp, int flag, int argc,
                if (list_empty(&uc->dev_head))
                        continue;
                list_for_each_entry(dev, &uc->dev_head, uclass_node) {
-                       dm_display_line(dev, "");
+                       dm_display_line(dev);
                }
                puts("\n");
        }
diff --git a/test/dm/i2c.c b/test/dm/i2c.c
new file mode 100644 (file)
index 0000000..a53e28d
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Note: Test coverage does not include 10-bit addressing
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <dm/ut.h>
+#include <dm/util.h>
+#include <asm/state.h>
+#include <asm/test.h>
+
+static const int busnum;
+static const int chip = 0x2c;
+
+/* Test that we can find buses and chips */
+static int dm_test_i2c_find(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       const int no_chip = 0x10;
+
+       ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_I2C, busnum,
+                                                      false, &bus));
+
+       /*
+        * i2c_post_bind() will bind devices to chip selects. Check this then
+        * remove the emulation and the slave device.
+        */
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_probe(bus, chip, 0, &dev));
+       ut_asserteq(-ENODEV, i2c_probe(bus, no_chip, 0, &dev));
+       ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_I2C, 1, &bus));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_find, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_read_write(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0AB\0", sizeof(buf)));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_read_write, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_speed(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_set_bus_speed(bus, 100000));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(i2c_set_bus_speed(bus, 400000));
+       ut_asserteq(400000, i2c_get_bus_speed(bus));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_asserteq(-EINVAL, i2c_write(dev, 0, buf, 5));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_speed, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_offset_len(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_set_chip_offset_len(dev, 1));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+
+       /* This is not supported by the uclass */
+       ut_asserteq(-EINVAL, i2c_set_chip_offset_len(dev, 5));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_offset_len, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_probe_empty(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_probe_empty, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_bytewise(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       struct udevice *eeprom;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
+
+       /* Tell the EEPROM to only read/write one register at a time */
+       ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom));
+       ut_assertnonnull(eeprom);
+       sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_SINGLE_BYTE);
+
+       /* Now we only get the first byte - the rest will be 0xff */
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
+
+       /* If we do a separate transaction for each byte, it works */
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
+
+       /* This will only write A */
+       ut_assertok(i2c_set_chip_flags(dev, 0));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
+
+       /* Check that the B was ignored */
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0A\0\0\0", sizeof(buf)));
+
+       /* Now write it again with the new flags, it should work */
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
+
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS |
+                                               DM_I2C_CHIP_RD_ADDRESS));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0AB\0\0", sizeof(buf)));
+
+       /* Restore defaults */
+       sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_NONE);
+       ut_assertok(i2c_set_chip_flags(dev, 0));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_bytewise, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_offset(struct dm_test_state *dms)
+{
+       struct udevice *eeprom;
+       struct udevice *dev;
+       uint8_t buf[5];
+
+       ut_assertok(i2c_get_chip_for_busnum(busnum, chip, &dev));
+
+       /* Do a transfer so we can find the emulator */
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom));
+
+       /* Offset length 0 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 0);
+       ut_assertok(i2c_set_chip_offset_len(dev, 0));
+       ut_assertok(i2c_write(dev, 10 /* ignored */, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0\0", sizeof(buf)));
+
+       /* Offset length 1 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 1);
+       ut_assertok(i2c_set_chip_offset_len(dev, 1));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "ABAB\0", sizeof(buf)));
+
+       /* Offset length 2 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
+       ut_assertok(i2c_set_chip_offset_len(dev, 2));
+       ut_assertok(i2c_write(dev, 0x210, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0x210, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+
+       /* Offset length 3 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
+       ut_assertok(i2c_set_chip_offset_len(dev, 2));
+       ut_assertok(i2c_write(dev, 0x410, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0x410, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+
+       /* Offset length 4 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
+       ut_assertok(i2c_set_chip_offset_len(dev, 2));
+       ut_assertok(i2c_write(dev, 0x420, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0x420, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+
+       /* Restore defaults */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 1);
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_offset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
index 1fba7925642a928fd60f10fd4ed7ee1bcc192890..fb0272a59cd25472b4e733afbe832a35c607d1d8 100644 (file)
                num-gpios = <10>;
        };
 
+       i2c@0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0>;
+               compatible = "sandbox,i2c";
+               clock-frequency = <100000>;
+               eeprom@2c {
+                       reg = <0x2c>;
+                       compatible = "i2c-eeprom";
+                       emul {
+                               compatible = "sandbox,i2c-eeprom";
+                               sandbox,filename = "i2c.bin";
+                               sandbox,size = <256>;
+                       };
+               };
+       };
+
        spi@0 {
                #address-cells = <1>;
                #size-cells = <0>;