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:
commit
84a6df09c7
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
15
arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c
Normal file
15
arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c
Normal 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)
|
@ -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
|
||||
|
15
arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c
Normal file
15
arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c
Normal 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)
|
@ -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
|
||||
|
15
arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c
Normal file
15
arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c
Normal 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)
|
@ -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>;
|
||||
|
@ -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
|
24
arch/arm/include/asm/arch-uniphier/platdevice.h
Normal file
24
arch/arm/include/asm/arch-uniphier/platdevice.h
Normal 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 */
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
15
arch/x86/include/asm/arch-coreboot/gpio.h
Normal file
15
arch/x86/include/asm/arch-coreboot/gpio.h
Normal 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_ */
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -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.
|
@ -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)
|
||||
|
@ -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) = {
|
||||
|
@ -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),
|
||||
};
|
||||
|
@ -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(®s->gpio_psr) >> offset) & 0x01;
|
||||
}
|
||||
|
||||
static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
|
||||
{
|
||||
return (readl(®s->gpio_dr) >> offset) & 0x01;
|
||||
}
|
||||
|
||||
static int check_requested(struct udevice *dev, unsigned offset,
|
||||
const char *func)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev->uclass_priv;
|
||||
|
||||
if (!gpio_is_requested(bank, offset)) {
|
||||
printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
|
||||
func, uc_priv->bank_name, offset);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set GPIO pin 'gpio' as an input */
|
||||
static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct mxc_bank_info *bank = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = check_requested(dev, offset, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure GPIO direction as input. */
|
||||
mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
|
||||
@ -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[] = {
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
38
drivers/serial/serial_coreboot.c
Normal file
38
drivers/serial/serial_coreboot.c
Normal 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,
|
||||
};
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
47
drivers/serial/serial_omap.c
Normal file
47
drivers/serial/serial_omap.c
Normal 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,
|
||||
};
|
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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.
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
18
include/dm/platform_data/serial-uniphier.h
Normal file
18
include/dm/platform_data/serial-uniphier.h
Normal 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 */
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
111
test/dm/gpio.c
111
test/dm/gpio.c
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user