Merge git://git.denx.de/u-boot-dm

Fix a trivial conflict over adding <dm.h>

Conflicts:
	arch/arm/cpu/armv7/omap3/board.c

Signed-off-by: Tom Rini <trini@ti.com>
This commit is contained in:
Tom Rini 2014-10-26 14:03:08 -04:00
commit 84a6df09c7
75 changed files with 1447 additions and 1114 deletions

View File

@ -9,7 +9,9 @@
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <ns16550.h>
#include <spl.h>
#include <asm/arch/cpu.h>
#include <asm/arch/hardware.h>
@ -36,6 +38,63 @@
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_DM_GPIO
static const struct omap_gpio_platdata am33xx_gpio[] = {
{ 0, AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
{ 1, AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
{ 2, AM33XX_GPIO2_BASE, METHOD_GPIO_24XX },
{ 3, AM33XX_GPIO3_BASE, METHOD_GPIO_24XX },
#ifdef CONFIG_AM43XX
{ 4, AM33XX_GPIO4_BASE, METHOD_GPIO_24XX },
{ 5, AM33XX_GPIO5_BASE, METHOD_GPIO_24XX },
#endif
};
U_BOOT_DEVICES(am33xx_gpios) = {
{ "gpio_omap", &am33xx_gpio[0] },
{ "gpio_omap", &am33xx_gpio[1] },
{ "gpio_omap", &am33xx_gpio[2] },
{ "gpio_omap", &am33xx_gpio[3] },
#ifdef CONFIG_AM43XX
{ "gpio_omap", &am33xx_gpio[4] },
{ "gpio_omap", &am33xx_gpio[5] },
#endif
};
# ifndef CONFIG_OF_CONTROL
/*
* TODO(sjg@chromium.org): When we can move SPL serial to DM, we can remove
* the CONFIGs. At the same time, we should move this to the board files.
*/
static const struct ns16550_platdata am33xx_serial[] = {
{ CONFIG_SYS_NS16550_COM1, 2, CONFIG_SYS_NS16550_CLK },
# ifdef CONFIG_SYS_NS16550_COM2
{ CONFIG_SYS_NS16550_COM2, 2, CONFIG_SYS_NS16550_CLK },
# ifdef CONFIG_SYS_NS16550_COM3
{ CONFIG_SYS_NS16550_COM3, 2, CONFIG_SYS_NS16550_CLK },
{ CONFIG_SYS_NS16550_COM4, 2, CONFIG_SYS_NS16550_CLK },
{ CONFIG_SYS_NS16550_COM5, 2, CONFIG_SYS_NS16550_CLK },
{ CONFIG_SYS_NS16550_COM6, 2, CONFIG_SYS_NS16550_CLK },
# endif
# endif
};
U_BOOT_DEVICES(am33xx_uarts) = {
{ "serial_omap", &am33xx_serial[0] },
# ifdef CONFIG_SYS_NS16550_COM2
{ "serial_omap", &am33xx_serial[1] },
# ifdef CONFIG_SYS_NS16550_COM3
{ "serial_omap", &am33xx_serial[2] },
{ "serial_omap", &am33xx_serial[3] },
{ "serial_omap", &am33xx_serial[4] },
{ "serial_omap", &am33xx_serial[5] },
# endif
# endif
};
# endif
#else
static const struct gpio_bank gpio_bank_am33xx[] = {
{ (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
@ -49,6 +108,8 @@ static const struct gpio_bank gpio_bank_am33xx[] = {
const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx;
#endif
#if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)
int cpu_mmc_init(bd_t *bis)
{

View File

@ -17,6 +17,7 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <mmc.h>
#include <spl.h>
#include <asm/io.h>
@ -24,7 +25,7 @@
#include <asm/arch/mem.h>
#include <asm/cache.h>
#include <asm/armv7.h>
#include <asm/arch/gpio.h>
#include <asm/gpio.h>
#include <asm/omap_common.h>
#include <asm/arch/mmc_host_def.h>
#include <i2c.h>
@ -39,6 +40,27 @@ static void omap3_setup_aux_cr(void);
static void omap3_invalidate_l2_cache_secure(void);
#endif
#ifdef CONFIG_DM_GPIO
static const struct omap_gpio_platdata omap34xx_gpio[] = {
{ 0, OMAP34XX_GPIO1_BASE, METHOD_GPIO_24XX },
{ 1, OMAP34XX_GPIO2_BASE, METHOD_GPIO_24XX },
{ 2, OMAP34XX_GPIO3_BASE, METHOD_GPIO_24XX },
{ 3, OMAP34XX_GPIO4_BASE, METHOD_GPIO_24XX },
{ 4, OMAP34XX_GPIO5_BASE, METHOD_GPIO_24XX },
{ 5, OMAP34XX_GPIO6_BASE, METHOD_GPIO_24XX },
};
U_BOOT_DEVICES(am33xx_gpios) = {
{ "gpio_omap", &omap34xx_gpio[0] },
{ "gpio_omap", &omap34xx_gpio[1] },
{ "gpio_omap", &omap34xx_gpio[2] },
{ "gpio_omap", &omap34xx_gpio[3] },
{ "gpio_omap", &omap34xx_gpio[4] },
{ "gpio_omap", &omap34xx_gpio[5] },
};
#else
static const struct gpio_bank gpio_bank_34xx[6] = {
{ (void *)OMAP34XX_GPIO1_BASE, METHOD_GPIO_24XX },
{ (void *)OMAP34XX_GPIO2_BASE, METHOD_GPIO_24XX },
@ -50,6 +72,8 @@ static const struct gpio_bank gpio_bank_34xx[6] = {
const struct gpio_bank *const omap_gpio_bank = gpio_bank_34xx;
#endif
#ifdef CONFIG_SPL_BUILD
/*
* We use static variables because global data is not ready yet.

View File

@ -3,6 +3,7 @@
#
obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
obj-y += platdevice.o
obj-y += boot-mode.o
obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o bcu_init.o \
sbc_init.o sg_init.o pll_init.o clkrst_init.o pinctrl.o

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2014 Panasonic Corporation
* Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/arch/platdevice.h>
#define UART_MASTER_CLK 36864000
SERIAL_DEVICE(0, 0x54006800, UART_MASTER_CLK)
SERIAL_DEVICE(1, 0x54006900, UART_MASTER_CLK)
SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)

View File

@ -3,6 +3,7 @@
#
obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
obj-y += platdevice.o
obj-y += boot-mode.o
obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o sbc_init.o \
sg_init.o pll_init.o clkrst_init.o pinctrl.o

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2014 Panasonic Corporation
* Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/arch/platdevice.h>
#define UART_MASTER_CLK 73728000
SERIAL_DEVICE(0, 0x54006800, UART_MASTER_CLK)
SERIAL_DEVICE(1, 0x54006900, UART_MASTER_CLK)
SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)

View File

@ -3,6 +3,7 @@
#
obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
obj-y += platdevice.o
obj-y += boot-mode.o
obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o bcu_init.o \
sbc_init.o sg_init.o pll_init.o clkrst_init.o pinctrl.o

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2014 Panasonic Corporation
* Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/arch/platdevice.h>
#define UART_MASTER_CLK 80000000
SERIAL_DEVICE(0, 0x54006800, UART_MASTER_CLK)
SERIAL_DEVICE(1, 0x54006900, UART_MASTER_CLK)
SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)

View File

@ -10,6 +10,10 @@
model = "TI AM335x BeagleBone";
compatible = "ti,am335x-bone", "ti,am33xx";
chosen {
stdout-path = &uart0;
};
cpus {
cpu@0 {
cpu0-supply = <&dcdc2_reg>;

View File

@ -1,15 +0,0 @@
/*
* This header provides constants for most GPIO bindings.
*
* Most GPIO bindings include a flags cell as part of the GPIO specifier.
* In most cases, the format of the flags cell uses the standard values
* defined in this header.
*/
#ifndef _DT_BINDINGS_GPIO_GPIO_H
#define _DT_BINDINGS_GPIO_GPIO_H
#define GPIO_ACTIVE_HIGH 0
#define GPIO_ACTIVE_LOW 1
#endif

View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2014 Panasonic Corporation
* Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef ARCH_PLATDEVICE_H
#define ARCH_PLATDEVICE_H
#include <dm/platdata.h>
#include <dm/platform_data/serial-uniphier.h>
#define SERIAL_DEVICE(n, ba, clk) \
static struct uniphier_serial_platform_data serial_device##n = { \
.base = ba, \
.uartclk = clk \
}; \
U_BOOT_DEVICE(serial##n) = { \
.name = DRIVER_NAME, \
.platdata = &serial_device##n \
};
#endif /* ARCH_PLATDEVICE_H */

View File

@ -23,6 +23,21 @@
#include <asm/arch/cpu.h>
enum gpio_method {
METHOD_GPIO_24XX = 4,
};
#ifdef CONFIG_DM_GPIO
/* Information about a GPIO bank */
struct omap_gpio_platdata {
int bank_index;
ulong base; /* address of registers in physical memory */
enum gpio_method method;
};
#else
struct gpio_bank {
void *base;
int method;
@ -30,8 +45,6 @@ struct gpio_bank {
extern const struct gpio_bank *const omap_gpio_bank;
#define METHOD_GPIO_24XX 4
/**
* Check if gpio is valid.
*
@ -39,4 +52,6 @@ extern const struct gpio_bank *const omap_gpio_bank;
* @return 1 if ok, 0 on error
*/
int gpio_is_valid(int gpio);
#endif
#endif /* _GPIO_H_ */

View File

@ -85,12 +85,25 @@ car_init_ret:
/* Align global data to 16-byte boundary */
andl $0xfffffff0, %esp
/* Zero the global data since it won't happen later */
xorl %eax, %eax
movl $GENERATED_GBL_DATA_SIZE, %ecx
movl %esp, %edi
rep stosb
/* Setup first parameter to setup_gdt */
movl %esp, %eax
/* Reserve space for global descriptor table */
subl $X86_GDT_SIZE, %esp
#if defined(CONFIG_SYS_MALLOC_F_LEN)
subl $CONFIG_SYS_MALLOC_F_LEN, %esp
movl %eax, %edx
addl $GD_MALLOC_BASE, %edx
movl %esp, (%edx)
#endif
/* Align temporary global descriptor table to 16-byte boundary */
andl $0xfffffff0, %esp

View File

@ -1,13 +1,14 @@
/include/ "skeleton.dtsi"
/ {
aliases {
console = "/serial";
chosen {
stdout-path = "/serial";
};
serial {
compatible = "ns16550";
reg-shift = <1>;
compatible = "coreboot-uart";
reg = <0x3f8 0x10>;
reg-shift = <0>;
io-mapped = <1>;
multiplier = <1>;
baudrate = <115200>;

View File

@ -12,7 +12,23 @@
silent_console = <0>;
};
gpio: gpio {};
gpioa {
compatible = "intel,ich6-gpio";
reg = <0 0x10>;
bank-name = "A";
};
gpiob {
compatible = "intel,ich6-gpio";
reg = <0x30 0x10>;
bank-name = "B";
};
gpioc {
compatible = "intel,ich6-gpio";
reg = <0x40 0x10>;
bank-name = "C";
};
serial {
reg = <0x3f8 8>;

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2014, Google Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _X86_ARCH_GPIO_H_
#define _X86_ARCH_GPIO_H_
struct ich6_bank_platdata {
uint32_t base_addr;
const char *bank_name;
};
#endif /* _X86_ARCH_GPIO_H_ */

View File

@ -6,6 +6,7 @@
#ifndef _X86_GPIO_H_
#define _X86_GPIO_H_
#include <asm/arch/gpio.h>
#include <asm-generic/gpio.h>
#endif /* _X86_GPIO_H_ */

View File

@ -18,14 +18,4 @@
#define SYSCTLA 0x92
#define SLAVE_PIC 0xa0
#if 1
#define UART0_BASE 0x3f8
#define UART1_BASE 0x2f8
#else
/* FixMe: uarts swapped */
#define UART0_BASE 0x2f8
#define UART1_BASE 0x3f8
#endif
#endif

View File

@ -282,7 +282,6 @@ void boot_zimage(void *setup_base, void *load_address)
:: [kernel_entry]"a"(load_address),
[boot_params] "S"(setup_base),
"b"(0), "D"(0)
: "%ebp"
);
}

View File

@ -15,7 +15,6 @@
#include <netdev.h>
#include <fdt_support.h>
#include <sata.h>
#include <serial_mxc.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/iomux.h>
@ -23,6 +22,7 @@
#include <asm/imx-common/sata.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <dm/platform_data/serial_mxc.h>
#include "common.h"
#include "../common/eeprom.h"

View File

@ -5,6 +5,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <ns16550.h>
#include <twl4030.h>
#include <netdev.h>
#include <asm/gpio.h>
@ -30,6 +32,17 @@ static const u32 gpmc_lan_config[] = {
};
#endif
static const struct ns16550_platdata igep_serial = {
OMAP34XX_UART3,
2,
V_NS16550_CLK
};
U_BOOT_DEVICE(igep_uart) = {
"serial_omap",
&igep_serial
};
/*
* Routine: board_init
* Description: Early hardware init.

View File

@ -15,6 +15,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <ns16550.h>
#include <netdev.h>
#include <twl4030.h>
#include <asm/io.h>
@ -41,6 +43,17 @@ static const u32 gpmc_lab_enet[] = {
/*CONF7- computed as params */
};
static const struct ns16550_platdata zoom1_serial = {
OMAP34XX_UART3,
2,
V_NS16550_CLK
};
U_BOOT_DEVICE(zoom1_uart) = {
"serial_omap",
&zoom1_serial
};
/*
* Routine: board_init
* Description: Early hardware init.

View File

@ -13,6 +13,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <ns16550.h>
#include <netdev.h>
#include <twl4030.h>
#include <linux/mtd/nand.h>
@ -73,6 +75,17 @@ static const u32 gpmc_lan_config[] = {
/*CONFIG7- computed as params */
};
static const struct ns16550_platdata overo_serial = {
OMAP34XX_UART3,
2,
V_NS16550_CLK
};
U_BOOT_DEVICE(overo_uart) = {
"serial_omap",
&overo_serial
};
/*
* Routine: board_init
* Description: Early hardware init.

View File

@ -14,6 +14,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <ns16550.h>
#ifdef CONFIG_STATUS_LED
#include <status_led.h>
#endif
@ -70,6 +72,17 @@ static struct {
char env_setting[64];
} expansion_config;
static const struct ns16550_platdata beagle_serial = {
OMAP34XX_UART3,
2,
V_NS16550_CLK
};
U_BOOT_DEVICE(beagle_uart) = {
"serial_omap",
&beagle_serial
};
/*
* Routine: board_init
* Description: Early hardware init.
@ -103,12 +116,12 @@ int board_init(void)
*/
static int get_board_revision(void)
{
int revision;
if (!gpio_request(171, "") &&
!gpio_request(172, "") &&
!gpio_request(173, "")) {
static int revision = -1;
if (revision == -1) {
if (!gpio_request(171, "rev0") &&
!gpio_request(172, "rev1") &&
!gpio_request(173, "rev2")) {
gpio_direction_input(171);
gpio_direction_input(172);
gpio_direction_input(173);
@ -118,7 +131,7 @@ static int get_board_revision(void)
gpio_get_value(171);
} else {
printf("Error: unable to acquire board revision GPIOs\n");
revision = -1;
}
}
return revision;
@ -258,7 +271,7 @@ static void beagle_dvi_pup(void)
case REVISION_AXBX:
case REVISION_CX:
case REVISION_C4:
gpio_request(170, "");
gpio_request(170, "dvi");
gpio_direction_output(170, 0);
gpio_set_value(170, 1);
break;

View File

@ -27,47 +27,46 @@ void green_led_on(void)
}
#endif
static int get_led_gpio(led_id_t mask)
{
#ifdef STATUS_LED_BIT
if (STATUS_LED_BIT & mask)
return BEAGLE_LED_USR0;
#endif
#ifdef STATUS_LED_BIT1
if (STATUS_LED_BIT1 & mask)
return BEAGLE_LED_USR1;
#endif
return 0;
}
void __led_init (led_id_t mask, int state)
{
int toggle_gpio;
toggle_gpio = get_led_gpio(mask);
if (toggle_gpio && !gpio_request(toggle_gpio, "led"))
__led_set(mask, state);
}
void __led_toggle (led_id_t mask)
{
int state, toggle_gpio = 0;
#ifdef STATUS_LED_BIT
if (!toggle_gpio && STATUS_LED_BIT & mask)
toggle_gpio = BEAGLE_LED_USR0;
#endif
#ifdef STATUS_LED_BIT1
if (!toggle_gpio && STATUS_LED_BIT1 & mask)
toggle_gpio = BEAGLE_LED_USR1;
#endif
int state, toggle_gpio;
toggle_gpio = get_led_gpio(mask);
if (toggle_gpio) {
if (!gpio_request(toggle_gpio, "")) {
gpio_direction_output(toggle_gpio, 0);
state = gpio_get_value(toggle_gpio);
gpio_set_value(toggle_gpio, !state);
}
gpio_direction_output(toggle_gpio, !state);
}
}
void __led_set (led_id_t mask, int state)
{
#ifdef STATUS_LED_BIT
if (STATUS_LED_BIT & mask) {
if (!gpio_request(BEAGLE_LED_USR0, "")) {
gpio_direction_output(BEAGLE_LED_USR0, 0);
gpio_set_value(BEAGLE_LED_USR0, state);
}
}
#endif
#ifdef STATUS_LED_BIT1
if (STATUS_LED_BIT1 & mask) {
if (!gpio_request(BEAGLE_LED_USR1, "")) {
gpio_direction_output(BEAGLE_LED_USR1, 0);
gpio_set_value(BEAGLE_LED_USR1, state);
}
}
#endif
int toggle_gpio;
toggle_gpio = get_led_gpio(mask);
if (toggle_gpio)
gpio_direction_output(toggle_gpio, state);
}

View File

@ -25,13 +25,6 @@ enum gpio_cmd {
};
#if defined(CONFIG_DM_GPIO) && !defined(gpio_status)
static const char * const gpio_function[GPIOF_COUNT] = {
"input",
"output",
"unused",
"unknown",
"func",
};
/* A few flags used by show_gpio() */
enum {
@ -40,22 +33,16 @@ enum {
FLAG_SHOW_NEWLINE = 1 << 2,
};
static void show_gpio(struct udevice *dev, const char *bank_name, int offset,
int *flagsp)
static void gpio_get_description(struct udevice *dev, const char *bank_name,
int offset, int *flagsp)
{
struct dm_gpio_ops *ops = gpio_get_ops(dev);
int func = GPIOF_UNKNOWN;
char buf[80];
int ret;
BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
if (ops->get_function) {
ret = ops->get_function(dev, offset);
if (ret >= 0 && ret < ARRAY_SIZE(gpio_function))
func = ret;
}
if (!(*flagsp & FLAG_SHOW_ALL) && func == GPIOF_UNUSED)
ret = gpio_get_function(dev, offset, NULL);
if (ret < 0)
goto err;
if (!(*flagsp & FLAG_SHOW_ALL) && ret == GPIOF_UNUSED)
return;
if ((*flagsp & FLAG_SHOW_BANK) && bank_name) {
if (*flagsp & FLAG_SHOW_NEWLINE) {
@ -65,20 +52,15 @@ static void show_gpio(struct udevice *dev, const char *bank_name, int offset,
printf("Bank %s:\n", bank_name);
*flagsp &= ~FLAG_SHOW_BANK;
}
*buf = '\0';
if (ops->get_state) {
ret = ops->get_state(dev, offset, buf, sizeof(buf));
if (ret) {
puts("<unknown>");
return;
}
} else {
sprintf(buf, "%s%u: %8s %d", bank_name, offset,
gpio_function[func], ops->get_value(dev, offset));
}
puts(buf);
puts("\n");
ret = gpio_get_status(dev, offset, buf, sizeof(buf));
if (ret)
goto err;
printf("%s\n", buf);
return;
err:
printf("Error %d\n", ret);
}
static int do_gpio_status(bool all, const char *gpio_name)
@ -101,8 +83,10 @@ static int do_gpio_status(bool all, const char *gpio_name)
if (all)
flags |= FLAG_SHOW_ALL;
bank_name = gpio_get_bank_info(dev, &num_bits);
if (!num_bits)
if (!num_bits) {
debug("GPIO device %s has no bits\n", dev->name);
continue;
}
banklen = bank_name ? strlen(bank_name) : 0;
if (!gpio_name || !bank_name ||
@ -113,11 +97,12 @@ static int do_gpio_status(bool all, const char *gpio_name)
p = gpio_name + banklen;
if (gpio_name && *p) {
offset = simple_strtoul(p, NULL, 10);
show_gpio(dev, bank_name, offset, &flags);
gpio_get_description(dev, bank_name, offset,
&flags);
} else {
for (offset = 0; offset < num_bits; offset++) {
show_gpio(dev, bank_name, offset,
&flags);
gpio_get_description(dev, bank_name,
offset, &flags);
}
}
}

View File

@ -1,4 +1,4 @@
CONFIG_SPL=y
CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1,EMMC_BOOT"
CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
+S:CONFIG_ARM=y
+S:CONFIG_TARGET_AM335X_EVM=y

View File

@ -1,5 +1,5 @@
CONFIG_SPL=y
CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1,EMMC_BOOT,ENABLE_VBOOT"
CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT,ENABLE_VBOOT"
+S:CONFIG_ARM=y
+S:CONFIG_TARGET_AM335X_EVM=y
CONFIG_OF_CONTROL=y

View File

@ -2,7 +2,10 @@ CONFIG_SPL=y
+S:CONFIG_ARM=y
+S:CONFIG_ARCH_UNIPHIER=y
+S:CONFIG_MACH_PH1_LD4=y
CONFIG_DM=y
CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
CONFIG_DM_SERIAL=y
CONFIG_UNIPHIER_SERIAL=y
S:CONFIG_SPL_NAND_DENALI=y

View File

@ -2,7 +2,10 @@ CONFIG_SPL=y
+S:CONFIG_ARM=y
+S:CONFIG_ARCH_UNIPHIER=y
+S:CONFIG_MACH_PH1_PRO4=y
CONFIG_DM=y
CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
CONFIG_DM_SERIAL=y
CONFIG_UNIPHIER_SERIAL=y
S:CONFIG_SPL_NAND_DENALI=y

View File

@ -2,7 +2,10 @@ CONFIG_SPL=y
+S:CONFIG_ARM=y
+S:CONFIG_ARCH_UNIPHIER=y
+S:CONFIG_MACH_PH1_SLD8=y
CONFIG_DM=y
CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
CONFIG_DM_SERIAL=y
CONFIG_UNIPHIER_SERIAL=y
S:CONFIG_SPL_NAND_DENALI=y

View File

@ -95,7 +95,7 @@ are provided in test/dm. To run them, try:
You should see something like this:
<...U-Boot banner...>
Running 22 driver model tests
Running 29 driver model tests
Test: dm_test_autobind
Test: dm_test_autoprobe
Test: dm_test_bus_children
@ -115,7 +115,12 @@ You should see something like this:
Device 'd-test': seq 3 is in use by 'b-test'
Device 'a-test': seq 0 is in use by 'd-test'
Test: dm_test_gpio
sandbox_gpio: sb_gpio_get_value: error: offset 4 not reserved
extra-gpios: get_value: error: gpio b5 not reserved
Test: dm_test_gpio_anon
Test: dm_test_gpio_copy
Test: dm_test_gpio_leak
extra-gpios: get_value: error: gpio b5 not reserved
Test: dm_test_gpio_requestf
Test: dm_test_leak
Test: dm_test_lifecycle
Test: dm_test_operations
@ -123,6 +128,26 @@ You should see something like this:
Test: dm_test_platdata
Test: dm_test_pre_reloc
Test: dm_test_remove
Test: dm_test_spi_find
Invalid chip select 0:0 (err=-19)
SF: Failed to get idcodes
Device 'name-emul': seq 0 is in use by 'name-emul'
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
Test: dm_test_spi_flash
2097152 bytes written in 0 ms
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
SPI flash test:
0 erase: 0 ticks, 65536000 KiB/s 524288.000 Mbps
1 check: 0 ticks, 65536000 KiB/s 524288.000 Mbps
2 write: 0 ticks, 65536000 KiB/s 524288.000 Mbps
3 read: 0 ticks, 65536000 KiB/s 524288.000 Mbps
Test passed
0 erase: 0 ticks, 65536000 KiB/s 524288.000 Mbps
1 check: 0 ticks, 65536000 KiB/s 524288.000 Mbps
2 write: 0 ticks, 65536000 KiB/s 524288.000 Mbps
3 read: 0 ticks, 65536000 KiB/s 524288.000 Mbps
Test: dm_test_spi_xfer
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
Test: dm_test_uclass
Test: dm_test_uclass_before_ready
Failures: 0

View File

@ -0,0 +1,6 @@
config DM
bool "Enable Driver Model"
depends on !SPL_BUILD
help
This config option enables Driver Model.
To use legacy drivers, say N.

View File

@ -0,0 +1,6 @@
config DM_GPIO
bool "Enable Driver Model for GPIO drivers"
depends on DM
help
If you want to use driver model for GPIO drivers, say Y.
To use legacy GPIO drivers, say N.

View File

@ -11,67 +11,10 @@
#include <asm/gpio.h>
#include <asm/io.h>
#define GPIO_NAME_SIZE 20
struct bcm2835_gpios {
char label[BCM2835_GPIO_COUNT][GPIO_NAME_SIZE];
struct bcm2835_gpio_regs *reg;
};
/**
* gpio_is_requested() - check if a GPIO has been requested
*
* @bank: Bank to check
* @offset: GPIO offset within bank to check
* @return true if marked as requested, false if not
*/
static inline bool gpio_is_requested(struct bcm2835_gpios *gpios, int offset)
{
return *gpios->label[offset] != '\0';
}
static int check_requested(struct udevice *dev, unsigned offset,
const char *func)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
if (!gpio_is_requested(gpios, offset)) {
printf("omap_gpio: %s: error: gpio %s%d not requested\n",
func, uc_priv->bank_name, offset);
return -EPERM;
}
return 0;
}
static int bcm2835_gpio_request(struct udevice *dev, unsigned offset,
const char *label)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
if (gpio_is_requested(gpios, offset))
return -EBUSY;
strncpy(gpios->label[offset], label, GPIO_NAME_SIZE);
gpios->label[offset][GPIO_NAME_SIZE - 1] = '\0';
return 0;
}
static int bcm2835_gpio_free(struct udevice *dev, unsigned offset)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
int ret;
ret = check_requested(dev, offset, __func__);
if (ret)
return ret;
gpios->label[offset][0] = '\0';
return 0;
}
static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
@ -142,9 +85,6 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
if (!gpio_is_requested(gpios, offset))
return GPIOF_UNUSED;
/* GPIOF_FUNC is not implemented yet */
if (bcm2835_gpio_is_output(gpios, offset))
return GPIOF_OUTPUT;
@ -152,42 +92,13 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
static int bcm2835_gpio_get_state(struct udevice *dev, unsigned int offset,
char *buf, int bufsize)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct bcm2835_gpios *gpios = dev_get_priv(dev);
const char *label;
bool requested;
bool is_output;
int size;
label = gpios->label[offset];
is_output = bcm2835_gpio_is_output(gpios, offset);
size = snprintf(buf, bufsize, "%s%d: ",
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
buf += size;
bufsize -= size;
requested = gpio_is_requested(gpios, offset);
snprintf(buf, bufsize, "%s: %d [%c]%s%s",
is_output ? "out" : " in",
bcm2835_get_value(gpios, offset),
requested ? 'x' : ' ',
requested ? " " : "",
label);
return 0;
}
static const struct dm_gpio_ops gpio_bcm2835_ops = {
.request = bcm2835_gpio_request,
.free = bcm2835_gpio_free,
.direction_input = bcm2835_gpio_direction_input,
.direction_output = bcm2835_gpio_direction_output,
.get_value = bcm2835_gpio_get_value,
.set_value = bcm2835_gpio_set_value,
.get_function = bcm2835_gpio_get_function,
.get_state = bcm2835_gpio_get_state,
};
static int bcm2835_gpio_probe(struct udevice *dev)

View File

@ -7,7 +7,9 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <asm/gpio.h>
#include <linux/ctype.h>
/**
* gpio_to_device() - Convert global GPIO number to device, number
@ -43,35 +45,47 @@ static int gpio_to_device(unsigned int gpio, struct udevice **devp,
int gpio_lookup_name(const char *name, struct udevice **devp,
unsigned int *offsetp, unsigned int *gpiop)
{
struct gpio_dev_priv *uc_priv;
struct gpio_dev_priv *uc_priv = NULL;
struct udevice *dev;
ulong offset;
int numeric;
int ret;
if (devp)
*devp = NULL;
numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
for (ret = uclass_first_device(UCLASS_GPIO, &dev);
dev;
ret = uclass_next_device(&dev)) {
ulong offset;
int len;
uc_priv = dev->uclass_priv;
if (numeric != -1) {
offset = numeric - uc_priv->gpio_base;
/* Allow GPIOs to be numbered from 0 */
if (offset >= 0 && offset < uc_priv->gpio_count)
break;
}
len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
if (!strncasecmp(name, uc_priv->bank_name, len)) {
if (strict_strtoul(name + len, 10, &offset))
continue;
if (!strict_strtoul(name + len, 10, &offset))
break;
}
}
if (!dev)
return ret ? ret : -EINVAL;
if (devp)
*devp = dev;
if (offsetp)
*offsetp = offset;
if (gpiop)
*gpiop = uc_priv->gpio_base + offset;
return 0;
}
}
return ret ? ret : -EINVAL;
return 0;
}
/**
@ -79,24 +93,62 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
* gpio: GPIO number
* label: Name for the requested GPIO
*
* The label is copied and allocated so the caller does not need to keep
* the pointer around.
*
* This function implements the API that's compatible with current
* GPIO API used in U-Boot. The request is forwarded to particular
* GPIO driver. Returns 0 on success, negative value on error.
*/
int gpio_request(unsigned gpio, const char *label)
{
struct gpio_dev_priv *uc_priv;
unsigned int offset;
struct udevice *dev;
char *str;
int ret;
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
if (!gpio_get_ops(dev)->request)
return 0;
uc_priv = dev->uclass_priv;
if (uc_priv->name[offset])
return -EBUSY;
str = strdup(label);
if (!str)
return -ENOMEM;
if (gpio_get_ops(dev)->request) {
ret = gpio_get_ops(dev)->request(dev, offset, label);
if (ret) {
free(str);
return ret;
}
}
uc_priv->name[offset] = str;
return gpio_get_ops(dev)->request(dev, offset, label);
return 0;
}
/**
* gpio_requestf() - [COMPAT] Request GPIO
* @gpio: GPIO number
* @fmt: Format string for the requested GPIO
* @...: Arguments for the printf() format string
*
* This function implements the API that's compatible with current
* GPIO API used in U-Boot. The request is forwarded to particular
* GPIO driver. Returns 0 on success, negative value on error.
*/
int gpio_requestf(unsigned gpio, const char *fmt, ...)
{
va_list args;
char buf[40];
va_start(args, fmt);
vscnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
return gpio_request(gpio, buf);
}
/**
@ -109,6 +161,7 @@ int gpio_request(unsigned gpio, const char *label)
*/
int gpio_free(unsigned gpio)
{
struct gpio_dev_priv *uc_priv;
unsigned int offset;
struct udevice *dev;
int ret;
@ -117,9 +170,34 @@ int gpio_free(unsigned gpio)
if (ret)
return ret;
if (!gpio_get_ops(dev)->free)
uc_priv = dev->uclass_priv;
if (!uc_priv->name[offset])
return -ENXIO;
if (gpio_get_ops(dev)->free) {
ret = gpio_get_ops(dev)->free(dev, offset);
if (ret)
return ret;
}
free(uc_priv->name[offset]);
uc_priv->name[offset] = NULL;
return 0;
}
static int check_reserved(struct udevice *dev, unsigned offset,
const char *func)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
if (!uc_priv->name[offset]) {
printf("%s: %s: error: gpio %s%d not reserved\n",
dev->name, func,
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
return -EBUSY;
}
return 0;
return gpio_get_ops(dev)->free(dev, offset);
}
/**
@ -139,8 +217,9 @@ int gpio_direction_input(unsigned gpio)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
ret = check_reserved(dev, offset, "dir_input");
return gpio_get_ops(dev)->direction_input(dev, offset);
return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
}
/**
@ -161,8 +240,10 @@ int gpio_direction_output(unsigned gpio, int value)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
ret = check_reserved(dev, offset, "dir_output");
return gpio_get_ops(dev)->direction_output(dev, offset, value);
return ret ? ret :
gpio_get_ops(dev)->direction_output(dev, offset, value);
}
/**
@ -183,8 +264,9 @@ int gpio_get_value(unsigned gpio)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
ret = check_reserved(dev, offset, "get_value");
return gpio_get_ops(dev)->get_value(dev, offset);
return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
}
/**
@ -205,8 +287,9 @@ int gpio_set_value(unsigned gpio, int value)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
ret = check_reserved(dev, offset, "set_value");
return gpio_get_ops(dev)->set_value(dev, offset, value);
return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
}
const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
@ -221,8 +304,94 @@ const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
return priv->bank_name;
}
static const char * const gpio_function[GPIOF_COUNT] = {
"input",
"output",
"unused",
"unknown",
"func",
};
int get_function(struct udevice *dev, int offset, bool skip_unused,
const char **namep)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct dm_gpio_ops *ops = gpio_get_ops(dev);
BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
if (!device_active(dev))
return -ENODEV;
if (offset < 0 || offset >= uc_priv->gpio_count)
return -EINVAL;
if (namep)
*namep = uc_priv->name[offset];
if (skip_unused && !uc_priv->name[offset])
return GPIOF_UNUSED;
if (ops->get_function) {
int ret;
ret = ops->get_function(dev, offset);
if (ret < 0)
return ret;
if (ret >= ARRAY_SIZE(gpio_function))
return -ENODATA;
return ret;
}
return GPIOF_UNKNOWN;
}
int gpio_get_function(struct udevice *dev, int offset, const char **namep)
{
return get_function(dev, offset, true, namep);
}
int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
{
return get_function(dev, offset, false, namep);
}
int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
{
struct dm_gpio_ops *ops = gpio_get_ops(dev);
struct gpio_dev_priv *priv;
char *str = buf;
int func;
int ret;
int len;
BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
*buf = 0;
priv = dev->uclass_priv;
ret = gpio_get_raw_function(dev, offset, NULL);
if (ret < 0)
return ret;
func = ret;
len = snprintf(str, buffsize, "%s%d: %s",
priv->bank_name ? priv->bank_name : "",
offset, gpio_function[func]);
if (func == GPIOF_INPUT || func == GPIOF_OUTPUT ||
func == GPIOF_UNUSED) {
const char *label;
bool used;
ret = ops->get_value(dev, offset);
if (ret < 0)
return ret;
used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
ret,
used ? 'x' : ' ',
used ? " " : "",
label ? label : "");
}
return 0;
}
/* We need to renumber the GPIOs when any driver is probed/removed */
static int gpio_renumber(void)
static int gpio_renumber(struct udevice *removed_dev)
{
struct gpio_dev_priv *uc_priv;
struct udevice *dev;
@ -237,7 +406,7 @@ static int gpio_renumber(void)
/* Ensure that we have a base for each bank */
base = 0;
uclass_foreach_dev(dev, uc) {
if (device_active(dev)) {
if (device_active(dev) && dev != removed_dev) {
uc_priv = dev->uclass_priv;
uc_priv->gpio_base = base;
base += uc_priv->gpio_count;
@ -249,12 +418,27 @@ static int gpio_renumber(void)
static int gpio_post_probe(struct udevice *dev)
{
return gpio_renumber();
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
if (!uc_priv->name)
return -ENOMEM;
return gpio_renumber(NULL);
}
static int gpio_pre_remove(struct udevice *dev)
{
return gpio_renumber();
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
int i;
for (i = 0; i < uc_priv->gpio_count; i++) {
if (uc_priv->name[i])
free(uc_priv->name[i]);
}
free(uc_priv->name);
return gpio_renumber(dev);
}
UCLASS_DRIVER(gpio) = {

View File

@ -27,88 +27,46 @@
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <pci.h>
#include <asm/gpio.h>
#include <asm/io.h>
#define GPIO_PER_BANK 32
/* Where in config space is the register that points to the GPIO registers? */
#define PCI_CFG_GPIOBASE 0x48
#define NUM_BANKS 3
/* Within the I/O space, where are the registers to control the GPIOs? */
static struct {
u8 use_sel;
u8 io_sel;
u8 lvl;
} gpio_bank[NUM_BANKS] = {
{ 0x00, 0x04, 0x0c }, /* Bank 0 */
{ 0x30, 0x34, 0x38 }, /* Bank 1 */
{ 0x40, 0x44, 0x48 } /* Bank 2 */
struct ich6_bank_priv {
/* These are I/O addresses */
uint32_t use_sel;
uint32_t io_sel;
uint32_t lvl;
};
static pci_dev_t dev; /* handle for 0:1f:0 */
static u32 gpiobase; /* offset into I/O space */
static int found_it_once; /* valid GPIO device? */
static u32 lock[NUM_BANKS]; /* "lock" for access to pins */
static int bad_arg(int num, int *bank, int *bitnum)
{
int i = num / 32;
int j = num % 32;
if (num < 0 || i > NUM_BANKS) {
debug("%s: bogus gpio num: %d\n", __func__, num);
return -1;
}
*bank = i;
*bitnum = j;
return 0;
}
static int mark_gpio(int bank, int bitnum)
{
if (lock[bank] & (1UL << bitnum)) {
debug("%s: %d.%d already marked\n", __func__, bank, bitnum);
return -1;
}
lock[bank] |= (1 << bitnum);
return 0;
}
static void clear_gpio(int bank, int bitnum)
{
lock[bank] &= ~(1 << bitnum);
}
static int notmine(int num, int *bank, int *bitnum)
{
if (bad_arg(num, bank, bitnum))
return -1;
return !(lock[*bank] & (1UL << *bitnum));
}
static int gpio_init(void)
static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
{
struct ich6_bank_platdata *plat = dev_get_platdata(dev);
pci_dev_t pci_dev; /* handle for 0:1f:0 */
u8 tmpbyte;
u16 tmpword;
u32 tmplong;
/* Have we already done this? */
if (found_it_once)
return 0;
u32 gpiobase;
int offset;
/* Where should it be? */
dev = PCI_BDF(0, 0x1f, 0);
pci_dev = PCI_BDF(0, 0x1f, 0);
/* Is the device present? */
pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
pci_read_config_word(pci_dev, PCI_VENDOR_ID, &tmpword);
if (tmpword != PCI_VENDOR_ID_INTEL) {
debug("%s: wrong VendorID\n", __func__);
return -1;
return -ENODEV;
}
pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword);
pci_read_config_word(pci_dev, PCI_DEVICE_ID, &tmpword);
debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
/*
* We'd like to validate the Device ID too, but pretty much any
@ -118,37 +76,37 @@ static int gpio_init(void)
*/
/* I/O should already be enabled (it's a RO bit). */
pci_read_config_word(dev, PCI_COMMAND, &tmpword);
pci_read_config_word(pci_dev, PCI_COMMAND, &tmpword);
if (!(tmpword & PCI_COMMAND_IO)) {
debug("%s: device IO not enabled\n", __func__);
return -1;
return -ENODEV;
}
/* Header Type must be normal (bits 6-0 only; see spec.) */
pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
pci_read_config_byte(pci_dev, PCI_HEADER_TYPE, &tmpbyte);
if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
debug("%s: invalid Header type\n", __func__);
return -1;
return -ENODEV;
}
/* Base Class must be a bridge device */
pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
pci_read_config_byte(pci_dev, PCI_CLASS_CODE, &tmpbyte);
if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
debug("%s: invalid class\n", __func__);
return -1;
return -ENODEV;
}
/* Sub Class must be ISA */
pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
pci_read_config_byte(pci_dev, PCI_CLASS_SUB_CODE, &tmpbyte);
if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
debug("%s: invalid subclass\n", __func__);
return -1;
return -ENODEV;
}
/* Programming Interface must be 0x00 (no others exist) */
pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
pci_read_config_byte(pci_dev, PCI_CLASS_PROG, &tmpbyte);
if (tmpbyte != 0x00) {
debug("%s: invalid interface type\n", __func__);
return -1;
return -ENODEV;
}
/*
@ -156,11 +114,11 @@ static int gpio_init(void)
* that it was unused (or undocumented). Check that it looks
* okay: not all ones or zeros, and mapped to I/O space (bit 0).
*/
pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
pci_read_config_dword(pci_dev, PCI_CFG_GPIOBASE, &tmplong);
if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
!(tmplong & 0x00000001)) {
debug("%s: unexpected GPIOBASE value\n", __func__);
return -1;
return -ENODEV;
}
/*
@ -170,105 +128,137 @@ static int gpio_init(void)
* an I/O address, not a memory address, so mask that off.
*/
gpiobase = tmplong & 0xfffffffe;
offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
if (offset == -1) {
debug("%s: Invalid register offset %d\n", __func__, offset);
return -EINVAL;
}
plat->base_addr = gpiobase + offset;
plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
"bank-name", NULL);
/* Finally. These are the droids we're looking for. */
found_it_once = 1;
return 0;
}
int gpio_request(unsigned num, const char *label /* UNUSED */)
int ich6_gpio_probe(struct udevice *dev)
{
struct ich6_bank_platdata *plat = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct ich6_bank_priv *bank = dev_get_priv(dev);
uc_priv->gpio_count = GPIO_PER_BANK;
uc_priv->bank_name = plat->bank_name;
bank->use_sel = plat->base_addr;
bank->io_sel = plat->base_addr + 4;
bank->lvl = plat->base_addr + 8;
return 0;
}
int ich6_gpio_request(struct udevice *dev, unsigned offset, const char *label)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
int i = 0, j = 0;
/* Is the hardware ready? */
if (gpio_init())
return -1;
if (bad_arg(num, &i, &j))
return -1;
/*
* Make sure that the GPIO pin we want isn't already in use for some
* built-in hardware function. We have to check this for every
* requested pin.
*/
tmplong = inl(gpiobase + gpio_bank[i].use_sel);
if (!(tmplong & (1UL << j))) {
tmplong = inl(bank->use_sel);
if (!(tmplong & (1UL << offset))) {
debug("%s: gpio %d is reserved for internal use\n", __func__,
num);
return -1;
offset);
return -EPERM;
}
return mark_gpio(i, j);
}
int gpio_free(unsigned num)
{
int i = 0, j = 0;
if (notmine(num, &i, &j))
return -1;
clear_gpio(i, j);
return 0;
}
int gpio_direction_input(unsigned num)
static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
int i = 0, j = 0;
if (notmine(num, &i, &j))
return -1;
tmplong = inl(gpiobase + gpio_bank[i].io_sel);
tmplong |= (1UL << j);
outl(gpiobase + gpio_bank[i].io_sel, tmplong);
tmplong = inl(bank->io_sel);
tmplong |= (1UL << offset);
outl(bank->io_sel, tmplong);
return 0;
}
int gpio_direction_output(unsigned num, int value)
static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
int i = 0, j = 0;
if (notmine(num, &i, &j))
return -1;
tmplong = inl(gpiobase + gpio_bank[i].io_sel);
tmplong &= ~(1UL << j);
outl(gpiobase + gpio_bank[i].io_sel, tmplong);
tmplong = inl(bank->io_sel);
tmplong &= ~(1UL << offset);
outl(bank->io_sel, tmplong);
return 0;
}
int gpio_get_value(unsigned num)
static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
int i = 0, j = 0;
int r;
if (notmine(num, &i, &j))
return -1;
tmplong = inl(gpiobase + gpio_bank[i].lvl);
r = (tmplong & (1UL << j)) ? 1 : 0;
tmplong = inl(bank->lvl);
r = (tmplong & (1UL << offset)) ? 1 : 0;
return r;
}
int gpio_set_value(unsigned num, int value)
static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
int i = 0, j = 0;
if (notmine(num, &i, &j))
return -1;
tmplong = inl(gpiobase + gpio_bank[i].lvl);
tmplong = inl(bank->lvl);
if (value)
tmplong |= (1UL << j);
tmplong |= (1UL << offset);
else
tmplong &= ~(1UL << j);
outl(gpiobase + gpio_bank[i].lvl, tmplong);
tmplong &= ~(1UL << offset);
outl(bank->lvl, tmplong);
return 0;
}
static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 mask = 1UL << offset;
if (!(inl(bank->use_sel) & mask))
return GPIOF_FUNC;
if (inl(bank->io_sel) & mask)
return GPIOF_INPUT;
else
return GPIOF_OUTPUT;
}
static const struct dm_gpio_ops gpio_ich6_ops = {
.request = ich6_gpio_request,
.direction_input = ich6_gpio_direction_input,
.direction_output = ich6_gpio_direction_output,
.get_value = ich6_gpio_get_value,
.set_value = ich6_gpio_set_value,
.get_function = ich6_gpio_get_function,
};
static const struct udevice_id intel_ich6_gpio_ids[] = {
{ .compatible = "intel,ich6-gpio" },
{ }
};
U_BOOT_DRIVER(gpio_ich6) = {
.name = "gpio_ich6",
.id = UCLASS_GPIO,
.of_match = intel_ich6_gpio_ids,
.ops = &gpio_ich6_ops,
.ofdata_to_platdata = gpio_ich6_ofdata_to_platdata,
.probe = ich6_gpio_probe,
.priv_auto_alloc_size = sizeof(struct ich6_bank_priv),
.platdata_auto_alloc_size = sizeof(struct ich6_bank_platdata),
};

View File

@ -20,7 +20,6 @@ enum mxc_gpio_direction {
MXC_GPIO_DIRECTION_OUT,
};
#define GPIO_NAME_SIZE 20
#define GPIO_PER_BANK 32
struct mxc_gpio_plat {
@ -28,7 +27,6 @@ struct mxc_gpio_plat {
};
struct mxc_bank_info {
char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
struct gpio_regs *regs;
};
@ -152,18 +150,6 @@ int gpio_direction_output(unsigned gpio, int value)
#endif
#ifdef CONFIG_DM_GPIO
/**
* gpio_is_requested() - check if a GPIO has been requested
*
* @bank: Bank to check
* @offset: GPIO offset within bank to check
* @return true if marked as requested, false if not
*/
static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
{
return *bank->label[offset] != '\0';
}
static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
{
u32 val;
@ -208,35 +194,10 @@ static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
return (readl(&regs->gpio_psr) >> offset) & 0x01;
}
static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
{
return (readl(&regs->gpio_dr) >> offset) & 0x01;
}
static int check_requested(struct udevice *dev, unsigned offset,
const char *func)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
if (!gpio_is_requested(bank, offset)) {
printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
func, uc_priv->bank_name, offset);
return -EPERM;
}
return 0;
}
/* set GPIO pin 'gpio' as an input */
static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
int ret;
ret = check_requested(dev, offset, __func__);
if (ret)
return ret;
/* Configure GPIO direction as input. */
mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
@ -249,11 +210,6 @@ static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
int ret;
ret = check_requested(dev, offset, __func__);
if (ret)
return ret;
/* Configure GPIO output value. */
mxc_gpio_bank_set_value(bank->regs, offset, value);
@ -268,11 +224,6 @@ static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
int ret;
ret = check_requested(dev, offset, __func__);
if (ret)
return ret;
return mxc_gpio_bank_get_value(bank->regs, offset);
}
@ -282,80 +233,16 @@ static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
int ret;
ret = check_requested(dev, offset, __func__);
if (ret)
return ret;
mxc_gpio_bank_set_value(bank->regs, offset, value);
return 0;
}
static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
char *buf, int bufsize)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct mxc_bank_info *bank = dev_get_priv(dev);
const char *label;
bool requested;
bool is_output;
int size;
label = bank->label[offset];
is_output = mxc_gpio_is_output(bank->regs, offset);
size = snprintf(buf, bufsize, "%s%d: ",
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
buf += size;
bufsize -= size;
requested = gpio_is_requested(bank, offset);
snprintf(buf, bufsize, "%s: %d [%c]%s%s",
is_output ? "out" : " in",
is_output ?
mxc_gpio_bank_get_output_value(bank->regs, offset) :
mxc_gpio_bank_get_value(bank->regs, offset),
requested ? 'x' : ' ',
requested ? " " : "",
label);
return 0;
}
static int mxc_gpio_request(struct udevice *dev, unsigned offset,
const char *label)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
if (gpio_is_requested(bank, offset))
return -EBUSY;
strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
return 0;
}
static int mxc_gpio_free(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
int ret;
ret = check_requested(dev, offset, __func__);
if (ret)
return ret;
bank->label[offset][0] = '\0';
return 0;
}
static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
if (!gpio_is_requested(bank, offset))
return GPIOF_UNUSED;
/* GPIOF_FUNC is not implemented yet */
if (mxc_gpio_is_output(bank->regs, offset))
return GPIOF_OUTPUT;
@ -364,14 +251,11 @@ static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
}
static const struct dm_gpio_ops gpio_mxc_ops = {
.request = mxc_gpio_request,
.free = mxc_gpio_free,
.direction_input = mxc_gpio_direction_input,
.direction_output = mxc_gpio_direction_output,
.get_value = mxc_gpio_get_value,
.set_value = mxc_gpio_set_value,
.get_function = mxc_gpio_get_function,
.get_state = mxc_gpio_get_state,
};
static const struct mxc_gpio_plat mxc_plat[] = {

View File

@ -19,6 +19,7 @@
* Written by Juha Yrjölä <juha.yrjola@nokia.com>
*/
#include <common.h>
#include <dm.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/errno.h>
@ -26,10 +27,17 @@
#define OMAP_GPIO_DIR_OUT 0
#define OMAP_GPIO_DIR_IN 1
static inline const struct gpio_bank *get_gpio_bank(int gpio)
{
return &omap_gpio_bank[gpio >> 5];
}
#ifdef CONFIG_DM_GPIO
#define GPIO_PER_BANK 32
struct gpio_bank {
/* TODO(sjg@chromium.org): Can we use a struct here? */
void *base; /* address of registers in physical memory */
enum gpio_method method;
};
#endif
static inline int get_gpio_index(int gpio)
{
@ -41,15 +49,6 @@ int gpio_is_valid(int gpio)
return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
}
static int check_gpio(int gpio)
{
if (!gpio_is_valid(gpio)) {
printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
return -1;
}
return 0;
}
static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
int is_input)
{
@ -118,6 +117,48 @@ static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
__raw_writel(l, reg);
}
static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
{
void *reg = bank->base;
int input;
switch (bank->method) {
case METHOD_GPIO_24XX:
input = _get_gpio_direction(bank, gpio);
switch (input) {
case OMAP_GPIO_DIR_IN:
reg += OMAP_GPIO_DATAIN;
break;
case OMAP_GPIO_DIR_OUT:
reg += OMAP_GPIO_DATAOUT;
break;
default:
return -1;
}
break;
default:
return -1;
}
return (__raw_readl(reg) & (1 << gpio)) != 0;
}
#ifndef CONFIG_DM_GPIO
static inline const struct gpio_bank *get_gpio_bank(int gpio)
{
return &omap_gpio_bank[gpio >> 5];
}
static int check_gpio(int gpio)
{
if (!gpio_is_valid(gpio)) {
printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
return -1;
}
return 0;
}
/**
* Set value of the specified gpio
*/
@ -139,32 +180,12 @@ int gpio_set_value(unsigned gpio, int value)
int gpio_get_value(unsigned gpio)
{
const struct gpio_bank *bank;
void *reg;
int input;
if (check_gpio(gpio) < 0)
return -1;
bank = get_gpio_bank(gpio);
reg = bank->base;
switch (bank->method) {
case METHOD_GPIO_24XX:
input = _get_gpio_direction(bank, get_gpio_index(gpio));
switch (input) {
case OMAP_GPIO_DIR_IN:
reg += OMAP_GPIO_DATAIN;
break;
case OMAP_GPIO_DIR_OUT:
reg += OMAP_GPIO_DATAOUT;
break;
default:
return -1;
}
break;
default:
return -1;
}
return (__raw_readl(reg)
& (1 << get_gpio_index(gpio))) != 0;
return _get_gpio_value(bank, get_gpio_index(gpio));
}
/**
@ -220,3 +241,95 @@ int gpio_free(unsigned gpio)
{
return 0;
}
#else /* new driver model interface CONFIG_DM_GPIO */
/* set GPIO pin 'gpio' as an input */
static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct gpio_bank *bank = dev_get_priv(dev);
/* Configure GPIO direction as input. */
_set_gpio_direction(bank, offset, 1);
return 0;
}
/* set GPIO pin 'gpio' as an output, with polarity 'value' */
static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct gpio_bank *bank = dev_get_priv(dev);
_set_gpio_dataout(bank, offset, value);
_set_gpio_direction(bank, offset, 0);
return 0;
}
/* read GPIO IN value of pin 'gpio' */
static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct gpio_bank *bank = dev_get_priv(dev);
return _get_gpio_value(bank, offset);
}
/* write GPIO OUT value to pin 'gpio' */
static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct gpio_bank *bank = dev_get_priv(dev);
_set_gpio_dataout(bank, offset, value);
return 0;
}
static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct gpio_bank *bank = dev_get_priv(dev);
/* GPIOF_FUNC is not implemented yet */
if (_get_gpio_direction(bank->base, offset) == OMAP_GPIO_DIR_OUT)
return GPIOF_OUTPUT;
else
return GPIOF_INPUT;
}
static const struct dm_gpio_ops gpio_omap_ops = {
.direction_input = omap_gpio_direction_input,
.direction_output = omap_gpio_direction_output,
.get_value = omap_gpio_get_value,
.set_value = omap_gpio_set_value,
.get_function = omap_gpio_get_function,
};
static int omap_gpio_probe(struct udevice *dev)
{
struct gpio_bank *bank = dev_get_priv(dev);
struct omap_gpio_platdata *plat = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
char name[18], *str;
sprintf(name, "GPIO%d_", plat->bank_index);
str = strdup(name);
if (!str)
return -ENOMEM;
uc_priv->bank_name = str;
uc_priv->gpio_count = GPIO_PER_BANK;
bank->base = (void *)plat->base;
bank->method = plat->method;
return 0;
}
U_BOOT_DRIVER(gpio_omap) = {
.name = "gpio_omap",
.id = UCLASS_GPIO,
.ops = &gpio_omap_ops,
.probe = omap_gpio_probe,
.priv_auto_alloc_size = sizeof(struct gpio_bank),
};
#endif /* CONFIG_DM_GPIO */

View File

@ -33,8 +33,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define RATE_MASK(gpio) (0x1 << (gpio + 16))
#define RATE_SET(gpio) (0x1 << (gpio + 16))
#define GPIO_NAME_SIZE 20
/* Platform data for each bank */
struct exynos_gpio_platdata {
struct s5p_gpio_bank *bank;
@ -43,7 +41,6 @@ struct exynos_gpio_platdata {
/* Information about each bank at run-time */
struct exynos_bank_info {
char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
struct s5p_gpio_bank *bank;
};
@ -189,61 +186,10 @@ int s5p_gpio_get_pin(unsigned gpio)
/* Driver model interface */
#ifndef CONFIG_SPL_BUILD
static int exynos_gpio_get_state(struct udevice *dev, unsigned int offset,
char *buf, int bufsize)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct exynos_bank_info *state = dev_get_priv(dev);
const char *label;
bool is_output;
int size;
int cfg;
label = state->label[offset];
cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
is_output = cfg == S5P_GPIO_OUTPUT;
size = snprintf(buf, bufsize, "%s%d: ",
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
buf += size;
bufsize -= size;
if (is_output || cfg == S5P_GPIO_INPUT) {
snprintf(buf, bufsize, "%s: %d [%c]%s%s",
is_output ? "out" : " in",
s5p_gpio_get_value(state->bank, offset),
*label ? 'x' : ' ',
*label ? " " : "",
label);
} else {
snprintf(buf, bufsize, "sfpio");
}
return 0;
}
static int check_reserved(struct udevice *dev, unsigned offset,
const char *func)
{
struct exynos_bank_info *state = dev_get_priv(dev);
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
if (!*state->label[offset]) {
printf("exynos_gpio: %s: error: gpio %s%d not reserved\n",
func, uc_priv->bank_name, offset);
return -EPERM;
}
return 0;
}
/* set GPIO pin 'gpio' as an input */
static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct exynos_bank_info *state = dev_get_priv(dev);
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
/* Configure GPIO direction as input. */
s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
@ -256,11 +202,6 @@ static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct exynos_bank_info *state = dev_get_priv(dev);
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
/* Configure GPIO output value. */
s5p_gpio_set_value(state->bank, offset, value);
@ -275,11 +216,6 @@ static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct exynos_bank_info *state = dev_get_priv(dev);
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
return s5p_gpio_get_value(state->bank, offset);
}
@ -289,43 +225,11 @@ static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct exynos_bank_info *state = dev_get_priv(dev);
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
s5p_gpio_set_value(state->bank, offset, value);
return 0;
}
static int exynos_gpio_request(struct udevice *dev, unsigned offset,
const char *label)
{
struct exynos_bank_info *state = dev_get_priv(dev);
if (*state->label[offset])
return -EBUSY;
strncpy(state->label[offset], label, GPIO_NAME_SIZE);
state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
return 0;
}
static int exynos_gpio_free(struct udevice *dev, unsigned offset)
{
struct exynos_bank_info *state = dev_get_priv(dev);
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
state->label[offset][0] = '\0';
return 0;
}
#endif /* nCONFIG_SPL_BUILD */
/*
@ -362,8 +266,6 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
struct exynos_bank_info *state = dev_get_priv(dev);
int cfg;
if (!*state->label[offset])
return GPIOF_UNUSED;
cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
if (cfg == S5P_GPIO_OUTPUT)
return GPIOF_OUTPUT;
@ -374,14 +276,11 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
}
static const struct dm_gpio_ops gpio_exynos_ops = {
.request = exynos_gpio_request,
.free = exynos_gpio_free,
.direction_input = exynos_gpio_direction_input,
.direction_output = exynos_gpio_direction_output,
.get_value = exynos_gpio_get_value,
.set_value = exynos_gpio_set_value,
.get_function = exynos_gpio_get_function,
.get_state = exynos_gpio_get_state,
};
static int gpio_exynos_probe(struct udevice *dev)

View File

@ -14,7 +14,6 @@ DECLARE_GLOBAL_DATA_PTR;
/* Flags for each GPIO */
#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */
#define GPIOF_HIGH (1 << 1) /* Currently set high */
#define GPIOF_RESERVED (1 << 2) /* Is in use / requested */
struct gpio_state {
const char *label; /* label given by requester */
@ -54,18 +53,6 @@ static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag,
return 0;
}
static int check_reserved(struct udevice *dev, unsigned offset,
const char *func)
{
if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
printf("sandbox_gpio: %s: error: offset %u not reserved\n",
func, offset);
return -1;
}
return 0;
}
/*
* Back-channel sandbox-internal-only access to GPIO state
*/
@ -101,9 +88,6 @@ static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
{
debug("%s: offset:%u\n", __func__, offset);
if (check_reserved(dev, offset, __func__))
return -1;
return sandbox_gpio_set_direction(dev, offset, 0);
}
@ -113,9 +97,6 @@ static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
{
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
if (check_reserved(dev, offset, __func__))
return -1;
return sandbox_gpio_set_direction(dev, offset, 1) |
sandbox_gpio_set_value(dev, offset, value);
}
@ -125,9 +106,6 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
{
debug("%s: offset:%u\n", __func__, offset);
if (check_reserved(dev, offset, __func__))
return -1;
return sandbox_gpio_get_value(dev, offset);
}
@ -136,9 +114,6 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
{
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
if (check_reserved(dev, offset, __func__))
return -1;
if (!sandbox_gpio_get_direction(dev, offset)) {
printf("sandbox_gpio: error: set_value on input gpio %u\n",
offset);
@ -148,69 +123,19 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
return sandbox_gpio_set_value(dev, offset, value);
}
static int sb_gpio_request(struct udevice *dev, unsigned offset,
const char *label)
static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct gpio_state *state = dev_get_priv(dev);
debug("%s: offset:%u, label:%s\n", __func__, offset, label);
if (offset >= uc_priv->gpio_count) {
printf("sandbox_gpio: error: invalid gpio %u\n", offset);
return -1;
}
if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
printf("sandbox_gpio: error: gpio %u already reserved\n",
offset);
return -1;
}
state[offset].label = label;
return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1);
}
static int sb_gpio_free(struct udevice *dev, unsigned offset)
{
struct gpio_state *state = dev_get_priv(dev);
debug("%s: offset:%u\n", __func__, offset);
if (check_reserved(dev, offset, __func__))
return -1;
state[offset].label = NULL;
return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0);
}
static int sb_gpio_get_state(struct udevice *dev, unsigned int offset,
char *buf, int bufsize)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct gpio_state *state = dev_get_priv(dev);
const char *label;
label = state[offset].label;
snprintf(buf, bufsize, "%s%d: %s: %d [%c]%s%s",
uc_priv->bank_name ? uc_priv->bank_name : "", offset,
sandbox_gpio_get_direction(dev, offset) ? "out" : " in",
sandbox_gpio_get_value(dev, offset),
get_gpio_flag(dev, offset, GPIOF_RESERVED) ? 'x' : ' ',
label ? " " : "",
label ? label : "");
return 0;
if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
return GPIOF_OUTPUT;
return GPIOF_INPUT;
}
static const struct dm_gpio_ops gpio_sandbox_ops = {
.request = sb_gpio_request,
.free = sb_gpio_free,
.direction_input = sb_gpio_direction_input,
.direction_output = sb_gpio_direction_output,
.get_value = sb_gpio_get_value,
.set_value = sb_gpio_set_value,
.get_state = sb_gpio_get_state,
.get_function = sb_gpio_get_function,
};
static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
@ -239,6 +164,13 @@ static int gpio_sandbox_probe(struct udevice *dev)
return 0;
}
static int gpio_sandbox_remove(struct udevice *dev)
{
free(dev->priv);
return 0;
}
static const struct udevice_id sandbox_gpio_ids[] = {
{ .compatible = "sandbox,gpio" },
{ }
@ -250,5 +182,6 @@ U_BOOT_DRIVER(gpio_sandbox) = {
.of_match = sandbox_gpio_ids,
.ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
.probe = gpio_sandbox_probe,
.remove = gpio_sandbox_remove,
.ops = &gpio_sandbox_ops,
};

View File

@ -39,7 +39,6 @@ struct tegra_gpio_platdata {
/* Information about each port at run-time */
struct tegra_port_info {
char label[TEGRA_GPIOS_PER_PORT][GPIO_NAME_SIZE];
struct gpio_ctlr_bank *bank;
int base_gpio; /* Port number for this port (0, 1,.., n-1) */
};
@ -132,21 +131,6 @@ static void set_level(unsigned gpio, int high)
writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
}
static int check_reserved(struct udevice *dev, unsigned offset,
const char *func)
{
struct tegra_port_info *state = dev_get_priv(dev);
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
if (!*state->label[offset]) {
printf("tegra_gpio: %s: error: gpio %s%d not reserved\n",
func, uc_priv->bank_name, offset);
return -EBUSY;
}
return 0;
}
/* set GPIO pin 'gpio' as an output, with polarity 'value' */
int tegra_spl_gpio_direction_output(int gpio, int value)
{
@ -171,59 +155,16 @@ static int tegra_gpio_request(struct udevice *dev, unsigned offset,
{
struct tegra_port_info *state = dev_get_priv(dev);
if (!label)
return -EINVAL;
if (*state->label[offset])
return -EBUSY;
strncpy(state->label[offset], label, GPIO_NAME_SIZE);
state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
/* Configure as a GPIO */
set_config(state->base_gpio + offset, 1);
return 0;
}
static int tegra_gpio_free(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
state->label[offset][0] = '\0';
return 0;
}
/* read GPIO OUT value of pin 'gpio' */
static int tegra_gpio_get_output_value(unsigned gpio)
{
struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
int val;
debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
return (val >> GPIO_BIT(gpio)) & 1;
}
/* set GPIO pin 'gpio' as an input */
static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
/* Configure GPIO direction as input. */
set_direction(state->base_gpio + offset, 0);
@ -237,11 +178,6 @@ static int tegra_gpio_direction_output(struct udevice *dev, unsigned offset,
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
/* Configure GPIO output value. */
set_level(gpio, value);
@ -257,13 +193,8 @@ static int tegra_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
int ret;
int val;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
debug("%s: pin = %d (port %d:bit %d)\n", __func__,
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
@ -277,11 +208,6 @@ static int tegra_gpio_set_value(struct udevice *dev, unsigned offset, int value)
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
int ret;
ret = check_reserved(dev, offset, __func__);
if (ret)
return ret;
debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
@ -317,8 +243,6 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
if (!*state->label[offset])
return GPIOF_UNUSED;
if (!get_config(gpio))
return GPIOF_FUNC;
else if (get_direction(gpio))
@ -327,50 +251,13 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
static int tegra_gpio_get_state(struct udevice *dev, unsigned int offset,
char *buf, int bufsize)
{
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
const char *label;
int is_output;
int is_gpio;
int size;
label = state->label[offset];
is_gpio = get_config(gpio); /* GPIO, not SFPIO */
size = snprintf(buf, bufsize, "%s%d: ",
uc_priv->bank_name ? uc_priv->bank_name : "", offset);
buf += size;
bufsize -= size;
if (is_gpio) {
is_output = get_direction(gpio);
snprintf(buf, bufsize, "%s: %d [%c]%s%s",
is_output ? "out" : " in",
is_output ?
tegra_gpio_get_output_value(gpio) :
tegra_gpio_get_value(dev, offset),
*label ? 'x' : ' ',
*label ? " " : "",
label);
} else {
snprintf(buf, bufsize, "sfpio");
}
return 0;
}
static const struct dm_gpio_ops gpio_tegra_ops = {
.request = tegra_gpio_request,
.free = tegra_gpio_free,
.direction_input = tegra_gpio_direction_input,
.direction_output = tegra_gpio_direction_output,
.get_value = tegra_gpio_get_value,
.set_value = tegra_gpio_set_value,
.get_function = tegra_gpio_get_function,
.get_state = tegra_gpio_get_state,
};
/**

View File

@ -67,14 +67,19 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
#ifdef OMAP_HSMMC_USE_GPIO
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
{
int ret;
#ifndef CONFIG_DM_GPIO
if (!gpio_is_valid(gpio))
return -1;
#endif
ret = gpio_request(gpio, label);
if (ret)
return ret;
if (gpio_request(gpio, label) < 0)
return -1;
if (gpio_direction_input(gpio) < 0)
return -1;
ret = gpio_direction_input(gpio);
if (ret)
return ret;
return gpio;
}

View File

@ -0,0 +1,12 @@
config DM_SERIAL
bool "Enable Driver Model for serial drivers"
depends on DM
help
If you want to use driver model for serial drivers, say Y.
To use legacy serial drivers, say N.
config UNIPHIER_SERIAL
bool "UniPhier on-chip UART support"
depends on ARCH_UNIPHIER && DM_SERIAL
help
Support for the on-chip UARTs on the Panasonic UniPhier platform.

View File

@ -41,6 +41,8 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o
obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_TTY) += usbtty.o

View File

@ -61,13 +61,13 @@ static void ns16550_writeb(NS16550_t port, int offset, int value)
unsigned char *addr;
offset *= 1 << plat->reg_shift;
addr = plat->base + offset;
addr = map_sysmem(plat->base, 0) + offset;
/*
* As far as we know it doesn't make sense to support selection of
* these options at run-time, so use the existing CONFIG options.
*/
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
outb(value, addr);
outb(value, (ulong)addr);
#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
out_le32(addr, value);
#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
@ -85,9 +85,9 @@ static int ns16550_readb(NS16550_t port, int offset)
unsigned char *addr;
offset *= 1 << plat->reg_shift;
addr = plat->base + offset;
addr = map_sysmem(plat->base, 0) + offset;
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
return inb(addr);
return inb((ulong)addr);
#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
return in_le32(addr);
#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
@ -253,7 +253,7 @@ static int ns16550_serial_getc(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
if (!serial_in(&com_port->lsr) & UART_LSR_DR)
if (!(serial_in(&com_port->lsr) & UART_LSR_DR))
return -EAGAIN;
return serial_in(&com_port->rbr);
@ -276,14 +276,15 @@ int ns16550_serial_probe(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
com_port->plat = dev_get_platdata(dev);
NS16550_init(com_port, -1);
return 0;
}
#ifdef CONFIG_OF_CONTROL
int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
struct ns16550_platdata *plat = dev->platdata;
fdt_addr_t addr;
@ -291,13 +292,13 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
plat->base = (unsigned char *)addr;
plat->base = addr;
plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"reg-shift", 1);
com_port->plat = plat;
return 0;
}
#endif
const struct dm_serial_ops ns16550_serial_ops = {
.putc = ns16550_serial_putc,

View File

@ -11,9 +11,12 @@
#include <os.h>
#include <serial.h>
#include <stdio_dev.h>
#include <watchdog.h>
#include <dm/lists.h>
#include <dm/device-internal.h>
#include <ns16550.h>
DECLARE_GLOBAL_DATA_PTR;
/* The currently-selected console serial device */
@ -47,13 +50,22 @@ static void serial_find_console_or_panic(void)
}
#endif
/*
* Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!).
*
* Failing that, get the device with sequence number 0, or in extremis
* just the first serial device we can find. But we insist on having
* a console (even if it is silent).
*/
if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) &&
#ifdef CONFIG_CONS_INDEX
#define INDEX (CONFIG_CONS_INDEX - 1)
#else
#define INDEX 0
#endif
if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) &&
uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) &&
(uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev))
panic("No serial driver found");
#undef INDEX
}
/* Called prior to relocation */
@ -71,21 +83,66 @@ void serial_initialize(void)
serial_find_console_or_panic();
}
static void serial_putc_dev(struct udevice *dev, char ch)
static void _serial_putc(struct udevice *dev, char ch)
{
struct dm_serial_ops *ops = serial_get_ops(cur_dev);
struct dm_serial_ops *ops = serial_get_ops(dev);
int err;
do {
err = ops->putc(cur_dev, ch);
err = ops->putc(dev, ch);
} while (err == -EAGAIN);
if (ch == '\n')
serial_putc('\r');
_serial_putc(dev, '\r');
}
static void _serial_puts(struct udevice *dev, const char *str)
{
while (*str)
_serial_putc(dev, *str++);
}
static int _serial_getc(struct udevice *dev)
{
struct dm_serial_ops *ops = serial_get_ops(dev);
int err;
do {
err = ops->getc(dev);
if (err == -EAGAIN)
WATCHDOG_RESET();
} while (err == -EAGAIN);
return err >= 0 ? err : 0;
}
static int _serial_tstc(struct udevice *dev)
{
struct dm_serial_ops *ops = serial_get_ops(dev);
if (ops->pending)
return ops->pending(dev, true);
return 1;
}
void serial_putc(char ch)
{
serial_putc_dev(cur_dev, ch);
_serial_putc(cur_dev, ch);
}
void serial_puts(const char *str)
{
_serial_puts(cur_dev, str);
}
int serial_getc(void)
{
return _serial_getc(cur_dev);
}
int serial_tstc(void)
{
return _serial_tstc(cur_dev);
}
void serial_setbrg(void)
@ -96,72 +153,28 @@ void serial_setbrg(void)
ops->setbrg(cur_dev, gd->baudrate);
}
void serial_puts(const char *str)
{
while (*str)
serial_putc(*str++);
}
int serial_tstc(void)
{
struct dm_serial_ops *ops = serial_get_ops(cur_dev);
if (ops->pending)
return ops->pending(cur_dev, true);
return 1;
}
static int serial_getc_dev(struct udevice *dev)
{
struct dm_serial_ops *ops = serial_get_ops(dev);
int err;
do {
err = ops->getc(dev);
} while (err == -EAGAIN);
return err >= 0 ? err : 0;
}
int serial_getc(void)
{
return serial_getc_dev(cur_dev);
}
void serial_stdio_init(void)
{
}
static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
{
struct udevice *dev = sdev->priv;
serial_putc_dev(dev, ch);
_serial_putc(sdev->priv, ch);
}
void serial_stub_puts(struct stdio_dev *sdev, const char *str)
{
while (*str)
serial_stub_putc(sdev, *str++);
_serial_puts(sdev->priv, str);
}
int serial_stub_getc(struct stdio_dev *sdev)
{
struct udevice *dev = sdev->priv;
return serial_getc_dev(dev);
return _serial_getc(sdev->priv);
}
int serial_stub_tstc(struct stdio_dev *sdev)
{
struct udevice *dev = sdev->priv;
struct dm_serial_ops *ops = serial_get_ops(dev);
if (ops->pending)
return ops->pending(dev, true);
return 1;
return _serial_tstc(sdev->priv);
}
static int serial_post_probe(struct udevice *dev)

View File

@ -157,7 +157,6 @@ serial_initfunc(sh_serial_initialize);
serial_initfunc(arm_dcc_initialize);
serial_initfunc(mxs_auart_initialize);
serial_initfunc(arc_serial_initialize);
serial_initfunc(uniphier_serial_initialize);
/**
* serial_register() - Register serial driver with serial driver core
@ -251,7 +250,6 @@ void serial_initialize(void)
arm_dcc_initialize();
mxs_auart_initialize();
arc_serial_initialize();
uniphier_serial_initialize();
serial_assign(default_serial_console()->name);
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <ns16550.h>
#include <serial.h>
static const struct udevice_id coreboot_serial_ids[] = {
{ .compatible = "coreboot-uart" },
{ }
};
static int coreboot_serial_ofdata_to_platdata(struct udevice *dev)
{
struct ns16550_platdata *plat = dev_get_platdata(dev);
int ret;
ret = ns16550_serial_ofdata_to_platdata(dev);
if (ret)
return ret;
plat->clock = 1843200;
return 0;
}
U_BOOT_DRIVER(serial_ns16550) = {
.name = "serial_coreboot",
.id = UCLASS_SERIAL,
.of_match = coreboot_serial_ids,
.ofdata_to_platdata = coreboot_serial_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
.priv_auto_alloc_size = sizeof(struct NS16550),
.probe = ns16550_serial_probe,
.ops = &ns16550_serial_ops,
};

View File

@ -7,10 +7,10 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <serial_mxc.h>
#include <watchdog.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
#include <dm/platform_data/serial_mxc.h>
#include <serial.h>
#include <linux/compiler.h>

View File

@ -119,8 +119,7 @@ static NS16550_t serial_ports[6] = {
.puts = eserial##port##_puts, \
}
void
_serial_putc(const char c,const int port)
static void _serial_putc(const char c, const int port)
{
if (c == '\n')
NS16550_putc(PORT, '\r');
@ -128,35 +127,29 @@ _serial_putc(const char c,const int port)
NS16550_putc(PORT, c);
}
void
_serial_putc_raw(const char c,const int port)
static void _serial_putc_raw(const char c, const int port)
{
NS16550_putc(PORT, c);
}
void
_serial_puts (const char *s,const int port)
static void _serial_puts(const char *s, const int port)
{
while (*s) {
_serial_putc(*s++, port);
}
}
int
_serial_getc(const int port)
static int _serial_getc(const int port)
{
return NS16550_getc(PORT);
}
int
_serial_tstc(const int port)
static int _serial_tstc(const int port)
{
return NS16550_tstc(PORT);
}
void
_serial_setbrg (const int port)
static void _serial_setbrg(const int port)
{
int clock_divisor;

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <ns16550.h>
#include <serial.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_OF_CONTROL
static const struct udevice_id omap_serial_ids[] = {
{ .compatible = "ti,omap3-uart" },
{ }
};
static int omap_serial_ofdata_to_platdata(struct udevice *dev)
{
struct ns16550_platdata *plat = dev_get_platdata(dev);
int ret;
ret = ns16550_serial_ofdata_to_platdata(dev);
if (ret)
return ret;
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"clock-frequency", -1);
plat->reg_shift = 2;
return 0;
}
#endif
U_BOOT_DRIVER(serial_omap_ns16550) = {
.name = "serial_omap",
.id = UCLASS_SERIAL,
.of_match = of_match_ptr(omap_serial_ids),
.ofdata_to_platdata = of_match_ptr(omap_serial_ofdata_to_platdata),
.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
.priv_auto_alloc_size = sizeof(struct NS16550),
.probe = ns16550_serial_probe,
.ops = &ns16550_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@ -17,7 +17,7 @@
#include <watchdog.h>
#include <asm/io.h>
#include <serial.h>
#include <serial_pl01x.h>
#include <dm/platform_data/serial_pl01x.h>
#include <linux/compiler.h>
#include "serial_pl01x_internal.h"

View File

@ -69,7 +69,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int hwflow;
#endif
void _serial_setbrg(const int dev_index)
static void _serial_setbrg(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
unsigned int reg = 0;
@ -131,7 +131,7 @@ static int serial_init_dev(const int dev_index)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
int _serial_getc(const int dev_index)
static int _serial_getc(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
@ -181,7 +181,7 @@ void enable_putc(void)
/*
* Output a single byte to the serial port.
*/
void _serial_putc(const char c, const int dev_index)
static void _serial_putc(const char c, const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
#ifdef CONFIG_MODEM_SUPPORT
@ -212,7 +212,7 @@ static inline void serial_putc_dev(unsigned int dev_index, const char c)
/*
* Test whether a character is in the RX buffer
*/
int _serial_tstc(const int dev_index)
static int _serial_tstc(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
@ -224,7 +224,7 @@ static inline int serial_tstc_dev(unsigned int dev_index)
return _serial_tstc(dev_index);
}
void _serial_puts(const char *s, const int dev_index)
static void _serial_puts(const char *s, const int dev_index)
{
while (*s) {
_serial_putc(*s++, dev_index);

View File

@ -2,14 +2,14 @@
* Copyright (C) 2012-2014 Panasonic Corporation
* Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
*
* Based on serial_ns16550.c
* (C) Copyright 2000
* Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <dm/device.h>
#include <dm/platform_data/serial-uniphier.h>
#include <serial.h>
#define UART_REG(x) \
@ -48,157 +48,104 @@ struct uniphier_serial {
#define UART_LSR_DR 0x01 /* Data ready */
#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
DECLARE_GLOBAL_DATA_PTR;
struct uniphier_serial_private_data {
struct uniphier_serial __iomem *membase;
};
static void uniphier_serial_init(struct uniphier_serial *port)
#define uniphier_serial_port(dev) \
((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase
int uniphier_serial_setbrg(struct udevice *dev, int baudrate)
{
struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
const unsigned int mode_x_div = 16;
unsigned int divisor;
writeb(UART_LCR_WLS_8, &port->lcr);
divisor = DIV_ROUND_CLOSEST(CONFIG_SYS_UNIPHIER_UART_CLK,
mode_x_div * gd->baudrate);
divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate);
writew(divisor, &port->dlr);
return 0;
}
static void uniphier_serial_setbrg(struct uniphier_serial *port)
static int uniphier_serial_getc(struct udevice *dev)
{
uniphier_serial_init(port);
}
struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
static int uniphier_serial_tstc(struct uniphier_serial *port)
{
return (readb(&port->lsr) & UART_LSR_DR) != 0;
}
static int uniphier_serial_getc(struct uniphier_serial *port)
{
while (!uniphier_serial_tstc(port))
;
if (!(readb(&port->lsr) & UART_LSR_DR))
return -EAGAIN;
return readb(&port->rbr);
}
static void uniphier_serial_putc(struct uniphier_serial *port, const char c)
static int uniphier_serial_putc(struct udevice *dev, const char c)
{
if (c == '\n')
uniphier_serial_putc(port, '\r');
struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
while (!(readb(&port->lsr) & UART_LSR_THRE))
;
if (!(readb(&port->lsr) & UART_LSR_THRE))
return -EAGAIN;
writeb(c, &port->thr);
return 0;
}
static struct uniphier_serial *serial_ports[4] = {
#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE0
(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE0,
#else
NULL,
#endif
#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE1
(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE1,
#else
NULL,
#endif
#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE2
(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE2,
#else
NULL,
#endif
#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE3
(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE3,
#else
NULL,
#endif
int uniphier_serial_probe(struct udevice *dev)
{
struct uniphier_serial_private_data *priv = dev_get_priv(dev);
struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
priv->membase = map_sysmem(plat->base, sizeof(struct uniphier_serial));
if (!priv->membase)
return -ENOMEM;
return 0;
}
int uniphier_serial_remove(struct udevice *dev)
{
unmap_sysmem(uniphier_serial_port(dev));
return 0;
}
#ifdef CONFIG_OF_CONTROL
static const struct udevice_id uniphier_uart_of_match = {
{ .compatible = "panasonic,uniphier-uart"},
{},
};
/* Multi serial device functions */
#define DECLARE_ESERIAL_FUNCTIONS(port) \
static int eserial##port##_init(void) \
{ \
uniphier_serial_init(serial_ports[port]); \
return 0 ; \
} \
static void eserial##port##_setbrg(void) \
{ \
uniphier_serial_setbrg(serial_ports[port]); \
} \
static int eserial##port##_getc(void) \
{ \
return uniphier_serial_getc(serial_ports[port]); \
} \
static int eserial##port##_tstc(void) \
{ \
return uniphier_serial_tstc(serial_ports[port]); \
} \
static void eserial##port##_putc(const char c) \
{ \
uniphier_serial_putc(serial_ports[port], c); \
}
/* Serial device descriptor */
#define INIT_ESERIAL_STRUCTURE(port, __name) { \
.name = __name, \
.start = eserial##port##_init, \
.stop = NULL, \
.setbrg = eserial##port##_setbrg, \
.getc = eserial##port##_getc, \
.tstc = eserial##port##_tstc, \
.putc = eserial##port##_putc, \
.puts = default_serial_puts, \
}
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
DECLARE_ESERIAL_FUNCTIONS(0);
struct serial_device uniphier_serial0_device =
INIT_ESERIAL_STRUCTURE(0, "ttyS0");
#endif
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
DECLARE_ESERIAL_FUNCTIONS(1);
struct serial_device uniphier_serial1_device =
INIT_ESERIAL_STRUCTURE(1, "ttyS1");
#endif
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
DECLARE_ESERIAL_FUNCTIONS(2);
struct serial_device uniphier_serial2_device =
INIT_ESERIAL_STRUCTURE(2, "ttyS2");
#endif
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
DECLARE_ESERIAL_FUNCTIONS(3);
struct serial_device uniphier_serial3_device =
INIT_ESERIAL_STRUCTURE(3, "ttyS3");
#endif
__weak struct serial_device *default_serial_console(void)
static int uniphier_serial_ofdata_to_platdata(struct udevice *dev)
{
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
return &uniphier_serial0_device;
#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
return &uniphier_serial1_device;
#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
return &uniphier_serial2_device;
#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
return &uniphier_serial3_device;
#else
#error "No uniphier serial ports configured."
#endif
/*
* TODO: Masahiro Yamada (yamada.m@jp.panasonic.com)
*
* Implement conversion code from DTB to platform data
* when supporting CONFIG_OF_CONTROL on UniPhir platform.
*/
}
#endif
void uniphier_serial_initialize(void)
{
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
serial_register(&uniphier_serial0_device);
#endif
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
serial_register(&uniphier_serial1_device);
#endif
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
serial_register(&uniphier_serial2_device);
#endif
#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
serial_register(&uniphier_serial3_device);
#endif
}
static const struct dm_serial_ops uniphier_serial_ops = {
.setbrg = uniphier_serial_setbrg,
.getc = uniphier_serial_getc,
.putc = uniphier_serial_putc,
};
U_BOOT_DRIVER(uniphier_serial) = {
.name = DRIVER_NAME,
.id = UCLASS_SERIAL,
.of_match = of_match_ptr(uniphier_uart_of_match),
.ofdata_to_platdata = of_match_ptr(uniphier_serial_ofdata_to_platdata),
.probe = uniphier_serial_probe,
.remove = uniphier_serial_remove,
.priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data),
.platdata_auto_alloc_size =
sizeof(struct uniphier_serial_platform_data),
.ops = &uniphier_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@ -0,0 +1,6 @@
config DM_SPI
bool "Enable Driver Model for SPI drivers"
depends on DM
help
If you want to use driver model for SPI drivers, say Y.
To use legacy SPI drivers, say N.

View File

@ -29,6 +29,9 @@
* Request a GPIO. This should be called before any of the other functions
* are used on this GPIO.
*
* Note: With driver model, the label is allocated so there is no need for
* the caller to preserve it.
*
* @param gp GPIO number
* @param label User label for this GPIO
* @return 0 if ok, -1 on error
@ -80,7 +83,7 @@ int gpio_get_value(unsigned gpio);
int gpio_set_value(unsigned gpio, int value);
/* State of a GPIO, as reported by get_function() */
enum {
enum gpio_func_t {
GPIOF_INPUT = 0,
GPIOF_OUTPUT,
GPIOF_UNUSED, /* Not claimed */
@ -92,6 +95,66 @@ enum {
struct udevice;
/**
* gpio_get_status() - get the current GPIO status as a string
*
* Obtain the current GPIO status as a string which can be presented to the
* user. A typical string is:
*
* "b4: in: 1 [x] sdmmc_cd"
*
* which means this is GPIO bank b, offset 4, currently set to input, current
* value 1, [x] means that it is requested and the owner is 'sdmmc_cd'
*
* @dev: Device to check
* @offset: Offset of device GPIO to check
* @buf: Place to put string
* @buffsize: Size of string including \0
*/
int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize);
/**
* gpio_get_function() - get the current function for a GPIO pin
*
* Note this returns GPIOF_UNUSED if the GPIO is not requested.
*
* @dev: Device to check
* @offset: Offset of device GPIO to check
* @namep: If non-NULL, this is set to the nane given when the GPIO
* was requested, or -1 if it has not been requested
* @return -ENODATA if the driver returned an unknown function,
* -ENODEV if the device is not active, -EINVAL if the offset is invalid.
* GPIOF_UNUSED if the GPIO has not been requested. Otherwise returns the
* function from enum gpio_func_t.
*/
int gpio_get_function(struct udevice *dev, int offset, const char **namep);
/**
* gpio_get_raw_function() - get the current raw function for a GPIO pin
*
* Note this does not return GPIOF_UNUSED - it will always return the GPIO
* driver's view of a pin function, even if it is not correctly set up.
*
* @dev: Device to check
* @offset: Offset of device GPIO to check
* @namep: If non-NULL, this is set to the nane given when the GPIO
* was requested, or -1 if it has not been requested
* @return -ENODATA if the driver returned an unknown function,
* -ENODEV if the device is not active, -EINVAL if the offset is invalid.
* Otherwise returns the function from enum gpio_func_t.
*/
int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep);
/**
* gpio_requestf() - request a GPIO using a format string for the owner
*
* This is a helper function for gpio_request(). It allows you to provide
* a printf()-format string for the GPIO owner. It calls gpio_request() with
* the string that is created
*/
int gpio_requestf(unsigned gpio, const char *fmt, ...)
__attribute__ ((format (__printf__, 2, 3)));
/**
* struct struct dm_gpio_ops - Driver model GPIO operations
*
@ -135,8 +198,6 @@ struct dm_gpio_ops {
* @return current function - GPIOF_...
*/
int (*get_function)(struct udevice *dev, unsigned offset);
int (*get_state)(struct udevice *dev, unsigned offset, char *state,
int maxlen);
};
/**
@ -157,11 +218,14 @@ struct dm_gpio_ops {
* @gpio_base: Base GPIO number for this device. For the first active device
* this will be 0; the numbering for others will follow sequentially so that
* @gpio_base for device 1 will equal the number of GPIOs in device 0.
* @name: Array of pointers to the name for each GPIO in this bank. The
* value of the pointer will be NULL if the GPIO has not been claimed.
*/
struct gpio_dev_priv {
const char *bank_name;
unsigned gpio_count;
unsigned gpio_base;
char **name;
};
/* Access the GPIO operations for a device */

View File

@ -636,13 +636,6 @@ struct stdio_dev;
int serial_stub_getc(struct stdio_dev *sdev);
int serial_stub_tstc(struct stdio_dev *sdev);
void _serial_setbrg (const int);
void _serial_putc (const char, const int);
void _serial_putc_raw(const char, const int);
void _serial_puts (const char *, const int);
int _serial_getc (const int);
int _serial_tstc (const int);
/* $(CPU)/speed.c */
int get_clocks (void);
int get_clocks_866 (void);

View File

@ -27,6 +27,11 @@
#define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_DISPLAY_BOARDINFO_LATE
#define CONFIG_DM
#define CONFIG_CMD_DM
#define CONFIG_DM_GPIO
#define CONFIG_DM_SERIAL
#define CONFIG_LMB
#define CONFIG_OF_LIBFDT
@ -88,21 +93,16 @@
/*-----------------------------------------------------------------------
* Serial Configuration
*/
#define CONFIG_CONS_INDEX 1
#define CONFIG_COREBOOT_SERIAL
#define CONFIG_SYS_NS16550
#define CONFIG_SYS_NS16550_SERIAL
#define CONFIG_SYS_NS16550_REG_SIZE 1
#define CONFIG_SYS_NS16550_CLK 1843200
#define CONFIG_BAUDRATE 9600
#define CONFIG_BAUDRATE 115200
#define CONFIG_SYS_BAUDRATE_TABLE {300, 600, 1200, 2400, 4800, \
9600, 19200, 38400, 115200}
#define CONFIG_SYS_NS16550_COM1 UART0_BASE
#define CONFIG_SYS_NS16550_COM2 UART1_BASE
#define CONFIG_SYS_NS16550_PORT_MAPPED
#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,eserial0\0" \
"stdout=vga,eserial0,cbmem\0" \
"stderr=vga,eserial0,cbmem\0"
#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \
"stdout=vga,serial,cbmem\0" \
"stderr=vga,serial,cbmem\0"
#define CONFIG_CONSOLE_MUX
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
@ -256,7 +256,7 @@
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_MONITOR_LEN (256 * 1024)
#define CONFIG_SYS_MALLOC_LEN (0x20000 + 128 * 1024)
#define CONFIG_SYS_MALLOC_F_LEN (1 << 10)
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE

View File

@ -28,14 +28,10 @@
* SoC UART : enable CONFIG_UNIPHIER_SERIAL
* On-board UART: enable CONFIG_SYS_NS16550_SERIAL
*/
#if 1
#define CONFIG_UNIPHIER_SERIAL
#else
#if 0
#define CONFIG_SYS_NS16550_SERIAL
#endif
#define CONFIG_SYS_UNIPHIER_UART_CLK 36864000
#define CONFIG_SMC911X
#define CONFIG_DDR_NUM_CH0 1

View File

@ -28,14 +28,10 @@
* SoC UART : enable CONFIG_UNIPHIER_SERIAL
* On-board UART: enable CONFIG_SYS_NS16550_SERIAL
*/
#if 1
#define CONFIG_UNIPHIER_SERIAL
#else
#if 0
#define CONFIG_SYS_NS16550_SERIAL
#endif
#define CONFIG_SYS_UNIPHIER_UART_CLK 73728000
#define CONFIG_SMC911X
#define CONFIG_DDR_NUM_CH0 2

View File

@ -28,14 +28,10 @@
* SoC UART : enable CONFIG_UNIPHIER_SERIAL
* On-board UART: enable CONFIG_SYS_NS16550_SERIAL
*/
#if 1
#define CONFIG_UNIPHIER_SERIAL
#else
#if 0
#define CONFIG_SYS_NS16550_SERIAL
#endif
#define CONFIG_SYS_UNIPHIER_UART_CLK 80000000
#define CONFIG_SMC911X
#define CONFIG_DDR_NUM_CH0 1

View File

@ -19,12 +19,23 @@
#define CONFIG_SYS_TIMERBASE 0x48040000 /* Use Timer2 */
#define CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC
#ifndef CONFIG_SPL_BUILD
# define CONFIG_DM
# define CONFIG_CMD_DM
# define CONFIG_DM_GPIO
# define CONFIG_DM_SERIAL
# define CONFIG_OMAP_SERIAL
# define CONFIG_SYS_MALLOC_F_LEN (1 << 10)
#endif
#include <asm/arch/omap.h>
/* NS16550 Configuration */
#define CONFIG_SYS_NS16550
#ifdef CONFIG_SPL_BUILD
#define CONFIG_SYS_NS16550_SERIAL
#define CONFIG_SYS_NS16550_REG_SIZE (-4)
#endif
#define CONFIG_SYS_NS16550_CLK 48000000
/* Network defines. */

View File

@ -18,6 +18,15 @@
#include <asm/arch/cpu.h>
#include <asm/arch/omap3.h>
#ifndef CONFIG_SPL_BUILD
# define CONFIG_DM
# define CONFIG_CMD_DM
# define CONFIG_DM_GPIO
# define CONFIG_DM_SERIAL
# define CONFIG_OMAP_SERIAL
# define CONFIG_SYS_MALLOC_F_LEN (1 << 10)
#endif
/* The chip has SDRC controller */
#define CONFIG_SDRC
@ -28,16 +37,20 @@
/* NS16550 Configuration */
#define V_NS16550_CLK 48000000 /* 48MHz (APLL96/2) */
#define CONFIG_SYS_NS16550
#ifdef CONFIG_SPL_BUILD
# define CONFIG_SYS_NS16550_SERIAL
# define CONFIG_SYS_NS16550_REG_SIZE (-4)
# define CONFIG_SYS_NS16550_CLK V_NS16550_CLK
#endif
#define CONFIG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600, \
115200}
/* Select serial console configuration */
#define CONFIG_CONS_INDEX 3
#ifdef CONFIG_SPL_BUILD
#define CONFIG_SYS_NS16550_COM3 OMAP34XX_UART3
#define CONFIG_SERIAL3 3
#endif
/* Physical Memory Map */
#define PHYS_SDRAM_1 OMAP34XX_SDRC_CS0

View File

@ -33,18 +33,17 @@ are defined. Select only one of them."
# define CONFIG_SUPPORT_CARD_UART_BASE (CONFIG_SUPPORT_CARD_BASE + 0x00200000)
#endif
#ifdef CONFIG_SYS_NS16550_SERIAL
#define CONFIG_SYS_NS16550
#define CONFIG_SYS_NS16550_COM1 CONFIG_SUPPORT_CARD_UART_BASE
#define CONFIG_SYS_NS16550_CLK 12288000
#define CONFIG_SYS_NS16550_REG_SIZE -2
#endif
#define CONFIG_SMC911X_BASE CONFIG_SUPPORT_CARD_ETHER_BASE
#define CONFIG_SMC911X_32_BIT
#define CONFIG_SYS_UNIPHIER_SERIAL_BASE0 0x54006800
#define CONFIG_SYS_UNIPHIER_SERIAL_BASE1 0x54006900
#define CONFIG_SYS_UNIPHIER_SERIAL_BASE2 0x54006a00
#define CONFIG_SYS_UNIPHIER_SERIAL_BASE3 0x54006b00
#define CONFIG_SYS_MALLOC_F_LEN 0x7000
/*-----------------------------------------------------------------------
* MMU and Cache Setting

View File

@ -0,0 +1,18 @@
/*
* Copyright (C) 2014 Panasonic Corporation
* Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __PLAT_UNIPHIER_SERIAL_H
#define __PLAT_UNIPHIER_SERIAL_H
#define DRIVER_NAME "uniphier-uart"
struct uniphier_serial_platform_data {
unsigned long base;
unsigned int uartclk;
};
#endif /* __PLAT_UNIPHIER_SERIAL_H */

View File

@ -8,6 +8,7 @@
#define __DM_TEST_H
#include <dm.h>
#include <malloc.h>
/**
* struct dm_test_cdata - configuration data for test instance
@ -120,6 +121,7 @@ struct dm_test_state {
int force_fail_alloc;
int skip_post_probe;
struct udevice *removed;
struct mallinfo start;
};
/* Test flags for each test */
@ -177,6 +179,27 @@ int dm_check_operations(struct dm_test_state *dms, struct udevice *dev,
*/
int dm_check_devices(struct dm_test_state *dms, int num_devices);
/**
* dm_leak_check_start() - Prepare to check for a memory leak
*
* Call this before allocating memory to record the amount of memory being
* used.
*
* @dms: Overall test state
*/
void dm_leak_check_start(struct dm_test_state *dms);
/**
* dm_leak_check_end() - Check that no memory has leaked
*
* Call this after dm_leak_check_start() and after you have hopefuilly freed
* all the memory that was allocated. This function will print an error if
* it sees a different amount of total memory allocated than before.
*
* @dms: Overall test state
*/int dm_leak_check_end(struct dm_test_state *dms);
/**
* dm_test_main() - Run all the tests
*

View File

@ -53,7 +53,7 @@
* @clock: UART base clock speed in Hz
*/
struct ns16550_platdata {
unsigned char *base;
unsigned long base;
int reg_shift;
int clock;
};

View File

@ -67,6 +67,34 @@ static struct driver_info driver_info_pre_reloc = {
.platdata = &test_pdata_manual,
};
void dm_leak_check_start(struct dm_test_state *dms)
{
dms->start = mallinfo();
if (!dms->start.uordblks)
puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n");
}
int dm_leak_check_end(struct dm_test_state *dms)
{
struct mallinfo end;
int id;
/* Don't delete the root class, since we started with that */
for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) {
struct uclass *uc;
uc = uclass_find(id);
if (!uc)
continue;
ut_assertok(uclass_destroy(uc));
}
end = mallinfo();
ut_asserteq(dms->start.uordblks, end.uordblks);
return 0;
}
/* Test that binding with platdata occurs correctly */
static int dm_test_autobind(struct dm_test_state *dms)
{
@ -377,14 +405,11 @@ static int dm_test_leak(struct dm_test_state *dms)
int i;
for (i = 0; i < 2; i++) {
struct mallinfo start, end;
struct udevice *dev;
int ret;
int id;
start = mallinfo();
if (!start.uordblks)
puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n");
dm_leak_check_start(dms);
ut_assertok(dm_scan_platdata(false));
ut_assertok(dm_scan_fdt(gd->fdt_blob, false));
@ -398,18 +423,7 @@ static int dm_test_leak(struct dm_test_state *dms)
ut_assertok(ret);
}
/* Don't delete the root class, since we started with that */
for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) {
struct uclass *uc;
uc = uclass_find(id);
if (!uc)
continue;
ut_assertok(uclass_destroy(uc));
}
end = mallinfo();
ut_asserteq(start.uordblks, end.uordblks);
ut_assertok(dm_leak_check_end(dms));
}
return 0;

View File

@ -7,11 +7,14 @@
#include <common.h>
#include <fdtdec.h>
#include <dm.h>
#include <dm/root.h>
#include <dm/ut.h>
#include <dm/test.h>
#include <dm/util.h>
#include <asm/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
/* Test that sandbox GPIOs work correctly */
static int dm_test_gpio(struct dm_test_state *dms)
{
@ -39,52 +42,51 @@ static int dm_test_gpio(struct dm_test_state *dms)
/* Get the operations for this device */
ops = gpio_get_ops(dev);
ut_assert(ops->get_state);
ut_assert(ops->get_function);
/* Cannot get a value until it is reserved */
ut_asserteq(-1, ops->get_value(dev, offset));
ut_asserteq(-EBUSY, gpio_get_value(gpio + 1));
/*
* Now some tests that use the 'sandbox' back door. All GPIOs
* should default to input, include b4 that we are using here.
*/
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: in: 0 [ ]", buf);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: input: 0 [ ]", buf);
/* Change it to an output */
sandbox_gpio_set_direction(dev, offset, 1);
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: out: 0 [ ]", buf);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: output: 0 [ ]", buf);
sandbox_gpio_set_value(dev, offset, 1);
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: out: 1 [ ]", buf);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: output: 1 [ ]", buf);
ut_assertok(ops->request(dev, offset, "testing"));
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: out: 1 [x] testing", buf);
ut_assertok(gpio_request(gpio, "testing"));
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: output: 1 [x] testing", buf);
/* Change the value a bit */
ut_asserteq(1, ops->get_value(dev, offset));
ut_assertok(ops->set_value(dev, offset, 0));
ut_asserteq(0, ops->get_value(dev, offset));
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: out: 0 [x] testing", buf);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: output: 0 [x] testing", buf);
ut_assertok(ops->set_value(dev, offset, 1));
ut_asserteq(1, ops->get_value(dev, offset));
/* Make it an input */
ut_assertok(ops->direction_input(dev, offset));
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: in: 1 [x] testing", buf);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: input: 1 [x] testing", buf);
sandbox_gpio_set_value(dev, offset, 0);
ut_asserteq(0, sandbox_gpio_get_value(dev, offset));
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: in: 0 [x] testing", buf);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: input: 0 [x] testing", buf);
ut_assertok(ops->free(dev, offset));
ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: in: 0 [ ]", buf);
ut_assertok(gpio_free(gpio));
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b4: input: 0 [ ]", buf);
/* Check the 'a' bank also */
ut_assertok(gpio_lookup_name("a15", &dev, &offset, &gpio));
@ -96,6 +98,18 @@ static int dm_test_gpio(struct dm_test_state *dms)
ut_asserteq_str("a", name);
ut_asserteq(20, offset_count);
return 0;
}
DM_TEST(dm_test_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test that sandbox anonymous GPIOs work correctly */
static int dm_test_gpio_anon(struct dm_test_state *dms)
{
unsigned int offset, gpio;
struct udevice *dev;
const char *name;
int offset_count;
/* And the anonymous bank */
ut_assertok(gpio_lookup_name("14", &dev, &offset, &gpio));
ut_asserteq_str(dev->name, "gpio_sandbox");
@ -108,4 +122,57 @@ static int dm_test_gpio(struct dm_test_state *dms)
return 0;
}
DM_TEST(dm_test_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
DM_TEST(dm_test_gpio_anon, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test that gpio_requestf() works as expected */
static int dm_test_gpio_requestf(struct dm_test_state *dms)
{
unsigned int offset, gpio;
struct udevice *dev;
char buf[80];
ut_assertok(gpio_lookup_name("b5", &dev, &offset, &gpio));
ut_assertok(gpio_requestf(gpio, "testing %d %s", 1, "hi"));
sandbox_gpio_set_direction(dev, offset, 1);
sandbox_gpio_set_value(dev, offset, 1);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b5: output: 1 [x] testing 1 hi", buf);
return 0;
}
DM_TEST(dm_test_gpio_requestf, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test that gpio_request() copies its string */
static int dm_test_gpio_copy(struct dm_test_state *dms)
{
unsigned int offset, gpio;
struct udevice *dev;
char buf[80], name[10];
ut_assertok(gpio_lookup_name("b6", &dev, &offset, &gpio));
strcpy(name, "odd_name");
ut_assertok(gpio_request(gpio, name));
sandbox_gpio_set_direction(dev, offset, 1);
sandbox_gpio_set_value(dev, offset, 1);
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b6: output: 1 [x] odd_name", buf);
strcpy(name, "nothing");
ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
ut_asserteq_str("b6: output: 1 [x] odd_name", buf);
return 0;
}
DM_TEST(dm_test_gpio_copy, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test that we don't leak memory with GPIOs */
static int dm_test_gpio_leak(struct dm_test_state *dms)
{
ut_assertok(dm_test_gpio(dms));
ut_assertok(dm_test_gpio_anon(dms));
ut_assertok(dm_test_gpio_requestf(dms));
ut_assertok(dm_leak_check_end(dms));
return 0;
}
DM_TEST(dm_test_gpio_leak, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);

View File

@ -7,6 +7,7 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <dm/test.h>
#include <dm/root.h>
#include <dm/uclass-internal.h>
@ -88,6 +89,7 @@ int dm_test_main(void)
printf("Test: %s\n", test->name);
ut_assertok(dm_test_init(dms));
dms->start = mallinfo();
if (test->flags & DM_TESTF_SCAN_PDATA)
ut_assertok(dm_scan_platdata(false));
if (test->flags & DM_TESTF_PROBE_TEST)