]> git.sur5r.net Git - u-boot/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-video
authorTom Rini <trini@konsulko.com>
Thu, 5 Nov 2015 12:47:21 +0000 (07:47 -0500)
committerTom Rini <trini@konsulko.com>
Thu, 5 Nov 2015 12:47:21 +0000 (07:47 -0500)
66 files changed:
arch/arm/cpu/armv7/s5p-common/cpu_info.c
arch/arm/dts/exynos5422-odroidxu3.dts
arch/arm/dts/exynos54xx.dtsi
arch/arm/dts/exynos5800-peach-pi.dts
arch/arm/dts/socfpga_cyclone5_socdk.dts
arch/arm/mach-exynos/clock.c
arch/arm/mach-exynos/clock_init_exynos5.c
arch/arm/mach-exynos/common_setup.h
arch/arm/mach-exynos/dmc_init_ddr3.c
arch/arm/mach-exynos/include/mach/adc.h
arch/arm/mach-exynos/include/mach/cpu.h
arch/arm/mach-exynos/include/mach/gpio.h
arch/arm/mach-exynos/pinmux.c
arch/arm/mach-exynos/power.c
arch/arm/mach-socfpga/include/mach/reset_manager.h
arch/sandbox/dts/sandbox_pmic.dtsi
arch/sandbox/dts/test.dts
board/samsung/common/Makefile
board/samsung/common/board.c
board/samsung/common/exynos5-dt-types.c [new file with mode: 0644]
board/samsung/common/exynos5-dt.c
board/samsung/common/misc.c
board/samsung/odroid/odroid.c
board/samsung/smdk2410/smdk2410.c
board/samsung/smdkv310/smdkv310.c
common/usb_storage.c
configs/odroid-xu3_defconfig
configs/sandbox_defconfig
doc/device-tree-bindings/adc/adc.txt [new file with mode: 0644]
doc/device-tree-bindings/exynos/soc.txt [new file with mode: 0644]
doc/device-tree-bindings/pmic/s2mps11.txt [new file with mode: 0644]
drivers/Kconfig
drivers/Makefile
drivers/adc/Kconfig [new file with mode: 0644]
drivers/adc/Makefile [new file with mode: 0644]
drivers/adc/adc-uclass.c [new file with mode: 0644]
drivers/adc/exynos-adc.c [new file with mode: 0644]
drivers/adc/sandbox.c [new file with mode: 0644]
drivers/dfu/dfu_sf.c
drivers/mmc/s5p_sdhci.c
drivers/power/pmic/Kconfig
drivers/power/pmic/Makefile
drivers/power/pmic/s2mps11.c [new file with mode: 0644]
drivers/power/regulator/regulator-uclass.c
drivers/spi/cadence_qspi.c
drivers/spi/cadence_qspi.h
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/io.h
drivers/usb/gadget/f_thor.c
drivers/usb/gadget/udc/udc-core.c
drivers/usb/host/ohci-hcd.c
include/adc.h [new file with mode: 0644]
include/configs/dra7xx_evm.h
include/configs/odroid_xu3.h
include/dm/uclass-id.h
include/fdtdec.h
include/power/regulator.h
include/power/s2mps11.h [new file with mode: 0644]
include/power/sandbox_pmic.h
include/samsung/exynos5-dt-types.h [new file with mode: 0644]
include/sandbox-adc.h [new file with mode: 0644]
lib/fdtdec_common.c
test/dm/Makefile
test/dm/adc.c [new file with mode: 0644]

index 154d67490d4020eb41ecfd35219ab416946bc618..764c6614ea7f2bad8eb6dd15fb3c9c2a3f20081a 100644 (file)
@@ -5,9 +5,12 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <fdtdec.h>
 #include <asm/io.h>
 #include <asm/arch/clk.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Default is s5pc100 */
 unsigned int s5p_cpu_id = 0xC100;
 /* Default is EVT1 */
@@ -30,7 +33,16 @@ u32 get_device_type(void)
 #ifdef CONFIG_DISPLAY_CPUINFO
 int print_cpuinfo(void)
 {
-       printf("CPU:   %s%X @ ", s5p_get_cpu_name(), s5p_cpu_id);
+       const char *cpu_model;
+       int len;
+
+       /* For SoC with no real CPU ID in naming convention. */
+       cpu_model = fdt_getprop(gd->fdt_blob, 0, "cpu-model", &len);
+       if (cpu_model)
+               printf("CPU:   %.*s @ ", len, cpu_model);
+       else
+               printf("CPU:   %s%X @ ", s5p_get_cpu_name(), s5p_cpu_id);
+
        print_freq(get_arm_clk(), "\n");
 
        return 0;
index d0a8621fdad3c95cd0890a96ccc0208d8c03111a..690c747289a11bff9235c5d043228d88b93fbff6 100644 (file)
                        0xb0000000 0xea00000>;
        };
 
+       adc@12D10000 {
+               u-boot,dm-pre-reloc;
+               status = "okay";
+       };
+
+       i2c@12CA0000 {
+               s2mps11_pmic@66 {
+                       compatible = "samsung,s2mps11-pmic";
+                       reg = <0x66>;
+               };
+       };
+
        ehci@12110000 {
                samsung,vbus-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
        };
index bd3619d75137f0b884824eab6f3a73cc4b8c1098..daa6a33c5b5501566d399be0bb29700f5b301dad 100644 (file)
                xhci1 = "/xhci@12400000";
        };
 
+       adc@12D10000 {
+               compatible = "samsung,exynos-adc-v2";
+               reg = <0x12D10000 0x100>;
+               interrupts = <0 106 0>;
+               status = "disabled";
+       };
+
        i2c@12CA0000 {
                #address-cells = <1>;
                #size-cells = <0>;
index 1d7ff23c933cbeef16c088be12030b069b08c761..76826dc23b92c3b69f4eda5887793968a0078b98 100644 (file)
@@ -12,6 +12,7 @@
 
 / {
        model = "Samsung/Google Peach Pi board based on Exynos5800";
+       cpu-model = "Exynos5800";
 
        compatible = "google,pit-rev#", "google,pit",
                "google,peach", "samsung,exynos5800", "samsung,exynos5";
index 546560979bd97809dd550c1f31437ab23c7f979e..9eb5a2209c63b721ec5bc7fd773572703ef368be 100644 (file)
@@ -89,7 +89,7 @@
                #size-cells = <1>;
                compatible = "n25q00";
                reg = <0>;      /* chip select */
-               spi-max-frequency = <50000000>;
+               spi-max-frequency = <100000000>;
                m25p,fast-read;
                page-size = <256>;
                block-size = <16>; /* 2^16, 64KB */
index 18eadf545fa94926a324b53637e5e96d23e2e702..3d31f9d524909716ee3785139614d4d80366aefa 100644 (file)
@@ -159,8 +159,8 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
                        div = PLL_DIV_1024;
                else if (proid_is_exynos4412())
                        div = PLL_DIV_65535;
-               else if (proid_is_exynos5250() || proid_is_exynos5420()
-                        || proid_is_exynos5800())
+               else if (proid_is_exynos5250() || proid_is_exynos5420() ||
+                        proid_is_exynos5422())
                        div = PLL_DIV_65536;
                else
                        return 0;
@@ -346,7 +346,7 @@ static struct clk_bit_info *get_clk_bit_info(int peripheral)
        int i;
        struct clk_bit_info *info;
 
-       if (proid_is_exynos5420() || proid_is_exynos5800())
+       if (proid_is_exynos5420() || proid_is_exynos5422())
                info = exynos542x_bit_info;
        else
                info = exynos5_bit_info;
@@ -558,7 +558,7 @@ static unsigned long exynos542x_get_periph_rate(int peripheral)
 unsigned long clock_get_periph_rate(int peripheral)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        return exynos542x_get_periph_rate(peripheral);
                return exynos5_get_periph_rate(peripheral);
        } else {
@@ -1576,7 +1576,7 @@ static unsigned long exynos4_get_i2c_clk(void)
 unsigned long get_pll_clk(int pllreg)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        return exynos542x_get_pll_clk(pllreg);
                return exynos5_get_pll_clk(pllreg);
        } else if (cpu_is_exynos4()) {
@@ -1692,7 +1692,7 @@ void set_mmc_clk(int dev_index, unsigned int div)
                div -= 1;
 
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        exynos5420_set_mmc_clk(dev_index, div);
                else
                        exynos5_set_mmc_clk(dev_index, div);
@@ -1708,7 +1708,7 @@ unsigned long get_lcd_clk(void)
        } else if (cpu_is_exynos5()) {
                if (proid_is_exynos5420())
                        return exynos5420_get_lcd_clk();
-               else if (proid_is_exynos5800())
+               else if (proid_is_exynos5422())
                        return exynos5800_get_lcd_clk();
                else
                        return exynos5_get_lcd_clk();
@@ -1740,7 +1740,7 @@ void set_mipi_clk(void)
 int set_spi_clk(int periph_id, unsigned int rate)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        return exynos5420_set_spi_clk(periph_id, rate);
                return exynos5_set_spi_clk(periph_id, rate);
        }
index 0200fd154f9491eb974873db7ec4b0e061dae515..1b7498d9d5f6fc113191178322cd4702210a943a 100644 (file)
@@ -971,7 +971,7 @@ static void exynos5420_system_clock_init(void)
 
 void system_clock_init(void)
 {
-       if (proid_is_exynos5420() || proid_is_exynos5800())
+       if (proid_is_exynos5420() || proid_is_exynos5422())
                exynos5420_system_clock_init();
        else
                exynos5250_system_clock_init();
index 67aac2d57517b5988c637798ee739509cb796847..2829fb269edae48d1fa1891d629059c88fb16db4 100644 (file)
@@ -78,7 +78,7 @@ static inline void configure_l2_ctlr(void)
                CACHE_TAG_RAM_LATENCY_2_CYCLES |
                CACHE_DATA_RAM_LATENCY_2_CYCLES;
 
-       if (proid_is_exynos5420() || proid_is_exynos5800()) {
+       if (proid_is_exynos5420() || proid_is_exynos5422()) {
                val |= CACHE_ECC_AND_PARITY |
                        CACHE_TAG_RAM_LATENCY_3_CYCLES |
                        CACHE_DATA_RAM_LATENCY_3_CYCLES;
@@ -97,7 +97,7 @@ static inline void configure_l2_actlr(void)
 {
        uint32_t val;
 
-       if (proid_is_exynos5420() || proid_is_exynos5800()) {
+       if (proid_is_exynos5420() || proid_is_exynos5422()) {
                mrc_l2_aux_ctlr(val);
                val |= CACHE_ENABLE_FORCE_L2_LOGIC |
                        CACHE_DISABLE_CLEAN_EVICT;
index 7c0b12ae51addbffee5af54128ddd2f57a539adf..25a9df936479c8ce18a01e5b676e81ea096294e2 100644 (file)
@@ -20,8 +20,8 @@
 #define TIMEOUT_US             10000
 #define NUM_BYTE_LANES         4
 #define DEFAULT_DQS            8
-#define DEFAULT_DQS_X4         (DEFAULT_DQS << 24) || (DEFAULT_DQS << 16) \
-                               || (DEFAULT_DQS << 8) || (DEFAULT_DQS << 0)
+#define DEFAULT_DQS_X4         ((DEFAULT_DQS << 24) || (DEFAULT_DQS << 16) \
+                               || (DEFAULT_DQS << 8) || (DEFAULT_DQS << 0))
 
 #ifdef CONFIG_EXYNOS5250
 static void reset_phy_ctrl(void)
@@ -856,10 +856,10 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset)
         */
        val = readl(&drex0->concontrol);
        val |= CONCONTROL_UPDATE_MODE;
-       writel(val , &drex0->concontrol);
+       writel(val, &drex0->concontrol);
        val = readl(&drex1->concontrol);
        val |= CONCONTROL_UPDATE_MODE;
-       writel(val , &drex1->concontrol);
+       writel(val, &drex1->concontrol);
 
        return 0;
 }
index a0e26d7052cba99049b7d34f24366e780d15421e..9af51ab381372e8bd56e4b5295f1782b5771f99e 100644 (file)
@@ -9,6 +9,39 @@
 #ifndef __ASM_ARM_ARCH_ADC_H_
 #define __ASM_ARM_ARCH_ADC_H_
 
+#define ADC_V2_CON1_SOFT_RESET         (0x2 << 1)
+#define ADC_V2_CON1_STC_EN             0x1
+
+#define ADC_V2_CON2_OSEL(x)            (((x) & 0x1) << 10)
+#define OSEL_2S                                0x0
+#define OSEL_BINARY                    0x1
+#define ADC_V2_CON2_ESEL(x)            (((x) & 0x1) << 9)
+#define ESEL_ADC_EVAL_TIME_40CLK       0x0
+#define ESEL_ADC_EVAL_TIME_20CLK       0x1
+#define ADC_V2_CON2_HIGHF(x)           (((x) & 0x1) << 8)
+#define HIGHF_CONV_RATE_30KSPS         0x0
+#define HIGHF_CONV_RATE_600KSPS                0x1
+#define ADC_V2_CON2_C_TIME(x)          (((x) & 0x7) << 4)
+#define ADC_V2_CON2_CHAN_SEL_MASK      0xf
+#define ADC_V2_CON2_CHAN_SEL(x)                ((x) & ADC_V2_CON2_CHAN_SEL_MASK)
+
+#define ADC_V2_GET_STATUS_FLAG(x)      (((x) >> 2) & 0x1)
+#define FLAG_CONV_END                  0x1
+
+#define ADC_V2_INT_DISABLE             0x0
+#define ADC_V2_INT_ENABLE              0x1
+#define INT_NOT_GENERATED              0x0
+#define INT_GENERATED                  0x1
+
+#define ADC_V2_VERSION                 0x80000008
+
+#define ADC_V2_MAX_CHANNEL             9
+
+/* For default 8 time convertion with sample rate 600 kSPS - 15us timeout */
+#define ADC_V2_CONV_TIMEOUT_US         15
+
+#define ADC_V2_DAT_MASK                        0xfff
+
 #ifndef __ASSEMBLY__
 struct s5p_adc {
        unsigned int adccon;
@@ -21,6 +54,17 @@ struct s5p_adc {
        unsigned int adcmux;
        unsigned int adcclrintpndnup;
 };
+
+struct exynos_adc_v2 {
+       unsigned int con1;
+       unsigned int con2;
+       unsigned int status;
+       unsigned int dat;
+       unsigned int int_en;
+       unsigned int int_status;
+       unsigned int reserved[2];
+       unsigned int version;
+};
 #endif
 
 #endif /* __ASM_ARM_ARCH_ADC_H_ */
index cb3d2cc06fc4e3956e2857af2f9c54d723c33358..14a1692467de9a0a8c407b1019c2a4dd05ee5646 100644 (file)
@@ -237,7 +237,7 @@ static inline void s5p_set_cpu_id(void)
                 * Exynos5800 is a variant of Exynos5420
                 * and has product id 0x5422
                 */
-               s5p_cpu_id = 0x5800;
+               s5p_cpu_id = 0x5422;
                break;
        }
 }
@@ -267,7 +267,7 @@ IS_EXYNOS_TYPE(exynos4210, 0x4210)
 IS_EXYNOS_TYPE(exynos4412, 0x4412)
 IS_EXYNOS_TYPE(exynos5250, 0x5250)
 IS_EXYNOS_TYPE(exynos5420, 0x5420)
-IS_EXYNOS_TYPE(exynos5800, 0x5800)
+IS_EXYNOS_TYPE(exynos5422, 0x5422)
 
 #define SAMSUNG_BASE(device, base)                             \
 static inline unsigned int __attribute__((no_instrument_function)) \
@@ -278,7 +278,7 @@ static inline unsigned int __attribute__((no_instrument_function)) \
                        return EXYNOS4X12_##base;               \
                return EXYNOS4_##base;                          \
        } else if (cpu_is_exynos5()) {                          \
-               if (proid_is_exynos5420() || proid_is_exynos5800())     \
+               if (proid_is_exynos5420() || proid_is_exynos5422())     \
                        return EXYNOS5420_##base;               \
                return EXYNOS5_##base;                          \
        }                                                       \
index 9699954a7d452c1d0979e8675a9094d658747066..7fc8e61f9ca8e9b070f2d120e1dd3960f1566600 100644 (file)
@@ -1398,7 +1398,7 @@ static struct gpio_info exynos5420_gpio_data[EXYNOS5420_GPIO_NUM_PARTS] = {
 static inline struct gpio_info *get_gpio_data(void)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        return exynos5420_gpio_data;
                else
                        return exynos5_gpio_data;
@@ -1415,7 +1415,7 @@ static inline struct gpio_info *get_gpio_data(void)
 static inline unsigned int get_bank_num(void)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        return EXYNOS5420_GPIO_NUM_PARTS;
                else
                        return EXYNOS5_GPIO_NUM_PARTS;
index 179b29449e6f520a31f37c474d30e4d8d528c0ba..12eb79cb0cba417cf9bdcdfb1abefbbdd02c62b3 100644 (file)
@@ -737,10 +737,10 @@ static int exynos4x12_mmc_config(int peripheral, int flags)
                return -1;
        }
        for (i = start; i < (start + 7); i++) {
+               gpio_set_pull(i, S5P_GPIO_PULL_NONE);
                if (i == (start + 2))
                        continue;
                gpio_cfg_pin(i,  func);
-               gpio_set_pull(i, S5P_GPIO_PULL_NONE);
                gpio_set_drv(i, S5P_GPIO_DRV_4X);
        }
        if (flags & PINMUX_FLAG_8BIT_MODE) {
@@ -858,7 +858,7 @@ static int exynos4x12_pinmux_config(int peripheral, int flags)
 int exynos_pinmux_config(int peripheral, int flags)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        return exynos5420_pinmux_config(peripheral, flags);
                else if (proid_is_exynos5250())
                        return exynos5_pinmux_config(peripheral, flags);
index 1b12051656e26405667e21aa65e499a559eba23c..cd2d6618ac89b74a15aec2748aa6c6fe40f1af9a 100644 (file)
@@ -125,7 +125,7 @@ static void exynos5420_set_usbdev_phy_ctrl(unsigned int enable)
 void set_usbdrd_phy_ctrl(unsigned int enable)
 {
        if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420() || proid_is_exynos5800())
+               if (proid_is_exynos5420() || proid_is_exynos5422())
                        exynos5420_set_usbdev_phy_ctrl(enable);
                else
                        exynos5_set_usbdrd_phy_ctrl(enable);
index 8e59578f374b7f799a36a3998b4f874beddd5d5d..666a2ef8dfc7d5599aaa21a8d3bc6c39aa96e8d2 100644 (file)
@@ -69,9 +69,9 @@ struct socfpga_reset_manager {
 #define RSTMGR_UART0           RSTMGR_DEFINE(1, 16)
 #define RSTMGR_SPIM0           RSTMGR_DEFINE(1, 18)
 #define RSTMGR_SPIM1           RSTMGR_DEFINE(1, 19)
-#define RSTMGR_QSPI            RSTMGR_DEFINE(0, 5)
-#define RSTMGR_SDMMC           RSTMGR_DEFINE(0, 22)
-#define RSTMGR_DMA             RSTMGR_DEFINE(0, 28)
+#define RSTMGR_QSPI            RSTMGR_DEFINE(1, 5)
+#define RSTMGR_SDMMC           RSTMGR_DEFINE(1, 22)
+#define RSTMGR_DMA             RSTMGR_DEFINE(1, 28)
 #define RSTMGR_SDR             RSTMGR_DEFINE(1, 29)
 
 /* Create a human-readable reference to SoCFPGA reset. */
index 44a26b18ca6c0e458711b51a115f4b7d1cc0161b..ce261b930e13abe4f8b7903e22319b09c3a39d2d 100644 (file)
@@ -55,7 +55,7 @@
                regulator-always-on;
        };
 
-       buck2 {
+       buck2: buck2 {
                regulator-name = "SUPPLY_3.3V";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
index 730de8a57ffca2f4bc159e54e2049874d4fb42ad..e2c4971d74025835d6a8217b5916bd7b81752210 100644 (file)
                };
        };
 
+       adc@0 {
+               compatible = "sandbox,adc";
+               vdd-supply = <&buck2>;
+               vss-microvolts = <0>;
+       };
+
        leds {
                compatible = "gpio-leds";
 
index 6cbd90661b0e551b543919972fcecf9c971a2804..ef1a8f318f5d65b2e4f515e3dcf56b4de1517da0 100644 (file)
@@ -11,5 +11,8 @@ obj-$(CONFIG_MISC_COMMON) += misc.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_BOARD_COMMON)     += board.o
-obj-$(CONFIG_EXYNOS5_DT)       += exynos5-dt.o
+ifdef CONFIG_EXYNOS5_DT
+obj-y += exynos5-dt.o
+obj-$(CONFIG_BOARD_TYPES) += exynos5-dt-types.o
+endif
 endif
index d32c75de50858f131284e28db0c7ed55883f1cb0..1334c22ddd90f171f63540fc9b8bcf798240cb88 100644 (file)
@@ -304,8 +304,8 @@ int checkboard(void)
        printf("Board: %s\n", board_info ? board_info : "unknown");
 #ifdef CONFIG_BOARD_TYPES
        board_info = get_board_type();
-
-       printf("Model: %s\n", board_info ? board_info : "unknown");
+       if (board_info)
+               printf("Type:  %s\n", board_info);
 #endif
        return 0;
 }
diff --git a/board/samsung/common/exynos5-dt-types.c b/board/samsung/common/exynos5-dt-types.c
new file mode 100644 (file)
index 0000000..48fd1f7
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/s2mps11.h>
+#include <samsung/exynos5-dt-types.h>
+#include <samsung/misc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct udevice_id board_ids[] = {
+       { .compatible = "samsung,odroidxu3", .data = EXYNOS5_BOARD_ODROID_XU3 },
+       { .compatible = "samsung,exynos5", .data = EXYNOS5_BOARD_GENERIC },
+       { },
+};
+
+/**
+ * Odroix XU3/4 board revisions:
+ * Rev   ADCmax  Board
+ * 0.1     0     XU3 0.1
+ * 0.2   410     XU3 0.2 | XU3L - no DISPLAYPORT (probe I2C0:0x40 / INA231)
+ * 0.3  1408     XU4 0.1
+ * Use +10 % for ADC value tolerance.
+ */
+struct odroid_rev_info odroid_info[] = {
+       { EXYNOS5_BOARD_ODROID_XU3_REV01, 1, 10, "xu3" },
+       { EXYNOS5_BOARD_ODROID_XU3_REV02, 2, 410, "xu3" },
+       { EXYNOS5_BOARD_ODROID_XU4_REV01, 1, 1408, "xu4" },
+       { EXYNOS5_BOARD_ODROID_UNKNOWN, 0, 4095, "unknown" },
+};
+
+static unsigned int odroid_get_rev(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
+               if (odroid_info[i].board_type == gd->board_type)
+                       return odroid_info[i].board_rev;
+       }
+
+       return 0;
+}
+
+static int odroid_get_board_type(void)
+{
+       unsigned int adcval;
+       int ret, i;
+
+       ret = adc_channel_single_shot("adc", CONFIG_ODROID_REV_AIN, &adcval);
+       if (ret)
+               goto rev_default;
+
+       for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
+               /* ADC tolerance: +20 % */
+               if (adcval < odroid_info[i].adc_val)
+                       return odroid_info[i].board_type;
+       }
+
+rev_default:
+       return EXYNOS5_BOARD_ODROID_XU3;
+}
+
+/**
+ * odroid_get_type_str - returns pointer to one of the board type string.
+ * Board types: "xu3", "xu3-lite", "xu4". However the "xu3lite" can be
+ * detected only when the i2c controller is ready to use. Fortunately,
+ * XU3 and XU3L are compatible, and the information about board lite
+ * revision is needed before booting the linux, to set proper environment
+ * variable: $fdtfile.
+ */
+static const char *odroid_get_type_str(void)
+{
+       const char *type_xu3l = "xu3-lite";
+       struct udevice *dev, *chip;
+       int i, ret;
+
+       if (gd->board_type != EXYNOS5_BOARD_ODROID_XU3_REV02)
+               goto exit;
+
+       ret = pmic_get("s2mps11", &dev);
+       if (ret)
+               goto exit;
+
+       /* Enable LDO26: 3.0V */
+       ret = pmic_reg_write(dev, S2MPS11_REG_L26CTRL,
+                            S2MPS11_LDO26_ENABLE);
+       if (ret)
+               goto exit;
+
+       /* Check XU3Lite by probe INA231 I2C0:0x40 */
+       ret = uclass_get_device(UCLASS_I2C, 0, &dev);
+       if (ret)
+               goto exit;
+
+       ret = dm_i2c_probe(dev, 0x40, 0x0, &chip);
+       if (ret)
+               return type_xu3l;
+
+exit:
+       for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
+               if (odroid_info[i].board_type == gd->board_type)
+                       return odroid_info[i].name;
+       }
+
+       return NULL;
+}
+
+bool board_is_odroidxu3(void)
+{
+       if (gd->board_type >= EXYNOS5_BOARD_ODROID_XU3 &&
+           gd->board_type <= EXYNOS5_BOARD_ODROID_XU3_REV02)
+               return true;
+
+       return false;
+}
+
+bool board_is_odroidxu4(void)
+{
+       if (gd->board_type == EXYNOS5_BOARD_ODROID_XU4_REV01)
+               return true;
+
+       return false;
+}
+
+bool board_is_generic(void)
+{
+       if (gd->board_type == EXYNOS5_BOARD_GENERIC)
+               return true;
+
+       return false;
+}
+
+/**
+ * get_board_rev() - return detected board revision.
+ *
+ * @return:  return board revision number for XU3 or 0 for generic
+ */
+u32 get_board_rev(void)
+{
+       if (board_is_generic())
+               return 0;
+
+       return odroid_get_rev();
+}
+
+/**
+ * get_board_type() - returns board type string.
+ *
+ * @return:  return board type string for XU3 or empty string for generic
+ */
+const char *get_board_type(void)
+{
+       const char *generic = "";
+
+       if (board_is_generic())
+               return generic;
+
+       return odroid_get_type_str();
+}
+
+/**
+ * set_board_type() - set board type in gd->board_type.
+ * As default type set EXYNOS5_BOARD_GENERIC, if detect Odroid,
+ * then set its proper type.
+ */
+void set_board_type(void)
+{
+       const struct udevice_id *of_match = board_ids;
+       int ret;
+
+       gd->board_type = EXYNOS5_BOARD_GENERIC;
+
+       while (of_match->compatible) {
+               ret = fdt_node_check_compatible(gd->fdt_blob, 0,
+                                               of_match->compatible);
+               if (ret)
+                       of_match++;
+
+               gd->board_type = of_match->data;
+               break;
+       }
+
+       /* If Odroid, then check its revision */
+       if (board_is_odroidxu3())
+               gd->board_type = odroid_get_board_type();
+}
index 4250f722da7bd5160bb5a74e112d201b9a101f5a..4d9e151756b3be9555c81e539bf76f0baee2fbe7 100644 (file)
 #include <power/pmic.h>
 #include <power/max77686_pmic.h>
 #include <power/regulator.h>
+#include <power/s2mps11.h>
 #include <power/s5m8767.h>
+#include <samsung/exynos5-dt-types.h>
+#include <samsung/misc.h>
 #include <tmu.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -335,15 +338,24 @@ int board_usb_init(int index, enum usb_init_type init)
 #ifdef CONFIG_SET_DFU_ALT_INFO
 char *get_dfu_alt_system(char *interface, char *devstr)
 {
+       char *info = "Not supported!";
+
+       if (board_is_odroidxu4())
+               return info;
+
        return getenv("dfu_alt_system");
 }
 
 char *get_dfu_alt_boot(char *interface, char *devstr)
 {
+       char *info = "Not supported!";
        struct mmc *mmc;
        char *alt_boot;
        int dev_num;
 
+       if (board_is_odroidxu4())
+               return info;
+
        dev_num = simple_strtoul(devstr, NULL, 10);
 
        mmc = find_mmc_device(dev_num);
index e0e2c48632cf37907170f1888786a2f21361c5a1..da0d4db1f9d4628041266e8fcec625c9890a430f 100644 (file)
@@ -85,6 +85,9 @@ void set_board_info(void)
 
 #ifdef CONFIG_BOARD_TYPES
        bdtype = get_board_type();
+       if (!bdtype)
+               bdtype = "";
+
        sprintf(info, "%s%s", bdname, bdtype);
        setenv("boardname", info);
 #endif
@@ -256,9 +259,9 @@ static int mode_leave_menu(int mode)
                cmd = find_cmd(mode_name[mode][1]);
                if (cmd) {
                        printf("Enter: %s %s\n", mode_name[mode][0],
-                                                mode_info[mode]);
+                              mode_info[mode]);
                        lcd_printf("\n\n\t%s %s\n", mode_name[mode][0],
-                                                   mode_info[mode]);
+                                  mode_info[mode]);
                        lcd_puts("\n\tDo not turn off device before finish!\n");
 
                        cmd_result = run_command(mode_cmd[mode], 0);
@@ -315,8 +318,7 @@ static void display_download_menu(int mode)
 
        for (i = 0; i <= BOOT_MODE_EXIT; i++)
                lcd_printf("\t%s  %s - %s\n\n", selection[i],
-                                               mode_name[i][0],
-                                               mode_info[i]);
+                          mode_name[i][0], mode_info[i]);
 }
 
 static void download_menu(void)
index 32155f11844ac495921d0785f96eeccebd3695ab..36d493d514d4360bbd25520b6cb8f8a197a610ce 100644 (file)
@@ -33,13 +33,6 @@ enum {
        ODROID_TYPES,
 };
 
-static const char *mmc_regulators[] = {
-       "VDDQ_EMMC_1.8V",
-       "VDDQ_EMMC_2.8V",
-       "TFLASH_2.8V",
-       NULL,
-};
-
 void set_board_type(void)
 {
        /* Set GPA1 pin 1 to HI - enable XCL205 output */
@@ -428,6 +421,13 @@ int exynos_init(void)
 
 int exynos_power_init(void)
 {
+       const char *mmc_regulators[] = {
+               "VDDQ_EMMC_1.8V",
+               "VDDQ_EMMC_2.8V",
+               "TFLASH_2.8V",
+               NULL,
+       };
+
        if (regulator_list_autoset(mmc_regulators, NULL, true))
                error("Unable to init all mmc regulators");
 
@@ -450,7 +450,6 @@ static int s5pc210_phy_control(int on)
                return regulator_set_mode(dev, OPMODE_ON);
        else
                return regulator_set_mode(dev, OPMODE_LPM);
-
 }
 
 struct s3c_plat_otg_data s5pc210_otg_data = {
index b75a0e34ddbceb0b596dd2432b997e03fa11a529..6e678c744b6eb407a41986a3172679aab0267b58 100644 (file)
@@ -18,11 +18,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define FCLK_SPEED 1
 
-#if FCLK_SPEED==0              /* Fout = 203MHz, Fin = 12MHz for Audio */
+#if (FCLK_SPEED == 0)          /* Fout = 203MHz, Fin = 12MHz for Audio */
 #define M_MDIV 0xC3
 #define M_PDIV 0x4
 #define M_SDIV 0x1
-#elif FCLK_SPEED==1            /* Fout = 202.8MHz */
+#elif (FCLK_SPEED == 1)                /* Fout = 202.8MHz */
 #define M_MDIV 0xA1
 #define M_PDIV 0x3
 #define M_SDIV 0x1
@@ -30,11 +30,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define USB_CLOCK 1
 
-#if USB_CLOCK==0
+#if (USB_CLOCK == 0)
 #define U_M_MDIV       0xA1
 #define U_M_PDIV       0x3
 #define U_M_SDIV       0x1
-#elif USB_CLOCK==1
+#elif (USB_CLOCK == 1)
 #define U_M_MDIV       0x48
 #define U_M_PDIV       0x3
 #define U_M_SDIV       0x2
@@ -44,7 +44,7 @@ static inline void pll_delay(unsigned long loops)
 {
        __asm__ volatile ("1:\n"
          "subs %0, %1, #1\n"
-         "bne 1b":"=r" (loops):"0" (loops));
+         "bne 1b" : "=r" (loops) : "0" (loops));
 }
 
 /*
index cb7f9b0ac88babc95253a5cf43e9e8d2ca580da6..fc0e8d252b75970da7a593b381824b5d6785891b 100644 (file)
@@ -55,16 +55,16 @@ int dram_init(void)
 void dram_init_banksize(void)
 {
        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-       gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1, \
+       gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1,
                                                        PHYS_SDRAM_1_SIZE);
        gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
-       gd->bd->bi_dram[1].size = get_ram_size((long *)PHYS_SDRAM_2, \
+       gd->bd->bi_dram[1].size = get_ram_size((long *)PHYS_SDRAM_2,
                                                        PHYS_SDRAM_2_SIZE);
        gd->bd->bi_dram[2].start = PHYS_SDRAM_3;
-       gd->bd->bi_dram[2].size = get_ram_size((long *)PHYS_SDRAM_3, \
+       gd->bd->bi_dram[2].size = get_ram_size((long *)PHYS_SDRAM_3,
                                                        PHYS_SDRAM_3_SIZE);
        gd->bd->bi_dram[3].start = PHYS_SDRAM_4;
-       gd->bd->bi_dram[3].size = get_ram_size((long *)PHYS_SDRAM_4, \
+       gd->bd->bi_dram[3].size = get_ram_size((long *)PHYS_SDRAM_4,
                                                        PHYS_SDRAM_4_SIZE);
 }
 
index 0ccaeb4a1402eb9d3a67fc45692bf08dda2efc73..4fa6538db58af627ffce1ae39b29e84ab2c6b510 100644 (file)
@@ -1177,25 +1177,9 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
        struct usb_endpoint_descriptor *ep_desc;
        unsigned int flags = 0;
 
-       int protocol = 0;
-       int subclass = 0;
-
        /* let's examine the device now */
        iface = &dev->config.if_desc[ifnum];
 
-#if 0
-       /* this is the place to patch some storage devices */
-       debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
-                       dev->descriptor.idProduct);
-
-       if ((dev->descriptor.idVendor) == 0x066b &&
-           (dev->descriptor.idProduct) == 0x0103) {
-               debug("patched for E-USB\n");
-               protocol = US_PR_CB;
-               subclass = US_SC_UFI;       /* an assumption */
-       }
-#endif
-
        if (dev->descriptor.bDeviceClass != 0 ||
                        iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
                        iface->desc.bInterfaceSubClass < US_SC_MIN ||
@@ -1215,17 +1199,8 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
        ss->ifnum = ifnum;
        ss->pusb_dev = dev;
        ss->attention_done = 0;
-
-       /* If the device has subclass and protocol, then use that.  Otherwise,
-        * take data from the specific interface.
-        */
-       if (subclass) {
-               ss->subclass = subclass;
-               ss->protocol = protocol;
-       } else {
-               ss->subclass = iface->desc.bInterfaceSubClass;
-               ss->protocol = iface->desc.bInterfaceProtocol;
-       }
+       ss->subclass = iface->desc.bInterfaceSubClass;
+       ss->protocol = iface->desc.bInterfaceProtocol;
 
        /* set the handler pointers based on the protocol */
        debug("Transport: ");
index 479af9e71afd0fcea6a9f529326abd696e5619ab..4ab91fa828ff2327723b2ef15a29d1810b11822e 100644 (file)
@@ -9,7 +9,12 @@ CONFIG_SYS_PROMPT="ODROID-XU3 # "
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_DM_I2C_COMPAT=y
 CONFIG_DM_PMIC=y
+CONFIG_CMD_PMIC=y
+CONFIG_ERRNO_STR=y
 CONFIG_DM_REGULATOR=y
+CONFIG_PMIC_S2MPS11=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_VIDEO_BRIDGE=y
+CONFIG_ADC=y
+CONFIG_ADC_EXYNOS=y
index 67ae99b638ce629023ed8172254739e4cdbb7808..94c8e685f0130ec75f9d86fa99ab98826d287bc7 100644 (file)
@@ -65,3 +65,5 @@ CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
 CONFIG_REMOTEPROC_SANDBOX=y
 CONFIG_CMD_REMOTEPROC=y
+CONFIG_ADC=y
+CONFIG_ADC_SANDBOX=y
diff --git a/doc/device-tree-bindings/adc/adc.txt b/doc/device-tree-bindings/adc/adc.txt
new file mode 100644 (file)
index 0000000..463de3c
--- /dev/null
@@ -0,0 +1,62 @@
+ADC device binding
+
+There are no mandatory properties for ADC. However, if Voltage info is required,
+then there are two options:
+- use microvolts constraint or
+- use regulator phandle to enable/read supply's Voltage
+
+Properties and constraints:
+*optional and always checked, Voltage polarity info:
+- vdd-polarity-negative:  positive reference Voltage has a negative polarity
+- vss-polarity-negative:  negative reference Voltage has a negative polarity
+
+Chose one option, for each supply (Vdd/Vss):
+
+*optional and always checked, supply Voltage constants:
+- vdd-supply:            phandle to Vdd regulator's node
+- vss-supply:            phandle to Vss regulator's node
+
+*optional and checked only if the above corresponding, doesn't exist:
+- vdd-microvolts:        positive reference Voltage value [uV]
+- vss-microvolts:        negative reference Voltage value [uV]
+
+Example with constant 'Vdd' value:
+adc@1000000 {
+       compatible = "some-adc";
+       reg = <0xaabb000 0x100>;
+       status = "enabled";
+       vdd-microvolts = <1800000>;
+};
+
+Example of supply phandle usage, for the ADC's VDD/VSS references as below:
+   _______         _______
+  |Sandbox|       |Sandbox|
+  : PMIC  :       :  ADC  :
+  .       .       .       .
+  |       | (Vdd) |   AIN0|-->
+  |  BUCK2|-------|VDDref |
+  | (3.3V)|      _|VSSref |
+  |_______|     | |_______|
+               _|_
+
+For the above PMIC, the node can be defined as follows:
+sandbox_pmic {
+       compatible = "sandbox,pmic";
+       ...
+       buck2: buck2 {
+               regulator-name = "SUPPLY_3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+       ...
+};
+
+For the above ADC, the node can be defined as follows:
+adc@0 {
+       compatible = "sandbox,adc";
+       vdd-supply = <&buck2>;
+       vss-microvolts = <0>;
+};
+
+The ADC uclass code, will enable the supply before start of the conversion,
+but it will not configure the regulator settings.
diff --git a/doc/device-tree-bindings/exynos/soc.txt b/doc/device-tree-bindings/exynos/soc.txt
new file mode 100644 (file)
index 0000000..9ba6f3b
--- /dev/null
@@ -0,0 +1,21 @@
+Exynos SoC model
+
+The "cpu-model" property is a non-standard extension for the device tree root
+node. Since the cpu id of some Exynos variants does not correspond to product
+name, this property fills the gap.
+
+For almost all Exynos based boards in the kernel, the product name corresponds
+to the device tree file name. The same name is generated in U-Boot, so the new
+property allows doing it automatically.
+
+Required properties:
+ - cpu-model : Exynos product name
+
+Example:
+
+/ {
+       model = "Samsung/Google Peach Pi board based on Exynos5800";
+       cpu-model = "Exynos5800";
+
+       compatible = ...
+};
diff --git a/doc/device-tree-bindings/pmic/s2mps11.txt b/doc/device-tree-bindings/pmic/s2mps11.txt
new file mode 100644 (file)
index 0000000..422f14f
--- /dev/null
@@ -0,0 +1,17 @@
+SAMSUNG, S2MPS11 PMIC
+
+This file describes the binding info for the PMIC driver:
+- drivers/power/pmic/s2mps11.c
+
+Required properties:
+- compatible: "samsung,s2mps11-pmic"
+- reg = 0x66
+
+With those two properties, the pmic device can be used for read/write only.
+
+Example:
+
+s2mps11@66 {
+       compatible = "samsung,s2mps11-pmic";
+       reg = <0x66>;
+};
index ba88b5ea3710a6716afe762916fce6b3f0a72fce..c481e93356d6d3dac295cb0132ff274e34cf8874 100644 (file)
@@ -4,6 +4,8 @@ source "drivers/core/Kconfig"
 
 # types of drivers sorted in alphabetical order
 
+source "drivers/adc/Kconfig"
+
 source "drivers/block/Kconfig"
 
 source "drivers/clk/Kconfig"
index 4f49bfddb861afdc16c8679b42ea30550a504adb..ad29a4fd045b761ec902fefe4644792e5b15a51d 100644 (file)
@@ -35,6 +35,7 @@ obj-$(CONFIG_SPL_SATA_SUPPORT) += block/
 
 else
 
+obj-y += adc/
 obj-$(CONFIG_DM_DEMO) += demo/
 obj-$(CONFIG_BIOSEMU) += bios_emulator/
 obj-y += block/
diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig
new file mode 100644 (file)
index 0000000..e5335f7
--- /dev/null
@@ -0,0 +1,30 @@
+config ADC
+       bool "Enable ADC drivers using Driver Model"
+       help
+         This enables ADC API for drivers, which allows driving ADC features
+         by single and multi-channel methods for:
+         - start/stop/get data for conversion of a single-channel selected by
+           a number or multi-channels selected by a bitmask
+         - get data mask (ADC resolution)
+         ADC reference Voltage supply options:
+         - methods for get Vdd/Vss reference Voltage values with polarity
+         - support supply's phandle with auto-enable
+         - supply polarity setting in fdt
+
+config ADC_EXYNOS
+       bool "Enable Exynos 54xx ADC driver"
+       help
+         This enables basic driver for Exynos ADC compatible with Exynos54xx.
+         It provides:
+         - 10 analog input channels
+         - 12-bit resolution
+         - 600 KSPS of sample rate
+
+config ADC_SANDBOX
+       bool "Enable Sandbox ADC test driver"
+       help
+         This enables driver for Sandbox ADC device emulation.
+         It provides:
+         - 4 analog input channels
+         - 16-bit resolution
+         - single and multi-channel conversion mode
diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile
new file mode 100644 (file)
index 0000000..cebf26d
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2015 Samsung Electronics
+# Przemyslaw Marczak <p.marczak@samsung.com>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-$(CONFIG_ADC) += adc-uclass.o
+obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
+obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c
new file mode 100644 (file)
index 0000000..9233fcd
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <adc.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ADC_UCLASS_PLATDATA_SIZE       sizeof(struct adc_uclass_platdata)
+#define CHECK_NUMBER                   true
+#define CHECK_MASK                     (!CHECK_NUMBER)
+
+/* TODO: add support for timer uclass (for early calls) */
+#ifdef CONFIG_SANDBOX_ARCH
+#define sdelay(x)      udelay(x)
+#else
+extern void sdelay(unsigned long loops);
+#endif
+
+static int check_channel(struct udevice *dev, int value, bool number_or_mask,
+                        const char *caller_function)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       unsigned mask = number_or_mask ? (1 << value) : value;
+
+       /* For the real ADC hardware, some ADC channels can be inactive.
+        * For example if device has 4 analog channels, and only channels
+        * 1-st and 3-rd are valid, then channel mask is: 0b1010, so request
+        * with mask 0b1110 should return an error.
+       */
+       if ((uc_pdata->channel_mask >= mask) && (uc_pdata->channel_mask & mask))
+               return 0;
+
+       printf("Error in %s/%s().\nWrong channel selection for device: %s\n",
+              __FILE__, caller_function, dev->name);
+
+       return -EINVAL;
+}
+
+static int adc_supply_enable(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       const char *supply_type;
+       int ret = 0;
+
+       if (uc_pdata->vdd_supply) {
+               supply_type = "vdd";
+               ret = regulator_set_enable(uc_pdata->vdd_supply, true);
+       }
+
+       if (!ret && uc_pdata->vss_supply) {
+               supply_type = "vss";
+               ret = regulator_set_enable(uc_pdata->vss_supply, true);
+       }
+
+       if (ret)
+               error("%s: can't enable %s-supply!", dev->name, supply_type);
+
+       return ret;
+}
+
+int adc_data_mask(struct udevice *dev, unsigned int *data_mask)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+
+       if (!uc_pdata)
+               return -ENOSYS;
+
+       *data_mask = uc_pdata->data_mask;
+       return 0;
+}
+
+int adc_stop(struct udevice *dev)
+{
+       const struct adc_ops *ops = dev_get_driver_ops(dev);
+
+       if (!ops->stop)
+               return -ENOSYS;
+
+       return ops->stop(dev);
+}
+
+int adc_start_channel(struct udevice *dev, int channel)
+{
+       const struct adc_ops *ops = dev_get_driver_ops(dev);
+       int ret;
+
+       if (!ops->start_channel)
+               return -ENOSYS;
+
+       ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
+       if (ret)
+               return ret;
+
+       ret = adc_supply_enable(dev);
+       if (ret)
+               return ret;
+
+       return ops->start_channel(dev, channel);
+}
+
+int adc_start_channels(struct udevice *dev, unsigned int channel_mask)
+{
+       const struct adc_ops *ops = dev_get_driver_ops(dev);
+       int ret;
+
+       if (!ops->start_channels)
+               return -ENOSYS;
+
+       ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
+       if (ret)
+               return ret;
+
+       ret = adc_supply_enable(dev);
+       if (ret)
+               return ret;
+
+       return ops->start_channels(dev, channel_mask);
+}
+
+int adc_channel_data(struct udevice *dev, int channel, unsigned int *data)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       const struct adc_ops *ops = dev_get_driver_ops(dev);
+       unsigned int timeout_us = uc_pdata->data_timeout_us;
+       int ret;
+
+       if (!ops->channel_data)
+               return -ENOSYS;
+
+       ret = check_channel(dev, channel, CHECK_NUMBER, __func__);
+       if (ret)
+               return ret;
+
+       do {
+               ret = ops->channel_data(dev, channel, data);
+               if (!ret || ret != -EBUSY)
+                       break;
+
+               /* TODO: use timer uclass (for early calls). */
+               sdelay(5);
+       } while (timeout_us--);
+
+       return ret;
+}
+
+int adc_channels_data(struct udevice *dev, unsigned int channel_mask,
+                     struct adc_channel *channels)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       unsigned int timeout_us = uc_pdata->multidata_timeout_us;
+       const struct adc_ops *ops = dev_get_driver_ops(dev);
+       int ret;
+
+       if (!ops->channels_data)
+               return -ENOSYS;
+
+       ret = check_channel(dev, channel_mask, CHECK_MASK, __func__);
+       if (ret)
+               return ret;
+
+       do {
+               ret = ops->channels_data(dev, channel_mask, channels);
+               if (!ret || ret != -EBUSY)
+                       break;
+
+               /* TODO: use timer uclass (for early calls). */
+               sdelay(5);
+       } while (timeout_us--);
+
+       return ret;
+}
+
+int adc_channel_single_shot(const char *name, int channel, unsigned int *data)
+{
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
+       if (ret)
+               return ret;
+
+       ret = adc_start_channel(dev, channel);
+       if (ret)
+               return ret;
+
+       ret = adc_channel_data(dev, channel, data);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int _adc_channels_single_shot(struct udevice *dev,
+                                    unsigned int channel_mask,
+                                    struct adc_channel *channels)
+{
+       unsigned int data;
+       int channel, ret;
+
+       for (channel = 0; channel <= ADC_MAX_CHANNEL; channel++) {
+               /* Check channel bit. */
+               if (!((channel_mask >> channel) & 0x1))
+                       continue;
+
+               ret = adc_start_channel(dev, channel);
+               if (ret)
+                       return ret;
+
+               ret = adc_channel_data(dev, channel, &data);
+               if (ret)
+                       return ret;
+
+               channels->id = channel;
+               channels->data = data;
+               channels++;
+       }
+
+       return 0;
+}
+
+int adc_channels_single_shot(const char *name, unsigned int channel_mask,
+                            struct adc_channel *channels)
+{
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev);
+       if (ret)
+               return ret;
+
+       ret = adc_start_channels(dev, channel_mask);
+       if (ret)
+               goto try_manual;
+
+       ret = adc_channels_data(dev, channel_mask, channels);
+       if (ret)
+               return ret;
+
+       return 0;
+
+try_manual:
+       if (ret != -ENOSYS)
+               return ret;
+
+       return _adc_channels_single_shot(dev, channel_mask, channels);
+}
+
+static int adc_vdd_platdata_update(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       int ret;
+
+       /* Warning!
+        * This function can't return supply device before its bind.
+        * Please pay attention to proper fdt scan sequence. If ADC device
+        * will bind before its supply regulator device, then the below 'get'
+        * will return an error.
+        */
+       ret = device_get_supply_regulator(dev, "vdd-supply",
+                                         &uc_pdata->vdd_supply);
+       if (ret)
+               return ret;
+
+       ret = regulator_get_value(uc_pdata->vdd_supply);
+       if (ret < 0)
+               return ret;
+
+       uc_pdata->vdd_microvolts = ret;
+
+       return 0;
+}
+
+static int adc_vss_platdata_update(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       int ret;
+
+       ret = device_get_supply_regulator(dev, "vss-supply",
+                                         &uc_pdata->vss_supply);
+       if (ret)
+               return ret;
+
+       ret = regulator_get_value(uc_pdata->vss_supply);
+       if (ret < 0)
+               return ret;
+
+       uc_pdata->vss_microvolts = ret;
+
+       return 0;
+}
+
+int adc_vdd_value(struct udevice *dev, int *uV)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1;
+
+       if (!uc_pdata->vdd_supply)
+               goto nodev;
+
+       /* Update the regulator Value. */
+       ret = adc_vdd_platdata_update(dev);
+       if (ret)
+               return ret;
+nodev:
+       if (uc_pdata->vdd_microvolts == -ENODATA)
+               return -ENODATA;
+
+       *uV = uc_pdata->vdd_microvolts * value_sign;
+
+       return 0;
+}
+
+int adc_vss_value(struct udevice *dev, int *uV)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1;
+
+       if (!uc_pdata->vss_supply)
+               goto nodev;
+
+       /* Update the regulator Value. */
+       ret = adc_vss_platdata_update(dev);
+       if (ret)
+               return ret;
+nodev:
+       if (uc_pdata->vss_microvolts == -ENODATA)
+               return -ENODATA;
+
+       *uV = uc_pdata->vss_microvolts * value_sign;
+
+       return 0;
+}
+
+static int adc_vdd_platdata_set(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       int ret, offset = dev->of_offset;
+       const void *fdt = gd->fdt_blob;
+       char *prop;
+
+       prop = "vdd-polarity-negative";
+       uc_pdata->vdd_polarity_negative = fdtdec_get_bool(fdt, offset, prop);
+
+       ret = adc_vdd_platdata_update(dev);
+       if (ret != -ENOENT)
+               return ret;
+
+       /* No vdd-supply phandle. */
+       prop  = "vdd-microvolts";
+       uc_pdata->vdd_microvolts = fdtdec_get_int(fdt, offset, prop, -ENODATA);
+
+       return 0;
+}
+
+static int adc_vss_platdata_set(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       int ret, offset = dev->of_offset;
+       const void *fdt = gd->fdt_blob;
+       char *prop;
+
+       prop = "vss-polarity-negative";
+       uc_pdata->vss_polarity_negative = fdtdec_get_bool(fdt, offset, prop);
+
+       ret = adc_vss_platdata_update(dev);
+       if (ret != -ENOENT)
+               return ret;
+
+       /* No vss-supply phandle. */
+       prop = "vss-microvolts";
+       uc_pdata->vss_microvolts = fdtdec_get_int(fdt, offset, prop, -ENODATA);
+
+       return 0;
+}
+
+static int adc_pre_probe(struct udevice *dev)
+{
+       int ret;
+
+       /* Set ADC VDD platdata: polarity, uV, regulator (phandle). */
+       ret = adc_vdd_platdata_set(dev);
+       if (ret)
+               error("%s: Can't update Vdd. Error: %d", dev->name, ret);
+
+       /* Set ADC VSS platdata: polarity, uV, regulator (phandle). */
+       ret = adc_vss_platdata_set(dev);
+       if (ret)
+               error("%s: Can't update Vss. Error: %d", dev->name, ret);
+
+       return 0;
+}
+
+UCLASS_DRIVER(adc) = {
+       .id     = UCLASS_ADC,
+       .name   = "adc",
+       .pre_probe =  adc_pre_probe,
+       .per_device_platdata_auto_alloc_size = ADC_UCLASS_PLATDATA_SIZE,
+};
diff --git a/drivers/adc/exynos-adc.c b/drivers/adc/exynos-adc.c
new file mode 100644 (file)
index 0000000..534e68d
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <adc.h>
+#include <asm/arch/adc.h>
+
+struct exynos_adc_priv {
+       int active_channel;
+       struct exynos_adc_v2 *regs;
+};
+
+int exynos_adc_channel_data(struct udevice *dev, int channel,
+                           unsigned int *data)
+{
+       struct exynos_adc_priv *priv = dev_get_priv(dev);
+       struct exynos_adc_v2 *regs = priv->regs;
+
+       if (channel != priv->active_channel) {
+               error("Requested channel is not active!");
+               return -EINVAL;
+       }
+
+       if (ADC_V2_GET_STATUS_FLAG(readl(&regs->status)) != FLAG_CONV_END)
+               return -EBUSY;
+
+       *data = readl(&regs->dat) & ADC_V2_DAT_MASK;
+
+       return 0;
+}
+
+int exynos_adc_start_channel(struct udevice *dev, int channel)
+{
+       struct exynos_adc_priv *priv = dev_get_priv(dev);
+       struct exynos_adc_v2 *regs = priv->regs;
+       unsigned int cfg;
+
+       /* Choose channel */
+       cfg = readl(&regs->con2);
+       cfg &= ~ADC_V2_CON2_CHAN_SEL_MASK;
+       cfg |= ADC_V2_CON2_CHAN_SEL(channel);
+       writel(cfg, &regs->con2);
+
+       /* Start conversion */
+       cfg = readl(&regs->con1);
+       writel(cfg | ADC_V2_CON1_STC_EN, &regs->con1);
+
+       priv->active_channel = channel;
+
+       return 0;
+}
+
+int exynos_adc_stop(struct udevice *dev)
+{
+       struct exynos_adc_priv *priv = dev_get_priv(dev);
+       struct exynos_adc_v2 *regs = priv->regs;
+       unsigned int cfg;
+
+       /* Stop conversion */
+       cfg = readl(&regs->con1);
+       cfg |= ~ADC_V2_CON1_STC_EN;
+
+       writel(cfg, &regs->con1);
+
+       priv->active_channel = -1;
+
+       return 0;
+}
+
+int exynos_adc_probe(struct udevice *dev)
+{
+       struct exynos_adc_priv *priv = dev_get_priv(dev);
+       struct exynos_adc_v2 *regs = priv->regs;
+       unsigned int cfg;
+
+       /* Check HW version */
+       if (readl(&regs->version) != ADC_V2_VERSION) {
+               error("This driver supports only ADC v2!");
+               return -ENXIO;
+       }
+
+       /* ADC Reset */
+       writel(ADC_V2_CON1_SOFT_RESET, &regs->con1);
+
+       /* Disable INT - will read status only */
+       writel(0x0, &regs->int_en);
+
+       /* CON2 - set conversion parameters */
+       cfg = ADC_V2_CON2_C_TIME(3); /* Conversion times: (1 << 3) = 8 */
+       cfg |= ADC_V2_CON2_OSEL(OSEL_BINARY);
+       cfg |= ADC_V2_CON2_ESEL(ESEL_ADC_EVAL_TIME_20CLK);
+       cfg |= ADC_V2_CON2_HIGHF(HIGHF_CONV_RATE_600KSPS);
+       writel(cfg, &regs->con2);
+
+       priv->active_channel = -1;
+
+       return 0;
+}
+
+int exynos_adc_ofdata_to_platdata(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+       struct exynos_adc_priv *priv = dev_get_priv(dev);
+
+       priv->regs = (struct exynos_adc_v2 *)dev_get_addr(dev);
+       if (priv->regs == (struct exynos_adc_v2 *)FDT_ADDR_T_NONE) {
+               error("Dev: %s - can't get address!", dev->name);
+               return -ENODATA;
+       }
+
+       uc_pdata->data_mask = ADC_V2_DAT_MASK;
+       uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+       uc_pdata->data_timeout_us = ADC_V2_CONV_TIMEOUT_US;
+
+       /* Mask available channel bits: [0:9] */
+       uc_pdata->channel_mask = (2 << ADC_V2_MAX_CHANNEL) - 1;
+
+       return 0;
+}
+
+static const struct adc_ops exynos_adc_ops = {
+       .start_channel = exynos_adc_start_channel,
+       .channel_data = exynos_adc_channel_data,
+       .stop = exynos_adc_stop,
+};
+
+static const struct udevice_id exynos_adc_ids[] = {
+       { .compatible = "samsung,exynos-adc-v2" },
+       { }
+};
+
+U_BOOT_DRIVER(exynos_adc) = {
+       .name           = "exynos-adc",
+       .id             = UCLASS_ADC,
+       .of_match       = exynos_adc_ids,
+       .ops            = &exynos_adc_ops,
+       .probe          = exynos_adc_probe,
+       .ofdata_to_platdata = exynos_adc_ofdata_to_platdata,
+       .priv_auto_alloc_size = sizeof(struct exynos_adc_priv),
+};
diff --git a/drivers/adc/sandbox.c b/drivers/adc/sandbox.c
new file mode 100644 (file)
index 0000000..3718922
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <adc.h>
+#include <sandbox-adc.h>
+
+/**
+ * struct sandbox_adc_priv - sandbox ADC device's operation status and data
+ *
+ * @conversion_status - conversion status: ACTIVE (started) / INACTIVE (stopped)
+ * @conversion_mode   - conversion mode: single or multi-channel
+ * @active_channel    - active channel number, valid for single channel mode
+ * data[]             - channels data
+ */
+struct sandbox_adc_priv {
+       int conversion_status;
+       int conversion_mode;
+       int active_channel_mask;
+       unsigned int data[4];
+};
+
+int sandbox_adc_start_channel(struct udevice *dev, int channel)
+{
+       struct sandbox_adc_priv *priv = dev_get_priv(dev);
+
+       /* Set single-channel mode */
+       priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL;
+       /* Select channel */
+       priv->active_channel_mask = 1 << channel;
+       /* Start conversion */
+       priv->conversion_status = SANDBOX_ADC_ACTIVE;
+
+       return 0;
+}
+
+int sandbox_adc_start_channels(struct udevice *dev, unsigned int channel_mask)
+{
+       struct sandbox_adc_priv *priv = dev_get_priv(dev);
+
+       /* Set single-channel mode */
+       priv->conversion_mode = SANDBOX_ADC_MODE_MULTI_CHANNEL;
+       /* Select channel */
+       priv->active_channel_mask = channel_mask;
+       /* Start conversion */
+       priv->conversion_status = SANDBOX_ADC_ACTIVE;
+
+       return 0;
+}
+
+int sandbox_adc_channel_data(struct udevice *dev, int channel,
+                            unsigned int *data)
+{
+       struct sandbox_adc_priv *priv = dev_get_priv(dev);
+
+       /* For single-channel conversion mode, check if channel was selected */
+       if ((priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) &&
+           !(priv->active_channel_mask & (1 << channel))) {
+               error("Request for an inactive channel!");
+               return -EINVAL;
+       }
+
+       /* The conversion must be started before reading the data */
+       if (priv->conversion_status == SANDBOX_ADC_INACTIVE)
+               return -EIO;
+
+       *data = priv->data[channel];
+
+       return 0;
+}
+
+int sandbox_adc_channels_data(struct udevice *dev, unsigned int channel_mask,
+                             struct adc_channel *channels)
+{
+       struct sandbox_adc_priv *priv = dev_get_priv(dev);
+       int i;
+
+       /* Return error for single-channel conversion mode */
+       if (priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) {
+               error("ADC in single-channel mode!");
+               return -EPERM;
+       }
+       /* Check channel selection */
+       if (!(priv->active_channel_mask & channel_mask)) {
+               error("Request for an inactive channel!");
+               return -EINVAL;
+       }
+       /* The conversion must be started before reading the data */
+       if (priv->conversion_status == SANDBOX_ADC_INACTIVE)
+               return -EIO;
+
+       for (i = 0; i < SANDBOX_ADC_CHANNELS; i++) {
+               if (!((channel_mask >> i) & 0x1))
+                       continue;
+
+               channels->data = priv->data[i];
+               channels->id = i;
+               channels++;
+       }
+
+       return 0;
+}
+
+int sandbox_adc_stop(struct udevice *dev)
+{
+       struct sandbox_adc_priv *priv = dev_get_priv(dev);
+
+       /* Start conversion */
+       priv->conversion_status = SANDBOX_ADC_INACTIVE;
+
+       return 0;
+}
+
+int sandbox_adc_probe(struct udevice *dev)
+{
+       struct sandbox_adc_priv *priv = dev_get_priv(dev);
+
+       /* Stop conversion */
+       priv->conversion_status = SANDBOX_ADC_INACTIVE;
+       /* Set single-channel mode */
+       priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL;
+       /* Deselect all channels */
+       priv->active_channel_mask = 0;
+
+       /* Set sandbox test data */
+       priv->data[0] = SANDBOX_ADC_CHANNEL0_DATA;
+       priv->data[1] = SANDBOX_ADC_CHANNEL1_DATA;
+       priv->data[2] = SANDBOX_ADC_CHANNEL2_DATA;
+       priv->data[3] = SANDBOX_ADC_CHANNEL3_DATA;
+
+       return 0;
+}
+
+int sandbox_adc_ofdata_to_platdata(struct udevice *dev)
+{
+       struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+
+       uc_pdata->data_mask = SANDBOX_ADC_DATA_MASK;
+       uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+       uc_pdata->data_timeout_us = 0;
+
+       /* Mask available channel bits: [0:3] */
+       uc_pdata->channel_mask = (1 << SANDBOX_ADC_CHANNELS) - 1;
+
+       return 0;
+}
+
+static const struct adc_ops sandbox_adc_ops = {
+       .start_channel = sandbox_adc_start_channel,
+       .start_channels = sandbox_adc_start_channels,
+       .channel_data = sandbox_adc_channel_data,
+       .channels_data = sandbox_adc_channels_data,
+       .stop = sandbox_adc_stop,
+};
+
+static const struct udevice_id sandbox_adc_ids[] = {
+       { .compatible = "sandbox,adc" },
+       { }
+};
+
+U_BOOT_DRIVER(sandbox_adc) = {
+       .name           = "sandbox-adc",
+       .id             = UCLASS_ADC,
+       .of_match       = sandbox_adc_ids,
+       .ops            = &sandbox_adc_ops,
+       .probe          = sandbox_adc_probe,
+       .ofdata_to_platdata = sandbox_adc_ofdata_to_platdata,
+       .priv_auto_alloc_size = sizeof(struct sandbox_adc_priv),
+};
index 7646c6b7270c1859a6cf10985f65670a3f818bdb..9702eeea202a97f87b9c24b152e335d792b4f49b 100644 (file)
@@ -115,8 +115,10 @@ static struct spi_flash *parse_dev(char *devstr)
 int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s)
 {
        char *st;
+       char *devstr_bkup = strdup(devstr);
 
-       dfu->data.sf.dev = parse_dev(devstr);
+       dfu->data.sf.dev = parse_dev(devstr_bkup);
+       free(devstr_bkup);
        if (!dfu->data.sf.dev)
                return -ENODEV;
 
index 15ecfee961b4a9ed4b0b3ee2d20fad973373ddcd..44353c72f4d706d45d3acf29b9074320c819de88 100644 (file)
@@ -106,6 +106,12 @@ static int do_sdhci_init(struct sdhci_host *host)
        flag = host->bus_width == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
        dev_id = host->index + PERIPH_ID_SDMMC0;
 
+       ret = exynos_pinmux_config(dev_id, flag);
+       if (ret) {
+               printf("external SD not configured\n");
+               return ret;
+       }
+
        if (dm_gpio_is_valid(&host->pwr_gpio)) {
                dm_gpio_set_value(&host->pwr_gpio, 1);
                ret = exynos_pinmux_config(dev_id, flag);
@@ -121,12 +127,6 @@ static int do_sdhci_init(struct sdhci_host *host)
                        debug("no SD card detected (%d)\n", ret);
                        return -ENODEV;
                }
-
-               ret = exynos_pinmux_config(dev_id, flag);
-               if (ret) {
-                       printf("external SD not configured\n");
-                       return ret;
-               }
        }
 
        return s5p_sdhci_core_init(host);
@@ -193,7 +193,7 @@ static int process_nodes(const void *blob, int node_list[], int count)
                }
 
                ret = do_sdhci_init(host);
-               if (ret) {
+               if (ret && ret != -ENODEV) {
                        printf("%s: failed to initialize dev %d (%d)\n", __func__, i, ret);
                        failed++;
                }
index 547fd1aaa6a0d7ee0ece5ddbd15b5551f9fe9cd7..fb29843a5a12c9fa2d19aafc6777b16202faefad 100644 (file)
@@ -33,6 +33,20 @@ config DM_PMIC_MAX77686
        This config enables implementation of driver-model pmic uclass features
        for PMIC MAX77686. The driver implements read/write operations.
 
+config PMIC_S2MPS11
+       bool "Enable Driver Model for PMIC Samsung S2MPS11"
+       depends on DM_PMIC
+       ---help---
+       The Samsung S2MPS11 PMIC provides:
+        - 38 adjustable LDO regulators
+        - 9 High-Efficiency Buck Converters
+        - 1 BuckBoost Converter
+        - RTC with two alarms
+        - Backup battery charger
+        - I2C Configuration Interface
+       This driver provides access to I/O interface only.
+       Binding info: doc/device-tree-bindings/pmic/s2mps11.txt
+
 config DM_PMIC_SANDBOX
        bool "Enable Driver Model for emulated Sandbox PMIC "
        depends on DM_PMIC
index 00fde71b2c22f91ccae08eff799e80601ff9b09a..91e78f8149571087d19a3297149d088c709d2e6d 100644 (file)
@@ -8,6 +8,7 @@
 obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
 obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
 obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o
+obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
 obj-$(CONFIG_PMIC_ACT8846) += act8846.o
 obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
diff --git a/drivers/power/pmic/s2mps11.c b/drivers/power/pmic/s2mps11.c
new file mode 100644 (file)
index 0000000..9d83059
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics
+ *  Przemyslaw Marczak  <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/s2mps11.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int s2mps11_reg_count(struct udevice *dev)
+{
+       return S2MPS11_REG_COUNT;
+}
+
+static int s2mps11_write(struct udevice *dev, uint reg, const uint8_t *buff,
+                        int len)
+{
+       int ret;
+
+       ret = dm_i2c_write(dev, reg, buff, len);
+       if (ret)
+               error("write error to device: %p register: %#x!", dev, reg);
+
+       return ret;
+}
+
+static int s2mps11_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+       int ret;
+
+       ret = dm_i2c_read(dev, reg, buff, len);
+       if (ret)
+               error("read error from device: %p register: %#x!", dev, reg);
+
+       return ret;
+}
+
+static struct dm_pmic_ops s2mps11_ops = {
+       .reg_count = s2mps11_reg_count,
+       .read = s2mps11_read,
+       .write = s2mps11_write,
+};
+
+static const struct udevice_id s2mps11_ids[] = {
+       { .compatible = "samsung,s2mps11-pmic" },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_s2mps11) = {
+       .name = "s2mps11_pmic",
+       .id = UCLASS_PMIC,
+       .of_match = s2mps11_ids,
+       .ops = &s2mps11_ops,
+};
index a5170df9165152f81eda9c6f6dec0839ba0fbb74..4241a4c7f2bd1fbeec6df8ceee7c128f3c2db228 100644 (file)
@@ -138,6 +138,13 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp)
        return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
 }
 
+int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
+                               struct udevice **devp)
+{
+       return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+                                           supply_name, devp);
+}
+
 int regulator_autoset(struct udevice *dev)
 {
        struct dm_regulator_uclass_platdata *uc_pdata;
index 34a0f46a1ae0d5de7a43270acc9b87025d63950d..4f7fd5253220882c7074ac62bdcb5e4461a48b07 100644 (file)
@@ -37,9 +37,8 @@ static int cadence_spi_write_speed(struct udevice *bus, uint hz)
 }
 
 /* Calibration sequence to determine the read data capture delay register */
-static int spi_calibration(struct udevice *bus)
+static int spi_calibration(struct udevice *bus, uint hz)
 {
-       struct cadence_spi_platdata *plat = bus->platdata;
        struct cadence_spi_priv *priv = dev_get_priv(bus);
        void *base = priv->regbase;
        u8 opcode_rdid = 0x9F;
@@ -64,7 +63,7 @@ static int spi_calibration(struct udevice *bus)
        }
 
        /* use back the intended clock and find low range */
-       cadence_spi_write_speed(bus, plat->max_hz);
+       cadence_spi_write_speed(bus, hz);
        for (i = 0; i < CQSPI_READ_CAPTURE_MAX_DELAY; i++) {
                /* Disable QSPI */
                cadence_qspi_apb_controller_disable(base);
@@ -111,7 +110,7 @@ static int spi_calibration(struct udevice *bus)
              (range_hi + range_lo) / 2, range_lo, range_hi);
 
        /* just to ensure we do once only when speed or chip select change */
-       priv->qspi_calibrated_hz = plat->max_hz;
+       priv->qspi_calibrated_hz = hz;
        priv->qspi_calibrated_cs = spi_chip_select(bus);
 
        return 0;
@@ -123,17 +122,25 @@ static int cadence_spi_set_speed(struct udevice *bus, uint hz)
        struct cadence_spi_priv *priv = dev_get_priv(bus);
        int err;
 
+       if (hz > plat->max_hz)
+               hz = plat->max_hz;
+
        /* Disable QSPI */
        cadence_qspi_apb_controller_disable(priv->regbase);
 
-       cadence_spi_write_speed(bus, hz);
-
-       /* Calibration required for different SCLK speed or chip select */
-       if (priv->qspi_calibrated_hz != plat->max_hz ||
+       /*
+        * Calibration required for different current SCLK speed, requested
+        * SCLK speed or chip select
+        */
+       if (priv->previous_hz != hz ||
+           priv->qspi_calibrated_hz != hz ||
            priv->qspi_calibrated_cs != spi_chip_select(bus)) {
-               err = spi_calibration(bus);
+               err = spi_calibration(bus, hz);
                if (err)
                        return err;
+
+               /* prevent calibration run when same as previous request */
+               priv->previous_hz = hz;
        }
 
        /* Enable QSPI */
@@ -291,10 +298,6 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus)
        plat->regbase = (void *)data[0];
        plat->ahbbase = (void *)data[2];
 
-       /* Use 500KHz as a suitable default */
-       plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
-                                     500000);
-
        /* All other paramters are embedded in the child node */
        subnode = fdt_first_subnode(blob, node);
        if (subnode < 0) {
@@ -302,6 +305,10 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus)
                return -ENODEV;
        }
 
+       /* Use 500 KHz as a suitable default */
+       plat->max_hz = fdtdec_get_uint(blob, subnode, "spi-max-frequency",
+                                      500000);
+
        /* Read other parameters from DT */
        plat->page_size = fdtdec_get_int(blob, subnode, "page-size", 256);
        plat->block_size = fdtdec_get_int(blob, subnode, "block-size", 16);
index 98e57aa5bccceaedff06f0a9d7819db36bd3fb20..2912e36a53f7601f1d1251a1888c922ab6a7532c 100644 (file)
@@ -38,6 +38,7 @@ struct cadence_spi_priv {
        int             qspi_is_init;
        unsigned int    qspi_calibrated_hz;
        unsigned int    qspi_calibrated_cs;
+       unsigned int    previous_hz;
 };
 
 /* Functions call declaration */
index ab3c94e51275764df2e8b965329de604cc3d32e7..0ae3de5c27b9dcd0611dafc42f9ada8a18be89d0 100644 (file)
@@ -281,7 +281,7 @@ static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
        return 0;
 
 err1:
-       dma_unmap_single((void *)dwc->scratch_addr, dwc->nr_scratch *
+       dma_unmap_single((void *)(uintptr_t)dwc->scratch_addr, dwc->nr_scratch *
                         DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
 
 err0:
@@ -296,7 +296,7 @@ static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
        if (!dwc->nr_scratch)
                return;
 
-       dma_unmap_single((void *)dwc->scratch_addr, dwc->nr_scratch *
+       dma_unmap_single((void *)(uintptr_t)dwc->scratch_addr, dwc->nr_scratch *
                         DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
        kfree(dwc->scratchbuf);
 }
@@ -629,7 +629,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev)
        dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
        dwc->mem = mem;
 
-       dwc->regs       = (int *)(dwc3_dev->base + DWC3_GLOBALS_REGS_START);
+       dwc->regs = (void *)(uintptr_t)(dwc3_dev->base +
+                                       DWC3_GLOBALS_REGS_START);
 
        /* default to highest possible threshold */
        lpm_nyet_threshold = 0xff;
index aba614fb4e984011db4b24f09bd3404ded5770fb..12b133f93e178ee7b3d0c19017a2464c46642fbf 100644 (file)
@@ -81,8 +81,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
                trb->ctrl |= (DWC3_TRB_CTRL_IOC
                                | DWC3_TRB_CTRL_LST);
 
-       dwc3_flush_cache((int)buf_dma, len);
-       dwc3_flush_cache((int)trb, sizeof(*trb));
+       dwc3_flush_cache((long)buf_dma, len);
+       dwc3_flush_cache((long)trb, sizeof(*trb));
 
        if (chain)
                return 0;
@@ -790,7 +790,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
        if (!r)
                return;
 
-       dwc3_flush_cache((int)trb, sizeof(*trb));
+       dwc3_flush_cache((long)trb, sizeof(*trb));
 
        status = DWC3_TRB_SIZE_TRBSTS(trb->size);
        if (status == DWC3_TRBSTS_SETUP_PENDING) {
@@ -821,7 +821,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
                        ur->actual += transferred;
 
                        trb++;
-                       dwc3_flush_cache((int)trb, sizeof(*trb));
+                       dwc3_flush_cache((long)trb, sizeof(*trb));
                        length = trb->size & DWC3_TRB_SIZE_MASK;
 
                        ep0->free_slot = 0;
@@ -831,7 +831,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
                                        maxp);
                transferred = min_t(u32, ur->length - transferred,
                                    transfer_size - length);
-               dwc3_flush_cache((int)dwc->ep0_bounce, DWC3_EP0_BOUNCE_SIZE);
+               dwc3_flush_cache((long)dwc->ep0_bounce, DWC3_EP0_BOUNCE_SIZE);
                memcpy(buf, dwc->ep0_bounce, transferred);
        } else {
                transferred = ur->length - length;
index f3d649a5ee2f85d66bef3c4f5b1d2a5f55a26a6d..8ff949d241f6e9c13c13432d3a54db1bdfba44f2 100644 (file)
@@ -244,7 +244,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 
        list_del(&req->list);
        req->trb = NULL;
-       dwc3_flush_cache((int)req->request.dma, req->request.length);
+       dwc3_flush_cache((long)req->request.dma, req->request.length);
 
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
@@ -771,8 +771,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 
        trb->ctrl |= DWC3_TRB_CTRL_HWO;
 
-       dwc3_flush_cache((int)dma, length);
-       dwc3_flush_cache((int)trb, sizeof(*trb));
+       dwc3_flush_cache((long)dma, length);
+       dwc3_flush_cache((long)trb, sizeof(*trb));
 }
 
 /*
@@ -1769,7 +1769,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
        slot %= DWC3_TRB_NUM;
        trb = &dep->trb_pool[slot];
 
-       dwc3_flush_cache((int)trb, sizeof(*trb));
+       dwc3_flush_cache((long)trb, sizeof(*trb));
        __dwc3_cleanup_done_trbs(dwc, dep, req, trb, event, status);
        dwc3_gadget_giveback(dep, req, status);
 
@@ -2670,7 +2670,7 @@ void dwc3_gadget_uboot_handle_interrupt(struct dwc3 *dwc)
 
                for (i = 0; i < dwc->num_event_buffers; i++) {
                        evt = dwc->ev_buffs[i];
-                       dwc3_flush_cache((int)evt->buf, evt->length);
+                       dwc3_flush_cache((long)evt->buf, evt->length);
                }
 
                dwc3_thread_interrupt(0, dwc);
index 5042a2419369416db4abe8b6dca2a7b66c0885f9..0d9fa220e922ed9009b8a6aca5cf3d9ffe383c0e 100644 (file)
@@ -23,7 +23,7 @@
 #define        CACHELINE_SIZE          CONFIG_SYS_CACHELINE_SIZE
 static inline u32 dwc3_readl(void __iomem *base, u32 offset)
 {
-       u32 offs = offset - DWC3_GLOBALS_REGS_START;
+       unsigned long offs = offset - DWC3_GLOBALS_REGS_START;
        u32 value;
 
        /*
@@ -38,7 +38,7 @@ static inline u32 dwc3_readl(void __iomem *base, u32 offset)
 
 static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
 {
-       u32 offs = offset - DWC3_GLOBALS_REGS_START;
+       unsigned long offs = offset - DWC3_GLOBALS_REGS_START;
 
        /*
         * We requested the mem region starting from the Globals address
index ff1481ba372304f3f8f5af5be18ea2185a6d57b2..9ed0ce3d31328674f982e8b32a96643b8e77c361 100644 (file)
@@ -569,7 +569,7 @@ static void thor_tx_data(unsigned char *data, int len)
 
        dev->in_req->length = len;
 
-       debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__,
+       debug("%s: dev->in_req->length:%d to_cpy:%zd\n", __func__,
              dev->in_req->length, sizeof(data));
 
        status = usb_ep_queue(dev->in_ep, dev->in_req, 0);
index 875e998a82e395a8a89151bb4d3f54b8cfa0132b..326757b547fa85a0dcbc6d003cf253a2a48e223b 100644 (file)
@@ -65,7 +65,7 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget,
        if (req->length == 0)
                return;
 
-       dma_unmap_single((void *)req->dma, req->length,
+       dma_unmap_single((void *)(uintptr_t)req->dma, req->length,
                         is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 }
 EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
index 9bde2b252c03783356a83ffbb6d1769e4fbdb11d..ccbfc0265a362d8672ac56a6537013bc9413fd3b 100644 (file)
@@ -2205,6 +2205,7 @@ int ohci_register(struct udevice *dev, struct ohci_regs *regs)
        if (!ohci->hcca)
                return -ENOMEM;
        memset(ohci->hcca, 0, sizeof(struct ohci_hcca));
+       flush_dcache_hcca(ohci->hcca);
 
        if (hc_reset(ohci) < 0)
                return -EIO;
diff --git a/include/adc.h b/include/adc.h
new file mode 100644 (file)
index 0000000..4b14017
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _ADC_H_
+#define _ADC_H_
+
+/* ADC_CHANNEL() - ADC channel bit mask, to select only required channels */
+#define ADC_CHANNEL(x)         (1 << x)
+
+/* The last possible selected channel with 32-bit mask */
+#define ADC_MAX_CHANNEL                31
+
+/**
+ * adc_data_format: define the ADC output data format, can be useful when
+ * the device's input Voltage range is bipolar.
+ * - ADC_DATA_FORMAT_BIN - binary offset
+ * - ADC_DATA_FORMAT_2S  - two's complement
+ *
+ * Note: Device's driver should fill the 'data_format' field of its uclass's
+ * platform data using one of the above data format types.
+ */
+enum adc_data_format {
+       ADC_DATA_FORMAT_BIN,
+       ADC_DATA_FORMAT_2S,
+};
+
+/**
+ * struct adc_channel - structure to hold channel conversion data.
+ * Useful to keep the result of a multi-channel conversion output.
+ *
+ * @id   - channel id
+ * @data - channel conversion data
+ */
+struct adc_channel {
+       int id;
+       unsigned int data;
+};
+
+/**
+ * struct adc_uclass_platdata - basic ADC info
+ *
+ * Note: The positive/negative reference Voltage is only a name and it doesn't
+ * provide an information about the value polarity. It is possible, for both
+ * values to be a negative or positive. For this purpose the uclass's platform
+ * data provides a bool fields: 'vdd/vss_supply_is_negative'. This is useful,
+ * since the regulator API returns only a positive Voltage values.
+ *
+ * To get the reference Voltage values with polarity, use functions:
+ * - adc_vdd_value()
+ * - adc_vss_value()
+ * Those are useful for some cases of ADC's references, e.g.:
+ * * Vdd: +3.3V; Vss: -3.3V -> 6.6 Vdiff
+ * * Vdd: +3.3V; Vss: +0.3V -> 3.0 Vdiff
+ * * Vdd: +3.3V; Vss:  0.0V -> 3.3 Vdiff
+ * The last one is usually standard and doesn't require the fdt polarity info.
+ *
+ * For more informations read binding info:
+ * - doc/device-tree-bindings/adc/adc.txt
+ *
+ * @data_mask              - conversion output data mask
+ * @data_timeout_us        - single channel conversion timeout
+ * @multidata_timeout_us   - multi channel conversion timeout
+ * @channel_mask           - bit mask of available channels [0:31]
+ * @vdd_supply             - positive reference Voltage supply (regulator)
+ * @vss_supply             - negative reference Voltage supply (regulator)
+ * @vdd_polarity_negative  - positive reference Voltage has negative polarity
+ * @vss_polarity_negative  - negative reference Voltage has negative polarity
+ * @vdd_microvolts         - positive reference Voltage value
+ * @vss_microvolts         - negative reference Voltage value
+ */
+struct adc_uclass_platdata {
+       int data_format;
+       unsigned int data_mask;
+       unsigned int data_timeout_us;
+       unsigned int multidata_timeout_us;
+       unsigned int channel_mask;
+       struct udevice *vdd_supply;
+       struct udevice *vss_supply;
+       bool vdd_polarity_negative;
+       bool vss_polarity_negative;
+       int vdd_microvolts;
+       int vss_microvolts;
+};
+
+/**
+ * struct adc_ops - ADC device operations for single/multi-channel operation.
+ */
+struct adc_ops {
+       /**
+        * start_channel() - start conversion with its default parameters
+        *                   for the given channel number.
+        *
+        * @dev:          ADC device to init
+        * @channel:      analog channel number
+        * @return:       0 if OK, -ve on error
+        */
+       int (*start_channel)(struct udevice *dev, int channel);
+
+       /**
+        * start_channels() - start conversion with its default parameters
+        *                    for the channel numbers selected by the bit mask.
+        *
+        * This is optional, useful when the hardware supports multichannel
+        * conversion by the single software trigger.
+        *
+        * @dev:          ADC device to init
+        * @channel_mask: bit mask of selected analog channels
+        * @return:       0 if OK, -ve on error
+        */
+       int (*start_channels)(struct udevice *dev, unsigned int channel_mask);
+
+       /**
+        * channel_data() - get conversion output data for the given channel.
+        *
+        * Note: The implementation of this function should only check, that
+        * the conversion data is available at the call time. If the hardware
+        * requires some delay to get the data, then this function should
+        * return with -EBUSY value. The ADC API will call it in a loop,
+        * until the data is available or the timeout expires. The maximum
+        * timeout for this operation is defined by the field 'data_timeout_us'
+        * in ADC uclasses platform data structure.
+        *
+        * @dev:          ADC device to trigger
+        * @channel:      selected analog channel number
+        * @data:         returned pointer to selected channel's output data
+        * @return:       0 if OK, -EBUSY if busy, and other negative on error
+        */
+       int (*channel_data)(struct udevice *dev, int channel,
+                           unsigned int *data);
+
+       /**
+        * channels_data() - get conversion data for the selected channels.
+        *
+        * This is optional, useful when multichannel conversion is supported
+        * by the hardware, by the single software trigger.
+        *
+        * For the proper implementation, please look at the 'Note' for the
+        * above method. The only difference is in used timeout value, which
+        * is defined by field 'multidata_timeout_us'.
+        *
+        * @dev:          ADC device to trigger
+        * @channel_mask: bit mask of selected analog channels
+        * @channels:     returned pointer to array of output data for channels
+        *                selected by the given mask
+        * @return:       0 if OK, -ve on error
+        */
+       int (*channels_data)(struct udevice *dev, unsigned int channel_mask,
+                            struct adc_channel *channels);
+
+       /**
+        * stop() - stop conversion of the given ADC device
+        *
+        * @dev:          ADC device to stop
+        * @return:       0 if OK, -ve on error
+        */
+       int (*stop)(struct udevice *dev);
+};
+
+/**
+ * adc_start_channel() - start conversion for given device/channel and exit.
+ *
+ * @dev:     ADC device
+ * @channel: analog channel number
+ * @return:  0 if OK, -ve on error
+ */
+int adc_start_channel(struct udevice *dev, int channel);
+
+/**
+ * adc_start_channels() - start conversion for given device/channels and exit.
+ *
+ * Note:
+ * To use this function, device must implement method: start_channels().
+ *
+ * @dev:          ADC device to start
+ * @channel_mask: channel selection - a bit mask
+ * @channel_mask: bit mask of analog channels
+ * @return:       0 if OK, -ve on error
+ */
+int adc_start_channels(struct udevice *dev, unsigned int channel_mask);
+
+/**
+ * adc_channel_data() - get conversion data for the given device channel number.
+ *
+ * @dev:     ADC device to read
+ * @channel: analog channel number
+ * @data:    pointer to returned channel's data
+ * @return:  0 if OK, -ve on error
+ */
+int adc_channel_data(struct udevice *dev, int channel, unsigned int *data);
+
+/**
+ * adc_channels_data() - get conversion data for the channels selected by mask
+ *
+ * Note:
+ * To use this function, device must implement methods:
+ * - start_channels()
+ * - channels_data()
+ *
+ * @dev:          ADC device to read
+ * @channel_mask: channel selection - a bit mask
+ * @channels:     pointer to structure array of returned data for each channel
+ * @return:       0 if OK, -ve on error
+ */
+int adc_channels_data(struct udevice *dev, unsigned int channel_mask,
+                     struct adc_channel *channels);
+
+/**
+ * adc_data_mask() - get data mask (ADC resolution bitmask) for given ADC device
+ *
+ * This can be used if adc uclass platform data is filled.
+ *
+ * @dev:       ADC device to check
+ * @data_mask: pointer to the returned data bitmask
+ * @return: 0 if OK, -ve on error
+ */
+int adc_data_mask(struct udevice *dev, unsigned int *data_mask);
+
+/**
+ * adc_channel_single_shot() - get output data of conversion for the ADC
+ * device's channel. This function searches for the device with the given name,
+ * starts the given channel conversion and returns the output data.
+ *
+ * Note: To use this function, device must implement metods:
+ * - start_channel()
+ * - channel_data()
+ *
+ * @name:    device's name to search
+ * @channel: device's input channel to init
+ * @data:    pointer to conversion output data
+ * @return:  0 if OK, -ve on error
+ */
+int adc_channel_single_shot(const char *name, int channel, unsigned int *data);
+
+/**
+ * adc_channels_single_shot() - get ADC conversion output data for the selected
+ * device's channels. This function searches for the device by the given name,
+ * starts the selected channels conversion and returns the output data as array
+ * of type 'struct adc_channel'.
+ *
+ * Note: This function can be used if device implements one of ADC's single
+ * or multi-channel operation API. If multi-channel operation is not supported,
+ * then each selected channel is triggered by the sequence start/data in a loop.
+ *
+ * @name:         device's name to search
+ * @channel_mask: channel selection - a bit mask
+ * @channels:     pointer to conversion output data for the selected channels
+ * @return:       0 if OK, -ve on error
+ */
+int adc_channels_single_shot(const char *name, unsigned int channel_mask,
+                            struct adc_channel *channels);
+
+/**
+ * adc_vdd_value() - get the ADC device's positive reference Voltage value
+ *
+ * Note: Depending on bool value 'vdd_supply_is_negative' of platform data,
+ * the returned uV value can be negative, and it's not an error.
+ *
+ * @dev:     ADC device to check
+ * @uV:      Voltage value with polarization sign (uV)
+ * @return:  0 on success or -ve on error
+*/
+int adc_vdd_value(struct udevice *dev, int *uV);
+
+/**
+ * adc_vss_value() - get the ADC device's negative reference Voltage value
+ *
+ * Note: Depending on bool value 'vdd_supply_is_negative' of platform data,
+ * the returned uV value can be negative, and it's not an error.
+ *
+ * @dev:     ADC device to check
+ * @uV:      Voltage value with polarization sign (uV)
+ * @return:  0 on success or -ve on error
+*/
+int adc_vss_value(struct udevice *dev, int *uV);
+
+/**
+ * adc_stop() - stop operation for given ADC device.
+ *
+ * @dev:     ADC device to stop
+ * @return:  0 if OK, -ve on error
+ */
+int adc_stop(struct udevice *dev);
+
+#endif
index 6e32de854619cf07172b5ae908e62942fd73a0b9..cb9544b49efba0b6d513ede33d36d73852ced135 100644 (file)
        "fdt ram 0x80f80000 0x80000;" \
        "ramdisk ram 0x81000000 0x4000000\0"
 
+#define DFU_ALT_INFO_QSPI \
+       "dfu_alt_info_qspi=" \
+       "MLO raw 0x0 0x010000;" \
+       "MLO.backup1 raw 0x010000 0x010000;" \
+       "MLO.backup2 raw 0x020000 0x010000;" \
+       "MLO.backup3 raw 0x030000 0x010000;" \
+       "u-boot.img raw 0x040000 0x0100000;" \
+       "u-boot-spl-os raw 0x140000 0x080000;" \
+       "u-boot-env raw 0x1C0000 0x010000;" \
+       "u-boot-env.backup raw 0x1D0000 0x010000;" \
+       "kernel raw 0x1E0000 0x800000\0"
+
 #define DFUARGS \
        "dfu_bufsiz=0x10000\0" \
        DFU_ALT_INFO_MMC \
        DFU_ALT_INFO_EMMC \
-       DFU_ALT_INFO_RAM
+       DFU_ALT_INFO_RAM \
+       DFU_ALT_INFO_QSPI
 
 /* Fastboot */
 #define CONFIG_USB_FUNCTION_FASTBOOT
 
 #define CONFIG_DFU_MMC
 #define CONFIG_DFU_RAM
+#define CONFIG_DFU_SF
 
 /* SATA */
 #define CONFIG_BOARD_LATE_INIT
index 3c701587bfbe1bd6384d5abf58640fadecce39b7..648e48bcf4bf3f48b1a3dcacfc1ac9507d7d7317 100644 (file)
@@ -94,6 +94,8 @@
        "boot.scr fat 0 1;"                 \
        "boot.cmd fat 0 1;"                 \
        "exynos5422-odroidxu3.dtb fat 0 1;" \
+       "exynos5422-odroidxu3-lite.dtb fat 0 1;" \
+       "exynos5422-odroidxu4.dtb fat 0 1;" \
        "boot part 0 1;"                    \
        "root part 0 2\0"
 
 
 /* Enable: board/samsung/common/misc.c to use set_dfu_alt_info() */
 #define CONFIG_MISC_COMMON
+#define CONFIG_MISC_INIT_R
 #define CONFIG_SET_DFU_ALT_INFO
 #define CONFIG_SET_DFU_ALT_BUF_LEN     (SZ_1K)
 
+/* Set soc_rev, soc_id, board_rev, boardname, fdtfile */
+#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+#define CONFIG_ODROID_REV_AIN                  9
+#define CONFIG_REVISION_TAG
+#define CONFIG_BOARD_TYPES
+
+#undef CONFIG_SYS_BOARD
+#define CONFIG_SYS_BOARD       "odroid"
+
 /* Define new extra env settings, including DFU settings */
 #undef CONFIG_EXTRA_ENV_SETTINGS
 #define CONFIG_EXTRA_ENV_SETTINGS \
index 886a44c134ba3ebd83263332c0f824ba3176e825..d0cf4ce6a0d20e1af896db81d675a89daa1c7742 100644 (file)
@@ -25,6 +25,7 @@ enum uclass_id {
        UCLASS_SIMPLE_BUS,      /* bus with child devices */
 
        /* U-Boot uclasses start here - in alphabetical order */
+       UCLASS_ADC,             /* Analog-to-digital converter */
        UCLASS_CLK,             /* Clock source, e.g. used by peripherals */
        UCLASS_CPU,             /* CPU, typically part of an SoC */
        UCLASS_CROS_EC,         /* Chrome OS EC */
index 9fcc7a1e19997cbf729df718c268e8141b22d625..0e36664dca4aed281222a97388089049e1f10ae7 100644 (file)
@@ -489,6 +489,19 @@ int fdtdec_get_pci_bar32(const void *blob, int node,
 s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
                s32 default_val);
 
+/**
+ * Unsigned version of fdtdec_get_int. The property must have at least
+ * 4 bytes of data. The value of the first cell is returned.
+ *
+ * @param blob FDT blob
+ * @param node node to examine
+ * @param prop_name    name of property to find
+ * @param default_val  default value to return if the property is not found
+ * @return unsigned integer value, if found, or default_val if not
+ */
+unsigned int fdtdec_get_uint(const void *blob, int node, const char *prop_name,
+                       unsigned int default_val);
+
 /**
  * Get a variable-sized number from a property
  *
index 1a51c3f07bc80aa0911db796bfdbc12140916266..63c0814fe83cea2be9bb800940971c7f420395de 100644 (file)
@@ -419,4 +419,20 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp);
  */
 int regulator_get_by_platname(const char *platname, struct udevice **devp);
 
+/**
+ * device_get_supply_regulator: returns the pointer to the supply regulator.
+ * Search by phandle, found in device's node.
+ *
+ * Note: Please pay attention to proper order of device bind sequence.
+ * The regulator device searched by the phandle, must be binded before
+ * this function call.
+ *
+ * @dev         - device with supply phandle
+ * @supply_name - phandle name of regulator
+ * @devp        - returned pointer to the supply device
+ * @return 0 on success or negative value of errno.
+ */
+int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
+                               struct udevice **devp);
+
 #endif /* _INCLUDE_REGULATOR_H_ */
diff --git a/include/power/s2mps11.h b/include/power/s2mps11.h
new file mode 100644 (file)
index 0000000..5da4719
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef __S2MPS11__H__
+#define __S2MPS11__H__
+
+enum s2mps11_reg {
+       S2MPS11_REG_ID = 0,
+       S2MPS11_REG_INT1,
+       S2MPS11_REG_INT2,
+       S2MPS11_REG_INT3,
+       S2MPS11_REG_INT1M,
+       S2MPS11_REG_INT2M,
+       S2MPS11_REG_INT3M,
+       S2MPS11_REG_STATUS1,
+       S2MPS11_REG_STATUS2,
+       S2MPS11_REG_OFFSRC,
+       S2MPS11_REG_PWRONSRC,
+       S2MPS11_REG_RTC_CTRL,
+       S2MPS11_REG_CTRL1,
+       S2MPS11_REG_ETC_TEST,
+       S2MPS11_REG_RSVD3,
+       S2MPS11_REG_BU_CHG,
+       S2MPS11_REG_RAMP,
+       S2MPS11_REG_RAMP_BUCK,
+       S2MPS11_REG_LDO1_8,
+       S2MPS11_REG_LDO9_16,
+       S2MPS11_REG_LDO17_24,
+       S2MPS11_REG_LDO25_32,
+       S2MPS11_REG_LDO33_38,
+       S2MPS11_REG_LDO1_8_OVC,
+       S2MPS11_REG_LDO9_16_OVC,
+       S2MPS11_REG_LDO17_24_OVC,
+       S2MPS11_REG_LDO25_32_OVC,
+       S2MPS11_REG_LDO33_38_OVC,
+       S2MPS11_REG_RESERVED1,
+       S2MPS11_REG_RESERVED2,
+       S2MPS11_REG_RESERVED3,
+       S2MPS11_REG_RESERVED4,
+       S2MPS11_REG_RESERVED5,
+       S2MPS11_REG_RESERVED6,
+       S2MPS11_REG_RESERVED7,
+       S2MPS11_REG_RESERVED8,
+       S2MPS11_REG_WDRSTEN_CTRL,
+       S2MPS11_REG_B1CTRL1,
+       S2MPS11_REG_B1CTRL2,
+       S2MPS11_REG_B2CTRL1,
+       S2MPS11_REG_B2CTRL2,
+       S2MPS11_REG_B3CTRL1,
+       S2MPS11_REG_B3CTRL2,
+       S2MPS11_REG_B4CTRL1,
+       S2MPS11_REG_B4CTRL2,
+       S2MPS11_REG_B5CTRL1,
+       S2MPS11_REG_BUCK5_SW,
+       S2MPS11_REG_B5CTRL2,
+       S2MPS11_REG_B5CTRL3,
+       S2MPS11_REG_B5CTRL4,
+       S2MPS11_REG_B5CTRL5,
+       S2MPS11_REG_B6CTRL1,
+       S2MPS11_REG_B6CTRL2,
+       S2MPS11_REG_B7CTRL1,
+       S2MPS11_REG_B7CTRL2,
+       S2MPS11_REG_B8CTRL1,
+       S2MPS11_REG_B8CTRL2,
+       S2MPS11_REG_B9CTRL1,
+       S2MPS11_REG_B9CTRL2,
+       S2MPS11_REG_B10CTRL1,
+       S2MPS11_REG_B10CTRL2,
+       S2MPS11_REG_L1CTRL,
+       S2MPS11_REG_L2CTRL,
+       S2MPS11_REG_L3CTRL,
+       S2MPS11_REG_L4CTRL,
+       S2MPS11_REG_L5CTRL,
+       S2MPS11_REG_L6CTRL,
+       S2MPS11_REG_L7CTRL,
+       S2MPS11_REG_L8CTRL,
+       S2MPS11_REG_L9CTRL,
+       S2MPS11_REG_L10CTRL,
+       S2MPS11_REG_L11CTRL,
+       S2MPS11_REG_L12CTRL,
+       S2MPS11_REG_L13CTRL,
+       S2MPS11_REG_L14CTRL,
+       S2MPS11_REG_L15CTRL,
+       S2MPS11_REG_L16CTRL,
+       S2MPS11_REG_L17CTRL,
+       S2MPS11_REG_L18CTRL,
+       S2MPS11_REG_L19CTRL,
+       S2MPS11_REG_L20CTRL,
+       S2MPS11_REG_L21CTRL,
+       S2MPS11_REG_L22CTRL,
+       S2MPS11_REG_L23CTRL,
+       S2MPS11_REG_L24CTRL,
+       S2MPS11_REG_L25CTRL,
+       S2MPS11_REG_L26CTRL,
+       S2MPS11_REG_L27CTRL,
+       S2MPS11_REG_L28CTRL,
+       S2MPS11_REG_L29CTRL,
+       S2MPS11_REG_L30CTRL,
+       S2MPS11_REG_L31CTRL,
+       S2MPS11_REG_L32CTRL,
+       S2MPS11_REG_L33CTRL,
+       S2MPS11_REG_L34CTRL,
+       S2MPS11_REG_L35CTRL,
+       S2MPS11_REG_L36CTRL,
+       S2MPS11_REG_L37CTRL,
+       S2MPS11_REG_L38CTRL,
+       S2MPS11_REG_COUNT,
+};
+
+#define S2MPS11_LDO26_ENABLE   0xec
+
+#endif
index 854767497145f4a1a1670a807e4e4b5ac5c99030..7fdbfb9fc6f978ac9e58f26824b42044f6a42bf5 100644 (file)
@@ -126,6 +126,10 @@ enum {
 #define SANDBOX_BUCK1_AUTOSET_EXPECTED_UA      200000
 #define SANDBOX_BUCK1_AUTOSET_EXPECTED_ENABLE  true
 
+/* BUCK2: for testing sandbox ADC's supply */
+#define SANDBOX_BUCK2_INITIAL_EXPECTED_UV      3000000
+#define SANDBOX_BUCK2_SET_UV                   3300000
+
 /* LDO1/2 for testing regulator_list_autoset() */
 #define SANDBOX_LDO1_AUTOSET_EXPECTED_UV       1800000
 #define SANDBOX_LDO1_AUTOSET_EXPECTED_UA       100000
diff --git a/include/samsung/exynos5-dt-types.h b/include/samsung/exynos5-dt-types.h
new file mode 100644 (file)
index 0000000..479e2e7
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _EXYNOS5_DT_H_
+#define _EXYNOS5_DT_H_
+
+enum {
+       EXYNOS5_BOARD_GENERIC,
+
+       EXYNOS5_BOARD_ODROID_XU3,
+       EXYNOS5_BOARD_ODROID_XU3_REV01,
+       EXYNOS5_BOARD_ODROID_XU3_REV02,
+       EXYNOS5_BOARD_ODROID_XU4_REV01,
+       EXYNOS5_BOARD_ODROID_UNKNOWN,
+
+       EXYNOS5_BOARD_COUNT,
+};
+
+struct odroid_rev_info {
+       int board_type;
+       int board_rev;
+       int adc_val;
+       const char *name;
+};
+
+bool board_is_generic(void);
+bool board_is_odroidxu3(void);
+bool board_is_odroidxu4(void);
+
+#endif
diff --git a/include/sandbox-adc.h b/include/sandbox-adc.h
new file mode 100644 (file)
index 0000000..79ff01c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _SANDBOX_ADC_H_
+#define _SANDBOX_ADC_H_
+
+#define SANDBOX_ADC_DEVNAME            "adc@0"
+#define SANDBOX_ADC_DATA_MASK          0xffff /* 16-bits resolution */
+#define SANDBOX_ADC_CHANNELS           4
+#define SANDBOX_ADC_CHANNEL0_DATA      0x0
+#define SANDBOX_ADC_CHANNEL1_DATA      0x1000
+#define SANDBOX_ADC_CHANNEL2_DATA      0x2000
+#define SANDBOX_ADC_CHANNEL3_DATA      0x3000
+
+enum sandbox_adc_mode {
+       SANDBOX_ADC_MODE_SINGLE_CHANNEL = 0,
+       SANDBOX_ADC_MODE_MULTI_CHANNEL,
+};
+
+enum sandbox_adc_status {
+       SANDBOX_ADC_INACTIVE = 0,
+       SANDBOX_ADC_ACTIVE,
+};
+
+#define SANDBOX_ADC_VSS_VALUE          0
+
+#endif
index 757931a9cb25119b3283b12bc985310310dae4d0..63b704a3d719b178c79da4068a477aded2c80e9f 100644 (file)
@@ -36,3 +36,21 @@ int fdtdec_get_int(const void *blob, int node, const char *prop_name,
        debug("(not found)\n");
        return default_val;
 }
+
+unsigned int fdtdec_get_uint(const void *blob, int node, const char *prop_name,
+                       unsigned int default_val)
+{
+       const int *cell;
+       int len;
+
+       debug("%s: %s: ", __func__, prop_name);
+       cell = fdt_getprop(blob, node, prop_name, &len);
+       if (cell && len >= sizeof(unsigned int)) {
+               unsigned int val = fdt32_to_cpu(cell[0]);
+
+               debug("%#x (%d)\n", val, val);
+               return val;
+       }
+       debug("(not found)\n");
+       return default_val;
+}
index 7b3626cb32945e31eed962294ce163aeca5a164f..39630f68c878faae2e44bb49797c67fab7f9a238 100644 (file)
@@ -33,4 +33,5 @@ obj-y += syscon.o
 obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_REGULATOR) += regulator.o
+obj-$(CONFIG_ADC) += adc.o
 endif
diff --git a/test/dm/adc.c b/test/dm/adc.c
new file mode 100644 (file)
index 0000000..b0d4fe5
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Tests for the driver model ADC API
+ *
+ * Copyright (c) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <dm.h>
+#include <dm/root.h>
+#include <dm/util.h>
+#include <dm/test.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <power/regulator.h>
+#include <power/sandbox_pmic.h>
+#include <sandbox-adc.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int dm_test_adc_bind(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc", &dev));
+       ut_asserteq_str(SANDBOX_ADC_DEVNAME, dev->name);
+
+       return 0;
+}
+DM_TEST(dm_test_adc_bind, DM_TESTF_SCAN_FDT);
+
+static int dm_test_adc_wrong_channel_selection(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc", &dev));
+       ut_asserteq(-EINVAL, adc_start_channel(dev, SANDBOX_ADC_CHANNELS));
+
+       return 0;
+}
+DM_TEST(dm_test_adc_wrong_channel_selection, DM_TESTF_SCAN_FDT);
+
+static int dm_test_adc_supply(struct unit_test_state *uts)
+{
+       struct udevice *supply;
+       struct udevice *dev;
+       int uV;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc", &dev));
+
+       /* Test Vss value - predefined 0 uV */
+       ut_assertok(adc_vss_value(dev, &uV));
+       ut_asserteq(SANDBOX_ADC_VSS_VALUE, uV);
+
+       /* Test Vdd initial value - buck2 */
+       ut_assertok(adc_vdd_value(dev, &uV));
+       ut_asserteq(SANDBOX_BUCK2_INITIAL_EXPECTED_UV, uV);
+
+       /* Change Vdd value - buck2 manual preset */
+       ut_assertok(regulator_get_by_devname(SANDBOX_BUCK2_DEVNAME, &supply));
+       ut_assertok(regulator_set_value(supply, SANDBOX_BUCK2_SET_UV));
+       ut_asserteq(SANDBOX_BUCK2_SET_UV, regulator_get_value(supply));
+
+       /* Update ADC platdata and get new Vdd value */
+       ut_assertok(adc_vdd_value(dev, &uV));
+       ut_asserteq(SANDBOX_BUCK2_SET_UV, uV);
+
+       /* Disable buck2 and test ADC supply enable function */
+       ut_assertok(regulator_set_enable(supply, false));
+       ut_asserteq(false, regulator_get_enable(supply));
+       /* adc_start_channel() should enable the supply regulator */
+       ut_assertok(adc_start_channel(dev, 0));
+       ut_asserteq(true, regulator_get_enable(supply));
+
+       return 0;
+}
+DM_TEST(dm_test_adc_supply, DM_TESTF_SCAN_FDT);
+
+struct adc_channel adc_channel_test_data[] = {
+       { 0, SANDBOX_ADC_CHANNEL0_DATA },
+       { 1, SANDBOX_ADC_CHANNEL1_DATA },
+       { 2, SANDBOX_ADC_CHANNEL2_DATA },
+       { 3, SANDBOX_ADC_CHANNEL3_DATA },
+};
+
+static int dm_test_adc_single_channel_conversion(struct unit_test_state *uts)
+{
+       struct adc_channel *tdata = adc_channel_test_data;
+       unsigned int i, data;
+       struct udevice *dev;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc", &dev));
+       /* Test each ADC channel's value */
+       for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++) {
+               ut_assertok(adc_start_channel(dev, tdata->id));
+               ut_assertok(adc_channel_data(dev, tdata->id, &data));
+               ut_asserteq(tdata->data, data);
+       }
+
+       return 0;
+}
+DM_TEST(dm_test_adc_single_channel_conversion, DM_TESTF_SCAN_FDT);
+
+static int dm_test_adc_multi_channel_conversion(struct unit_test_state *uts)
+{
+       struct adc_channel channels[SANDBOX_ADC_CHANNELS];
+       struct udevice *dev;
+       struct adc_channel *tdata = adc_channel_test_data;
+       unsigned int i, channel_mask;
+
+       channel_mask = ADC_CHANNEL(0) | ADC_CHANNEL(1) |
+                      ADC_CHANNEL(2) | ADC_CHANNEL(3);
+
+       /* Start multi channel conversion */
+       ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc", &dev));
+       ut_assertok(adc_start_channels(dev, channel_mask));
+       ut_assertok(adc_channels_data(dev, channel_mask, channels));
+
+       /* Compare the expected and returned conversion data. */
+       for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++)
+               ut_asserteq(tdata->data, channels[i].data);
+
+       return 0;
+}
+DM_TEST(dm_test_adc_multi_channel_conversion, DM_TESTF_SCAN_FDT);
+
+static int dm_test_adc_single_channel_shot(struct unit_test_state *uts)
+{
+       struct adc_channel *tdata = adc_channel_test_data;
+       unsigned int i, data;
+
+       for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++) {
+               /* Start single channel conversion */
+               ut_assertok(adc_channel_single_shot("adc", tdata->id, &data));
+               /* Compare the expected and returned conversion data. */
+               ut_asserteq(tdata->data, data);
+       }
+
+       return 0;
+}
+DM_TEST(dm_test_adc_single_channel_shot, DM_TESTF_SCAN_FDT);
+
+static int dm_test_adc_multi_channel_shot(struct unit_test_state *uts)
+{
+       struct adc_channel channels[SANDBOX_ADC_CHANNELS];
+       struct adc_channel *tdata = adc_channel_test_data;
+       unsigned int i, channel_mask;
+
+       channel_mask = ADC_CHANNEL(0) | ADC_CHANNEL(1) |
+                      ADC_CHANNEL(2) | ADC_CHANNEL(3);
+
+       /* Start single call and multi channel conversion */
+       ut_assertok(adc_channels_single_shot("adc", channel_mask, channels));
+
+       /* Compare the expected and returned conversion data. */
+       for (i = 0; i < SANDBOX_ADC_CHANNELS; i++, tdata++)
+               ut_asserteq(tdata->data, channels[i].data);
+
+       return 0;
+}
+DM_TEST(dm_test_adc_multi_channel_shot, DM_TESTF_SCAN_FDT);