mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-09-30 18:21:28 +02:00
Merge branch '2021-07-14-platform-updates'
- Assorted platform updates
This commit is contained in:
commit
eae8c7c338
@ -118,8 +118,8 @@ F: cmd/arm/
|
||||
ARM ALTERA SOCFPGA
|
||||
M: Marek Vasut <marex@denx.de>
|
||||
M: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
|
||||
M: Ley Foon Tan <lftan.linux@gmail.com>
|
||||
S: Maintainted
|
||||
M: Tien Fong Chee <tien.fong.chee@intel.com>
|
||||
S: Maintained
|
||||
T: git https://source.denx.de/u-boot/custodians/u-boot-socfpga.git
|
||||
F: arch/arm/mach-socfpga/
|
||||
F: drivers/sysreset/sysreset_socfpga*
|
||||
|
@ -254,6 +254,7 @@ dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \
|
||||
uniphier-ld11-global.dtb \
|
||||
uniphier-ld11-ref.dtb
|
||||
dtb-$(CONFIG_ARCH_UNIPHIER_LD20) += \
|
||||
uniphier-ld20-akebi96.dtb \
|
||||
uniphier-ld20-global.dtb \
|
||||
uniphier-ld20-ref.dtb
|
||||
dtb-$(CONFIG_ARCH_UNIPHIER_LD4) += \
|
||||
|
189
arch/arm/dts/uniphier-ld20-akebi96.dts
Normal file
189
arch/arm/dts/uniphier-ld20-akebi96.dts
Normal file
@ -0,0 +1,189 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+ OR MIT
|
||||
//
|
||||
// Device Tree Source for Akebi96 Development Board
|
||||
//
|
||||
// Derived from uniphier-ld20-global.dts.
|
||||
//
|
||||
// Copyright (C) 2015-2017 Socionext Inc.
|
||||
// Copyright (C) 2019-2020 Linaro Ltd.
|
||||
|
||||
/dts-v1/;
|
||||
#include <dt-bindings/gpio/uniphier-gpio.h>
|
||||
#include "uniphier-ld20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Akebi96";
|
||||
compatible = "socionext,uniphier-ld20-akebi96",
|
||||
"socionext,uniphier-ld20";
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
serial2 = &serial2;
|
||||
serial3 = &serial3;
|
||||
i2c0 = &i2c0;
|
||||
i2c1 = &i2c1;
|
||||
i2c2 = &i2c2;
|
||||
i2c3 = &i2c3;
|
||||
i2c4 = &i2c4;
|
||||
i2c5 = &i2c5;
|
||||
spi0 = &spi0;
|
||||
spi1 = &spi1;
|
||||
spi2 = &spi2;
|
||||
spi3 = &spi3;
|
||||
ethernet0 = ð
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0 0x80000000 0 0xc0000000>;
|
||||
};
|
||||
|
||||
framebuffer@c0000000 {
|
||||
compatible = "simple-framebuffer";
|
||||
reg = <0 0xc0000000 0 0x02000000>;
|
||||
width = <1920>;
|
||||
height = <1080>;
|
||||
stride = <7680>;
|
||||
format = "a8r8g8b8";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
memory@c0000000 {
|
||||
reg = <0 0xc0000000 0 0x02000000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "audio-graph-card";
|
||||
label = "UniPhier LD20";
|
||||
dais = <&spdif_port0
|
||||
&comp_spdif_port0>;
|
||||
};
|
||||
|
||||
spdif-out {
|
||||
compatible = "linux,spdif-dit";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
spdif_tx: endpoint {
|
||||
remote-endpoint = <&spdif_hiecout1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
comp-spdif-out {
|
||||
compatible = "linux,spdif-dit";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
comp_spdif_tx: endpoint {
|
||||
remote-endpoint = <&comp_spdif_hiecout1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
firmware {
|
||||
optee {
|
||||
compatible = "linaro,optee-tz";
|
||||
method = "smc";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&spi3 {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
usb-over-spi@0 {
|
||||
compatible = "maxim,max3421-udc";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <12500000>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupt-names = "udc";
|
||||
interrupts = <0 2>;
|
||||
};
|
||||
};
|
||||
|
||||
&serial0 {
|
||||
/* Onboard USB-UART */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&serial2 {
|
||||
/* LS connector UART1 */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&serial3 {
|
||||
/* LS connector UART0 */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spdif_hiecout1 {
|
||||
remote-endpoint = <&spdif_tx>;
|
||||
};
|
||||
|
||||
&comp_spdif_hiecout1 {
|
||||
remote-endpoint = <&comp_spdif_tx>;
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
/* LS connector I2C0 */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
/* LS connector I2C1 */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ð {
|
||||
status = "okay";
|
||||
phy-handle = <ðphy>;
|
||||
};
|
||||
|
||||
&mdio {
|
||||
ethphy: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&usb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio {
|
||||
/* IRQs for Max3421 */
|
||||
xirq0 {
|
||||
gpio-hog;
|
||||
gpios = <UNIPHIER_GPIO_IRQ(0) 1>;
|
||||
input;
|
||||
};
|
||||
xirq10 {
|
||||
gpio-hog;
|
||||
gpios = <UNIPHIER_GPIO_IRQ(10) 1>;
|
||||
input;
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl_aout1 {
|
||||
groups = "aout1b";
|
||||
};
|
||||
|
||||
&pinctrl_uart3 {
|
||||
groups = "uart3", "uart3_ctsrts";
|
||||
};
|
@ -10,7 +10,7 @@
|
||||
#include <common.h>
|
||||
|
||||
#define MAX_PIN_NAME_LEN 32
|
||||
static char pin_name[MAX_PIN_NAME_LEN];
|
||||
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
|
||||
static const char * const msm_pinctrl_pins[] = {
|
||||
"SDC1_CLK",
|
||||
"SDC1_CMD",
|
||||
@ -59,4 +59,3 @@ struct msm_pinctrl_data apq8016_data = {
|
||||
.get_function_mux = apq8016_get_function_mux,
|
||||
.get_pin_name = apq8016_get_pin_name,
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <common.h>
|
||||
|
||||
#define MAX_PIN_NAME_LEN 32
|
||||
static char pin_name[MAX_PIN_NAME_LEN];
|
||||
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
|
||||
static const char * const msm_pinctrl_pins[] = {
|
||||
"SDC1_CLK",
|
||||
"SDC1_CMD",
|
||||
|
@ -8,6 +8,7 @@ choice
|
||||
|
||||
config TARGET_STEMMY
|
||||
bool "Samsung (stemmy) board"
|
||||
select MISC_INIT_R
|
||||
help
|
||||
The Samsung "stemmy" board supports Samsung smartphones released with
|
||||
the ST-Ericsson NovaThor U8500 SoC, e.g.
|
||||
@ -15,6 +16,7 @@ config TARGET_STEMMY
|
||||
- Samsung Galaxy S III mini (GT-I8190) "golden"
|
||||
- Samsung Galaxy S Advance (GT-I9070) "janice"
|
||||
- Samsung Galaxy Xcover 2 (GT-S7710) "skomer"
|
||||
- Samsung Galaxy Ace 2 (GT-I8160) "codina"
|
||||
|
||||
and likely others as well (untested).
|
||||
|
||||
|
@ -7,6 +7,7 @@ the ST-Ericsson NovaThor U8500 SoC, e.g.
|
||||
- Samsung Galaxy S III mini (GT-I8190) "golden"
|
||||
- Samsung Galaxy S Advance (GT-I9070) "janice"
|
||||
- Samsung Galaxy Xcover 2 (GT-S7710) "skomer"
|
||||
- Samsung Galaxy Ace 2 (GT-I8160) "codina"
|
||||
|
||||
and likely others as well (untested).
|
||||
|
||||
|
@ -3,18 +3,165 @@
|
||||
* Copyright (C) 2019 Stephan Gerhold <stephan@gerhold.net>
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <env.h>
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
#include <stdlib.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* Parse atags provided by Samsung bootloader to get available memory */
|
||||
static ulong fw_mach __section(".data");
|
||||
static ulong fw_atags __section(".data");
|
||||
|
||||
static const struct tag *fw_atags_copy;
|
||||
static uint fw_atags_size;
|
||||
|
||||
void save_boot_params(ulong r0, ulong r1, ulong r2, ulong r3)
|
||||
{
|
||||
fw_mach = r1;
|
||||
fw_atags = r2;
|
||||
save_boot_params_ret();
|
||||
}
|
||||
|
||||
static const struct tag *fw_atags_get(void)
|
||||
{
|
||||
const struct tag *tags = (const struct tag *)fw_atags;
|
||||
|
||||
if (tags->hdr.tag != ATAG_CORE) {
|
||||
log_err("Invalid atags: tag 0x%x at %p\n", tags->hdr.tag, tags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
gd->ram_size = get_ram_size(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_SIZE);
|
||||
const struct tag *t, *tags = fw_atags_get();
|
||||
|
||||
if (!tags)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_tag(t, tags) {
|
||||
if (t->hdr.tag != ATAG_MEM)
|
||||
continue;
|
||||
|
||||
debug("Memory: %#x-%#x (size %#x)\n", t->u.mem.start,
|
||||
t->u.mem.start + t->u.mem.size, t->u.mem.size);
|
||||
gd->ram_size += t->u.mem.size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dram_init_banksize(void)
|
||||
{
|
||||
const struct tag *t, *tags = fw_atags_get();
|
||||
unsigned int bank = 0;
|
||||
|
||||
if (!tags)
|
||||
return -EINVAL;
|
||||
|
||||
for_each_tag(t, tags) {
|
||||
if (t->hdr.tag != ATAG_MEM)
|
||||
continue;
|
||||
|
||||
gd->bd->bi_dram[bank].start = t->u.mem.start;
|
||||
gd->bd->bi_dram[bank].size = t->u.mem.size;
|
||||
if (++bank == CONFIG_NR_DRAM_BANKS)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
gd->bd->bi_arch_number = fw_mach;
|
||||
gd->bd->bi_boot_params = fw_atags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void parse_serial(const struct tag_serialnr *serialnr)
|
||||
{
|
||||
char serial[17];
|
||||
|
||||
if (env_get("serial#"))
|
||||
return;
|
||||
|
||||
sprintf(serial, "%08x%08x", serialnr->high, serialnr->low);
|
||||
env_set("serial#", serial);
|
||||
}
|
||||
|
||||
/*
|
||||
* The downstream/vendor kernel (provided by Samsung) uses ATAGS for booting.
|
||||
* It also requires an extremely long cmdline provided by the primary bootloader
|
||||
* that is not suitable for booting mainline.
|
||||
*
|
||||
* Since downstream is the only user of ATAGS, we emulate the behavior of the
|
||||
* Samsung bootloader by generating only the initrd atag in U-Boot, and copying
|
||||
* all other ATAGS as-is from the primary bootloader.
|
||||
*/
|
||||
static inline bool skip_atag(u32 tag)
|
||||
{
|
||||
return (tag == ATAG_NONE || tag == ATAG_CORE ||
|
||||
tag == ATAG_INITRD || tag == ATAG_INITRD2);
|
||||
}
|
||||
|
||||
static void copy_atags(const struct tag *tags)
|
||||
{
|
||||
const struct tag *t;
|
||||
struct tag *copy;
|
||||
|
||||
if (!tags)
|
||||
return;
|
||||
|
||||
/* Calculate necessary size for tags we want to copy */
|
||||
for_each_tag(t, tags) {
|
||||
if (skip_atag(t->hdr.tag))
|
||||
continue;
|
||||
|
||||
if (t->hdr.tag == ATAG_SERIAL)
|
||||
parse_serial(&t->u.serialnr);
|
||||
|
||||
fw_atags_size += t->hdr.size * sizeof(u32);
|
||||
}
|
||||
|
||||
if (!fw_atags_size)
|
||||
return; /* No tags to copy */
|
||||
|
||||
copy = malloc(fw_atags_size);
|
||||
if (!copy)
|
||||
return;
|
||||
fw_atags_copy = copy;
|
||||
|
||||
/* Copy tags */
|
||||
for_each_tag(t, tags) {
|
||||
if (skip_atag(t->hdr.tag))
|
||||
continue;
|
||||
|
||||
memcpy(copy, t, t->hdr.size * sizeof(u32));
|
||||
copy = tag_next(copy);
|
||||
}
|
||||
}
|
||||
|
||||
int misc_init_r(void)
|
||||
{
|
||||
copy_atags(fw_atags_get());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setup_board_tags(struct tag **in_params)
|
||||
{
|
||||
if (!fw_atags_copy)
|
||||
return;
|
||||
|
||||
/*
|
||||
* fw_atags_copy contains only full "struct tag" (plus data)
|
||||
* so copying it bytewise here should be fine.
|
||||
*/
|
||||
memcpy(*in_params, fw_atags_copy, fw_atags_size);
|
||||
*(u8 **)in_params += fw_atags_size;
|
||||
}
|
||||
|
@ -31,11 +31,15 @@ int __weak show_board_info(void)
|
||||
|
||||
if (IS_ENABLED(CONFIG_SYSINFO)) {
|
||||
/* This might provide more detail */
|
||||
ret = uclass_first_device_err(UCLASS_SYSINFO, &dev);
|
||||
if (!ret)
|
||||
ret = sysinfo_get_str(dev,
|
||||
ret = sysinfo_get(&dev);
|
||||
if (!ret) {
|
||||
ret = sysinfo_detect(dev);
|
||||
if (!ret) {
|
||||
ret = sysinfo_get_str(dev,
|
||||
SYSINFO_ID_BOARD_MODEL,
|
||||
sizeof(str), str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fail back to the main 'model' if available */
|
||||
|
@ -1,7 +1,7 @@
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_U8500=y
|
||||
CONFIG_SYS_TEXT_BASE=0x100000
|
||||
CONFIG_NR_DRAM_BANKS=1
|
||||
CONFIG_NR_DRAM_BANKS=2
|
||||
CONFIG_DEFAULT_DEVICE_TREE="ste-ux500-samsung-stemmy"
|
||||
CONFIG_SYS_CONSOLE_INFO_QUIET=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
|
@ -13,8 +13,7 @@ CONFIG_FIT=y
|
||||
CONFIG_FIT_SIGNATURE=y
|
||||
CONFIG_LEGACY_IMAGE_FORMAT=y
|
||||
CONFIG_BOOTDELAY=5
|
||||
CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="console=ttyAMA0 debug user_debug=31 earlycon=pl011,0x7ff80000 loglevel=9 androidboot.hardware=total_compute video=640x480-32@60 androidboot.boot_devices=1c050000.mmci ip=dhcp androidboot.selinux=permissive"
|
||||
# CONFIG_USE_BOOTARGS is not set
|
||||
# CONFIG_USE_BOOTCOMMAND is not set
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
# CONFIG_DISPLAY_BOARDINFO is not set
|
||||
|
@ -46,6 +46,7 @@ alias simongoldschmidt Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
|
||||
alias sjg Simon Glass <sjg@chromium.org>
|
||||
alias smcnutt Scott McNutt <smcnutt@psyent.com>
|
||||
alias stroese Stefan Roese <sr@denx.de>
|
||||
alias tienfong Tien Fong Chee <tien.fong.chee@intel.com>
|
||||
alias trini Tom Rini <trini@konsulko.com>
|
||||
alias wd Wolfgang Denk <wd@denx.de>
|
||||
alias priyankajain Priyanka Jain <priyanka.jain@nxp.com>
|
||||
@ -69,7 +70,7 @@ alias s3c samsung
|
||||
alias s5pc samsung
|
||||
alias samsung uboot, prom
|
||||
alias snapdragon uboot, mateusz
|
||||
alias socfpga uboot, marex, dinh, simongoldschmidt, leyfoon
|
||||
alias socfpga uboot, marex, dinh, simongoldschmidt, tienfong
|
||||
alias sunxi uboot, jagan, apritzel
|
||||
alias tegra uboot, sjg, Tom Warren <twarren@nvidia.com>, Stephen Warren <swarren@nvidia.com>
|
||||
alias tegra2 tegra
|
||||
|
@ -80,6 +80,8 @@ source "drivers/phy/allwinner/Kconfig"
|
||||
|
||||
source "drivers/phy/marvell/Kconfig"
|
||||
|
||||
source "drivers/phy/socionext/Kconfig"
|
||||
|
||||
source "drivers/pinctrl/Kconfig"
|
||||
|
||||
source "drivers/power/Kconfig"
|
||||
|
@ -96,6 +96,7 @@ obj-$(CONFIG_PCH) += pch/
|
||||
obj-y += phy/allwinner/
|
||||
obj-y += phy/marvell/
|
||||
obj-y += phy/rockchip/
|
||||
obj-y += phy/socionext/
|
||||
obj-y += rtc/
|
||||
obj-y += scsi/
|
||||
obj-y += sound/
|
||||
|
@ -29,6 +29,7 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
|
||||
UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19), /* usb30-phy (PXs2) */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20), /* usb31-phy (PXs2) */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(24, 0x2108, 2), /* pcie (Pro5) */
|
||||
{ /* sentinel */ }
|
||||
#endif
|
||||
};
|
||||
@ -43,6 +44,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
|
||||
UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12), /* usb30-phy0 (LD20) */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13), /* usb30-phy1 (LD20) */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 4), /* pcie */
|
||||
{ /* sentinel */ }
|
||||
#endif
|
||||
};
|
||||
@ -62,6 +64,7 @@ const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = {
|
||||
UNIPHIER_CLK_GATE_SIMPLE(18, 0x210c, 20), /* usb30-phy2 */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(20, 0x210c, 17), /* usb31-phy0 */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(21, 0x210c, 19), /* usb31-phy1 */
|
||||
UNIPHIER_CLK_GATE_SIMPLE(24, 0x210c, 3), /* pcie */
|
||||
{ /* sentinel */ }
|
||||
#endif
|
||||
};
|
||||
|
@ -495,4 +495,12 @@ config NX_GPIO
|
||||
The GPIOs for a device are defined in the device tree with one node
|
||||
for each bank.
|
||||
|
||||
config NOMADIK_GPIO
|
||||
bool "Nomadik GPIO driver"
|
||||
depends on DM_GPIO
|
||||
help
|
||||
Support GPIO access on ST-Ericsson Ux500 SoCs. The GPIOs are arranged
|
||||
into a number of banks each with 32 GPIOs. The GPIOs for a device are
|
||||
defined in the device tree with one node for each bank.
|
||||
|
||||
endmenu
|
||||
|
@ -43,7 +43,6 @@ obj-$(CONFIG_MPC8XXX_GPIO) += mpc8xxx_gpio.o
|
||||
obj-$(CONFIG_MPC83XX_SPISEL_BOOT) += mpc83xx_spisel_boot.o
|
||||
obj-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o
|
||||
obj-$(CONFIG_OMAP_GPIO) += omap_gpio.o
|
||||
obj-$(CONFIG_DB8500_GPIO) += db8500_gpio.o
|
||||
obj-$(CONFIG_BCM2835_GPIO) += bcm2835_gpio.o
|
||||
obj-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o
|
||||
obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o
|
||||
@ -68,3 +67,4 @@ obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o
|
||||
obj-$(CONFIG_MSCC_SGPIO) += mscc_sgpio.o
|
||||
obj-$(CONFIG_NX_GPIO) += nx_gpio.o
|
||||
obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o
|
||||
obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o
|
||||
|
@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code.
|
||||
* The purpose is that GPIO config found in kernel should work by simply
|
||||
* copy-paste it to U-Boot.
|
||||
*
|
||||
* Original Linux authors:
|
||||
* Copyright (C) 2008,2009 STMicroelectronics
|
||||
* Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
|
||||
* Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
|
||||
*
|
||||
* Ported to U-Boot by:
|
||||
* Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/db8500_gpio.h>
|
||||
#include <asm/arch/db8500_pincfg.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#define IO_ADDR(x) (void *) (x)
|
||||
|
||||
/*
|
||||
* The GPIO module in the db8500 Systems-on-Chip is an
|
||||
* AMBA device, managing 32 pins and alternate functions. The logic block
|
||||
* is currently only used in the db8500.
|
||||
*/
|
||||
|
||||
#define GPIO_TOTAL_PINS 268
|
||||
#define GPIO_PINS_PER_BLOCK 32
|
||||
#define GPIO_BLOCKS_COUNT (GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK + 1)
|
||||
#define GPIO_BLOCK(pin) (((pin + GPIO_PINS_PER_BLOCK) >> 5) - 1)
|
||||
#define GPIO_PIN_WITHIN_BLOCK(pin) ((pin)%(GPIO_PINS_PER_BLOCK))
|
||||
|
||||
/* Register in the logic block */
|
||||
#define DB8500_GPIO_DAT 0x00
|
||||
#define DB8500_GPIO_DATS 0x04
|
||||
#define DB8500_GPIO_DATC 0x08
|
||||
#define DB8500_GPIO_PDIS 0x0c
|
||||
#define DB8500_GPIO_DIR 0x10
|
||||
#define DB8500_GPIO_DIRS 0x14
|
||||
#define DB8500_GPIO_DIRC 0x18
|
||||
#define DB8500_GPIO_SLPC 0x1c
|
||||
#define DB8500_GPIO_AFSLA 0x20
|
||||
#define DB8500_GPIO_AFSLB 0x24
|
||||
|
||||
#define DB8500_GPIO_RIMSC 0x40
|
||||
#define DB8500_GPIO_FIMSC 0x44
|
||||
#define DB8500_GPIO_IS 0x48
|
||||
#define DB8500_GPIO_IC 0x4c
|
||||
#define DB8500_GPIO_RWIMSC 0x50
|
||||
#define DB8500_GPIO_FWIMSC 0x54
|
||||
#define DB8500_GPIO_WKS 0x58
|
||||
|
||||
static void __iomem *get_gpio_addr(unsigned gpio)
|
||||
{
|
||||
/* Our list of GPIO chips */
|
||||
static void __iomem *gpio_addrs[GPIO_BLOCKS_COUNT] = {
|
||||
IO_ADDR(CFG_GPIO_0_BASE),
|
||||
IO_ADDR(CFG_GPIO_1_BASE),
|
||||
IO_ADDR(CFG_GPIO_2_BASE),
|
||||
IO_ADDR(CFG_GPIO_3_BASE),
|
||||
IO_ADDR(CFG_GPIO_4_BASE),
|
||||
IO_ADDR(CFG_GPIO_5_BASE),
|
||||
IO_ADDR(CFG_GPIO_6_BASE),
|
||||
IO_ADDR(CFG_GPIO_7_BASE),
|
||||
IO_ADDR(CFG_GPIO_8_BASE)
|
||||
};
|
||||
|
||||
return gpio_addrs[GPIO_BLOCK(gpio)];
|
||||
}
|
||||
|
||||
static unsigned get_gpio_offset(unsigned gpio)
|
||||
{
|
||||
return GPIO_PIN_WITHIN_BLOCK(gpio);
|
||||
}
|
||||
|
||||
/* Can only be called from config_pin. Don't configure alt-mode directly */
|
||||
static void gpio_set_mode(unsigned gpio, enum db8500_gpio_alt mode)
|
||||
{
|
||||
void __iomem *addr = get_gpio_addr(gpio);
|
||||
unsigned offset = get_gpio_offset(gpio);
|
||||
u32 bit = 1 << offset;
|
||||
u32 afunc, bfunc;
|
||||
|
||||
afunc = readl(addr + DB8500_GPIO_AFSLA) & ~bit;
|
||||
bfunc = readl(addr + DB8500_GPIO_AFSLB) & ~bit;
|
||||
if (mode & DB8500_GPIO_ALT_A)
|
||||
afunc |= bit;
|
||||
if (mode & DB8500_GPIO_ALT_B)
|
||||
bfunc |= bit;
|
||||
writel(afunc, addr + DB8500_GPIO_AFSLA);
|
||||
writel(bfunc, addr + DB8500_GPIO_AFSLB);
|
||||
}
|
||||
|
||||
/**
|
||||
* db8500_gpio_set_pull() - enable/disable pull up/down on a gpio
|
||||
* @gpio: pin number
|
||||
* @pull: one of DB8500_GPIO_PULL_DOWN, DB8500_GPIO_PULL_UP,
|
||||
* and DB8500_GPIO_PULL_NONE
|
||||
*
|
||||
* Enables/disables pull up/down on a specified pin. This only takes effect if
|
||||
* the pin is configured as an input (either explicitly or by the alternate
|
||||
* function).
|
||||
*
|
||||
* NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
|
||||
* configured as an input. Otherwise, due to the way the controller registers
|
||||
* work, this function will change the value output on the pin.
|
||||
*/
|
||||
void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull)
|
||||
{
|
||||
void __iomem *addr = get_gpio_addr(gpio);
|
||||
unsigned offset = get_gpio_offset(gpio);
|
||||
u32 bit = 1 << offset;
|
||||
u32 pdis;
|
||||
|
||||
pdis = readl(addr + DB8500_GPIO_PDIS);
|
||||
if (pull == DB8500_GPIO_PULL_NONE)
|
||||
pdis |= bit;
|
||||
else
|
||||
pdis &= ~bit;
|
||||
writel(pdis, addr + DB8500_GPIO_PDIS);
|
||||
|
||||
if (pull == DB8500_GPIO_PULL_UP)
|
||||
writel(bit, addr + DB8500_GPIO_DATS);
|
||||
else if (pull == DB8500_GPIO_PULL_DOWN)
|
||||
writel(bit, addr + DB8500_GPIO_DATC);
|
||||
}
|
||||
|
||||
void db8500_gpio_make_input(unsigned gpio)
|
||||
{
|
||||
void __iomem *addr = get_gpio_addr(gpio);
|
||||
unsigned offset = get_gpio_offset(gpio);
|
||||
|
||||
writel(1 << offset, addr + DB8500_GPIO_DIRC);
|
||||
}
|
||||
|
||||
int db8500_gpio_get_input(unsigned gpio)
|
||||
{
|
||||
void __iomem *addr = get_gpio_addr(gpio);
|
||||
unsigned offset = get_gpio_offset(gpio);
|
||||
u32 bit = 1 << offset;
|
||||
|
||||
printf("db8500_gpio_get_input gpio=%u addr=%p offset=%u bit=%#x\n",
|
||||
gpio, addr, offset, bit);
|
||||
|
||||
return (readl(addr + DB8500_GPIO_DAT) & bit) != 0;
|
||||
}
|
||||
|
||||
void db8500_gpio_make_output(unsigned gpio, int val)
|
||||
{
|
||||
void __iomem *addr = get_gpio_addr(gpio);
|
||||
unsigned offset = get_gpio_offset(gpio);
|
||||
|
||||
writel(1 << offset, addr + DB8500_GPIO_DIRS);
|
||||
db8500_gpio_set_output(gpio, val);
|
||||
}
|
||||
|
||||
void db8500_gpio_set_output(unsigned gpio, int val)
|
||||
{
|
||||
void __iomem *addr = get_gpio_addr(gpio);
|
||||
unsigned offset = get_gpio_offset(gpio);
|
||||
|
||||
if (val)
|
||||
writel(1 << offset, addr + DB8500_GPIO_DATS);
|
||||
else
|
||||
writel(1 << offset, addr + DB8500_GPIO_DATC);
|
||||
}
|
||||
|
||||
/**
|
||||
* config_pin - configure a pin's mux attributes
|
||||
* @cfg: pin configuration
|
||||
*
|
||||
* Configures a pin's mode (alternate function or GPIO), its pull up status,
|
||||
* and its sleep mode based on the specified configuration. The @cfg is
|
||||
* usually one of the SoC specific macros defined in mach/<soc>-pins.h. These
|
||||
* are constructed using, and can be further enhanced with, the macros in
|
||||
* plat/pincfg.h.
|
||||
*
|
||||
* If a pin's mode is set to GPIO, it is configured as an input to avoid
|
||||
* side-effects. The gpio can be manipulated later using standard GPIO API
|
||||
* calls.
|
||||
*/
|
||||
static void config_pin(unsigned long cfg)
|
||||
{
|
||||
int pin = PIN_NUM(cfg);
|
||||
int pull = PIN_PULL(cfg);
|
||||
int af = PIN_ALT(cfg);
|
||||
int output = PIN_DIR(cfg);
|
||||
int val = PIN_VAL(cfg);
|
||||
|
||||
if (output)
|
||||
db8500_gpio_make_output(pin, val);
|
||||
else {
|
||||
db8500_gpio_make_input(pin);
|
||||
db8500_gpio_set_pull(pin, pull);
|
||||
}
|
||||
|
||||
gpio_set_mode(pin, af);
|
||||
}
|
||||
|
||||
/**
|
||||
* db8500_config_pins - configure several pins at once
|
||||
* @cfgs: array of pin configurations
|
||||
* @num: number of elments in the array
|
||||
*
|
||||
* Configures several pins using config_pin(). Refer to that function for
|
||||
* further information.
|
||||
*/
|
||||
void db8500_gpio_config_pins(unsigned long *cfgs, size_t num)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
config_pin(cfgs[i]);
|
||||
}
|
125
drivers/gpio/nmk_gpio.c
Normal file
125
drivers/gpio/nmk_gpio.c
Normal file
@ -0,0 +1,125 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* Copyright (C) 2019 Stephan Gerhold */
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct nmk_gpio_regs {
|
||||
u32 dat; /* data */
|
||||
u32 dats; /* data set */
|
||||
u32 datc; /* data clear */
|
||||
u32 pdis; /* pull disable */
|
||||
u32 dir; /* direction */
|
||||
u32 dirs; /* direction set */
|
||||
u32 dirc; /* direction clear */
|
||||
u32 slpm; /* sleep mode */
|
||||
u32 afsla; /* alternate function select A */
|
||||
u32 afslb; /* alternate function select B */
|
||||
u32 lowemi; /* low EMI mode */
|
||||
};
|
||||
|
||||
struct nmk_gpio {
|
||||
struct nmk_gpio_regs *regs;
|
||||
};
|
||||
|
||||
static int nmk_gpio_get_value(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct nmk_gpio *priv = dev_get_priv(dev);
|
||||
|
||||
return !!(readl(&priv->regs->dat) & BIT(offset));
|
||||
}
|
||||
|
||||
static int nmk_gpio_set_value(struct udevice *dev, unsigned offset, int value)
|
||||
{
|
||||
struct nmk_gpio *priv = dev_get_priv(dev);
|
||||
|
||||
if (value)
|
||||
writel(BIT(offset), &priv->regs->dats);
|
||||
else
|
||||
writel(BIT(offset), &priv->regs->datc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmk_gpio_get_function(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct nmk_gpio *priv = dev_get_priv(dev);
|
||||
|
||||
if (readl(&priv->regs->afsla) & BIT(offset) ||
|
||||
readl(&priv->regs->afslb) & BIT(offset))
|
||||
return GPIOF_FUNC;
|
||||
|
||||
if (readl(&priv->regs->dir) & BIT(offset))
|
||||
return GPIOF_OUTPUT;
|
||||
else
|
||||
return GPIOF_INPUT;
|
||||
}
|
||||
|
||||
static int nmk_gpio_direction_input(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
struct nmk_gpio *priv = dev_get_priv(dev);
|
||||
|
||||
writel(BIT(offset), &priv->regs->dirc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmk_gpio_direction_output(struct udevice *dev, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct nmk_gpio *priv = dev_get_priv(dev);
|
||||
|
||||
writel(BIT(offset), &priv->regs->dirs);
|
||||
return nmk_gpio_set_value(dev, offset, value);
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops nmk_gpio_ops = {
|
||||
.get_value = nmk_gpio_get_value,
|
||||
.set_value = nmk_gpio_set_value,
|
||||
.get_function = nmk_gpio_get_function,
|
||||
.direction_input = nmk_gpio_direction_input,
|
||||
.direction_output = nmk_gpio_direction_output,
|
||||
};
|
||||
|
||||
static int nmk_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
struct nmk_gpio *priv = dev_get_priv(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
char buf[20];
|
||||
u32 bank;
|
||||
int ret;
|
||||
|
||||
priv->regs = dev_read_addr_ptr(dev);
|
||||
if (!priv->regs)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dev_read_u32(dev, "gpio-bank", &bank);
|
||||
if (ret < 0) {
|
||||
printf("nmk_gpio(%s): Failed to read gpio-bank\n", dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sprintf(buf, "nmk%u-gpio", bank);
|
||||
uc_priv->bank_name = strdup(buf);
|
||||
if (!uc_priv->bank_name)
|
||||
return -ENOMEM;
|
||||
|
||||
uc_priv->gpio_count = sizeof(priv->regs->dat) * BITS_PER_BYTE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id nmk_gpio_ids[] = {
|
||||
{ .compatible = "st,nomadik-gpio" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(gpio_nmk) = {
|
||||
.name = "nmk_gpio",
|
||||
.id = UCLASS_GPIO,
|
||||
.of_match = nmk_gpio_ids,
|
||||
.probe = nmk_gpio_probe,
|
||||
.ops = &nmk_gpio_ops,
|
||||
.priv_auto = sizeof(struct nmk_gpio),
|
||||
};
|
@ -264,6 +264,7 @@ static const struct i2c_eeprom_drv_data atmel24c512_data = {
|
||||
static const struct udevice_id i2c_eeprom_std_ids[] = {
|
||||
{ .compatible = "i2c-eeprom", (ulong)&eeprom_data },
|
||||
{ .compatible = "microchip,24aa02e48", (ulong)&mc24aa02e48_data },
|
||||
{ .compatible = "atmel,24c01", (ulong)&atmel24c01a_data },
|
||||
{ .compatible = "atmel,24c01a", (ulong)&atmel24c01a_data },
|
||||
{ .compatible = "atmel,24c02", (ulong)&atmel24c02_data },
|
||||
{ .compatible = "atmel,24c04", (ulong)&atmel24c04_data },
|
||||
|
@ -340,4 +340,14 @@ config PCI_BRCMSTB
|
||||
on Broadcom set-top-box (STB) SoCs.
|
||||
This driver currently supports only BCM2711 SoC and RC mode
|
||||
of the controller.
|
||||
|
||||
config PCIE_UNIPHIER
|
||||
bool "Socionext UniPhier PCIe driver"
|
||||
depends on DM_PCI
|
||||
depends on ARCH_UNIPHIER
|
||||
select PHY_UNIPHIER_PCIE
|
||||
help
|
||||
Say Y here if you want to enable PCIe controller support on
|
||||
UniPhier SoCs.
|
||||
|
||||
endif
|
||||
|
@ -56,3 +56,4 @@ obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o
|
||||
obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o
|
||||
obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o
|
||||
obj-$(CONFIG_PCIE_DW_SIFIVE) += pcie_dw_sifive.o
|
||||
obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o
|
||||
|
424
drivers/pci/pcie_uniphier.c
Normal file
424
drivers/pci/pcie_uniphier.c
Normal file
@ -0,0 +1,424 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* pcie_uniphier.c - Socionext UniPhier PCIe driver
|
||||
* Copyright 2019-2021 Socionext, Inc.
|
||||
*/
|
||||
|
||||
#include <clk.h>
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <generic-phy.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <pci.h>
|
||||
#include <reset.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* DBI registers */
|
||||
#define PCIE_LINK_STATUS_REG 0x0080
|
||||
#define PCIE_LINK_STATUS_WIDTH_MASK GENMASK(25, 20)
|
||||
#define PCIE_LINK_STATUS_SPEED_MASK GENMASK(19, 16)
|
||||
|
||||
#define PCIE_MISC_CONTROL_1_OFF 0x08BC
|
||||
#define PCIE_DBI_RO_WR_EN BIT(0)
|
||||
|
||||
/* DBI iATU registers */
|
||||
#define PCIE_ATU_VIEWPORT 0x0900
|
||||
#define PCIE_ATU_REGION_INBOUND BIT(31)
|
||||
#define PCIE_ATU_REGION_OUTBOUND 0
|
||||
#define PCIE_ATU_REGION_INDEX_MASK GENMASK(3, 0)
|
||||
|
||||
#define PCIE_ATU_CR1 0x0904
|
||||
#define PCIE_ATU_TYPE_MEM 0
|
||||
#define PCIE_ATU_TYPE_IO 2
|
||||
#define PCIE_ATU_TYPE_CFG0 4
|
||||
#define PCIE_ATU_TYPE_CFG1 5
|
||||
|
||||
#define PCIE_ATU_CR2 0x0908
|
||||
#define PCIE_ATU_ENABLE BIT(31)
|
||||
#define PCIE_ATU_MATCH_MODE BIT(30)
|
||||
#define PCIE_ATU_BAR_NUM_MASK GENMASK(10, 8)
|
||||
|
||||
#define PCIE_ATU_LOWER_BASE 0x090C
|
||||
#define PCIE_ATU_UPPER_BASE 0x0910
|
||||
#define PCIE_ATU_LIMIT 0x0914
|
||||
#define PCIE_ATU_LOWER_TARGET 0x0918
|
||||
#define PCIE_ATU_BUS(x) FIELD_PREP(GENMASK(31, 24), x)
|
||||
#define PCIE_ATU_DEV(x) FIELD_PREP(GENMASK(23, 19), x)
|
||||
#define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x)
|
||||
#define PCIE_ATU_UPPER_TARGET 0x091C
|
||||
|
||||
/* Link Glue registers */
|
||||
#define PCL_PINCTRL0 0x002c
|
||||
#define PCL_PERST_PLDN_REGEN BIT(12)
|
||||
#define PCL_PERST_NOE_REGEN BIT(11)
|
||||
#define PCL_PERST_OUT_REGEN BIT(8)
|
||||
#define PCL_PERST_PLDN_REGVAL BIT(4)
|
||||
#define PCL_PERST_NOE_REGVAL BIT(3)
|
||||
#define PCL_PERST_OUT_REGVAL BIT(0)
|
||||
|
||||
#define PCL_MODE 0x8000
|
||||
#define PCL_MODE_REGEN BIT(8)
|
||||
#define PCL_MODE_REGVAL BIT(0)
|
||||
|
||||
#define PCL_APP_READY_CTRL 0x8008
|
||||
#define PCL_APP_LTSSM_ENABLE BIT(0)
|
||||
|
||||
#define PCL_APP_PM0 0x8078
|
||||
#define PCL_SYS_AUX_PWR_DET BIT(8)
|
||||
|
||||
#define PCL_STATUS_LINK 0x8140
|
||||
#define PCL_RDLH_LINK_UP BIT(1)
|
||||
#define PCL_XMLH_LINK_UP BIT(0)
|
||||
|
||||
#define LINK_UP_TIMEOUT_MS 100
|
||||
|
||||
struct uniphier_pcie_priv {
|
||||
void *base;
|
||||
void *dbi_base;
|
||||
void *cfg_base;
|
||||
fdt_size_t cfg_size;
|
||||
struct fdt_resource link_res;
|
||||
struct fdt_resource dbi_res;
|
||||
struct fdt_resource cfg_res;
|
||||
|
||||
struct clk clk;
|
||||
struct reset_ctl rst;
|
||||
struct phy phy;
|
||||
|
||||
struct pci_region io;
|
||||
struct pci_region mem;
|
||||
};
|
||||
|
||||
static int pcie_dw_get_link_speed(struct uniphier_pcie_priv *priv)
|
||||
{
|
||||
u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
|
||||
|
||||
return FIELD_GET(PCIE_LINK_STATUS_SPEED_MASK, val);
|
||||
}
|
||||
|
||||
static int pcie_dw_get_link_width(struct uniphier_pcie_priv *priv)
|
||||
{
|
||||
u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
|
||||
|
||||
return FIELD_GET(PCIE_LINK_STATUS_WIDTH_MASK, val);
|
||||
}
|
||||
|
||||
static void pcie_dw_prog_outbound_atu(struct uniphier_pcie_priv *priv,
|
||||
int index, int type, u64 cpu_addr,
|
||||
u64 pci_addr, u32 size)
|
||||
{
|
||||
writel(PCIE_ATU_REGION_OUTBOUND
|
||||
| FIELD_PREP(PCIE_ATU_REGION_INDEX_MASK, index),
|
||||
priv->dbi_base + PCIE_ATU_VIEWPORT);
|
||||
writel(lower_32_bits(cpu_addr),
|
||||
priv->dbi_base + PCIE_ATU_LOWER_BASE);
|
||||
writel(upper_32_bits(cpu_addr),
|
||||
priv->dbi_base + PCIE_ATU_UPPER_BASE);
|
||||
writel(lower_32_bits(cpu_addr + size - 1),
|
||||
priv->dbi_base + PCIE_ATU_LIMIT);
|
||||
writel(lower_32_bits(pci_addr),
|
||||
priv->dbi_base + PCIE_ATU_LOWER_TARGET);
|
||||
writel(upper_32_bits(pci_addr),
|
||||
priv->dbi_base + PCIE_ATU_UPPER_TARGET);
|
||||
|
||||
writel(type, priv->dbi_base + PCIE_ATU_CR1);
|
||||
writel(PCIE_ATU_ENABLE, priv->dbi_base + PCIE_ATU_CR2);
|
||||
}
|
||||
|
||||
static int uniphier_pcie_addr_valid(pci_dev_t bdf, int first_busno)
|
||||
{
|
||||
/* accept only device {0,1} on first bus */
|
||||
if ((PCI_BUS(bdf) != first_busno) || (PCI_DEV(bdf) > 1))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uniphier_pcie_conf_address(const struct udevice *dev, pci_dev_t bdf,
|
||||
uint offset, void **paddr)
|
||||
{
|
||||
struct uniphier_pcie_priv *priv = dev_get_priv(dev);
|
||||
u32 busdev;
|
||||
int seq = dev_seq(dev);
|
||||
int ret;
|
||||
|
||||
ret = uniphier_pcie_addr_valid(bdf, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((PCI_BUS(bdf) == seq) && !PCI_DEV(bdf)) {
|
||||
*paddr = (void *)(priv->dbi_base + offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
busdev = PCIE_ATU_BUS(PCI_BUS(bdf) - seq)
|
||||
| PCIE_ATU_DEV(PCI_DEV(bdf))
|
||||
| PCIE_ATU_FUNC(PCI_FUNC(bdf));
|
||||
|
||||
pcie_dw_prog_outbound_atu(priv, 0,
|
||||
PCIE_ATU_TYPE_CFG0, (u64)priv->cfg_base,
|
||||
busdev, priv->cfg_size);
|
||||
*paddr = (void *)(priv->cfg_base + offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uniphier_pcie_read_config(const struct udevice *dev, pci_dev_t bdf,
|
||||
uint offset, ulong *valp,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
return pci_generic_mmap_read_config(dev, uniphier_pcie_conf_address,
|
||||
bdf, offset, valp, size);
|
||||
}
|
||||
|
||||
static int uniphier_pcie_write_config(struct udevice *dev, pci_dev_t bdf,
|
||||
uint offset, ulong val,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
return pci_generic_mmap_write_config(dev, uniphier_pcie_conf_address,
|
||||
bdf, offset, val, size);
|
||||
}
|
||||
|
||||
static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_priv *priv,
|
||||
bool enable)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(priv->base + PCL_APP_READY_CTRL);
|
||||
if (enable)
|
||||
val |= PCL_APP_LTSSM_ENABLE;
|
||||
else
|
||||
val &= ~PCL_APP_LTSSM_ENABLE;
|
||||
writel(val, priv->base + PCL_APP_READY_CTRL);
|
||||
}
|
||||
|
||||
static int uniphier_pcie_link_up(struct uniphier_pcie_priv *priv)
|
||||
{
|
||||
u32 val, mask;
|
||||
|
||||
val = readl(priv->base + PCL_STATUS_LINK);
|
||||
mask = PCL_RDLH_LINK_UP | PCL_XMLH_LINK_UP;
|
||||
|
||||
return (val & mask) == mask;
|
||||
}
|
||||
|
||||
static int uniphier_pcie_wait_link(struct uniphier_pcie_priv *priv)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
timeout = get_timer(0) + LINK_UP_TIMEOUT_MS;
|
||||
|
||||
while (get_timer(0) < timeout) {
|
||||
if (uniphier_pcie_link_up(priv))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int uniphier_pcie_establish_link(struct uniphier_pcie_priv *priv)
|
||||
{
|
||||
if (uniphier_pcie_link_up(priv))
|
||||
return 0;
|
||||
|
||||
uniphier_pcie_ltssm_enable(priv, true);
|
||||
|
||||
return uniphier_pcie_wait_link(priv);
|
||||
}
|
||||
|
||||
static void uniphier_pcie_init_rc(struct uniphier_pcie_priv *priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* set RC mode */
|
||||
val = readl(priv->base + PCL_MODE);
|
||||
val |= PCL_MODE_REGEN;
|
||||
val &= ~PCL_MODE_REGVAL;
|
||||
writel(val, priv->base + PCL_MODE);
|
||||
|
||||
/* use auxiliary power detection */
|
||||
val = readl(priv->base + PCL_APP_PM0);
|
||||
val |= PCL_SYS_AUX_PWR_DET;
|
||||
writel(val, priv->base + PCL_APP_PM0);
|
||||
|
||||
/* assert PERST# */
|
||||
val = readl(priv->base + PCL_PINCTRL0);
|
||||
val &= ~(PCL_PERST_NOE_REGVAL | PCL_PERST_OUT_REGVAL
|
||||
| PCL_PERST_PLDN_REGVAL);
|
||||
val |= PCL_PERST_NOE_REGEN | PCL_PERST_OUT_REGEN
|
||||
| PCL_PERST_PLDN_REGEN;
|
||||
writel(val, priv->base + PCL_PINCTRL0);
|
||||
|
||||
uniphier_pcie_ltssm_enable(priv, false);
|
||||
|
||||
mdelay(100);
|
||||
|
||||
/* deassert PERST# */
|
||||
val = readl(priv->base + PCL_PINCTRL0);
|
||||
val |= PCL_PERST_OUT_REGVAL | PCL_PERST_OUT_REGEN;
|
||||
writel(val, priv->base + PCL_PINCTRL0);
|
||||
}
|
||||
|
||||
static void uniphier_pcie_setup_rc(struct uniphier_pcie_priv *priv,
|
||||
struct pci_controller *hose)
|
||||
{
|
||||
/* Store the IO and MEM windows settings for future use by the ATU */
|
||||
priv->io.phys_start = hose->regions[0].phys_start; /* IO base */
|
||||
priv->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */
|
||||
priv->io.size = hose->regions[0].size; /* IO size */
|
||||
priv->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
|
||||
priv->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */
|
||||
priv->mem.size = hose->regions[1].size; /* MEM size */
|
||||
|
||||
/* outbound: IO */
|
||||
pcie_dw_prog_outbound_atu(priv, 0,
|
||||
PCIE_ATU_TYPE_IO, priv->io.phys_start,
|
||||
priv->io.bus_start, priv->io.size);
|
||||
|
||||
/* outbound: MEM */
|
||||
pcie_dw_prog_outbound_atu(priv, 1,
|
||||
PCIE_ATU_TYPE_MEM, priv->mem.phys_start,
|
||||
priv->mem.bus_start, priv->mem.size);
|
||||
}
|
||||
|
||||
static int uniphier_pcie_probe(struct udevice *dev)
|
||||
{
|
||||
struct uniphier_pcie_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *ctlr = pci_get_controller(dev);
|
||||
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
|
||||
int ret;
|
||||
|
||||
priv->base = map_physmem(priv->link_res.start,
|
||||
fdt_resource_size(&priv->link_res),
|
||||
MAP_NOCACHE);
|
||||
priv->dbi_base = map_physmem(priv->dbi_res.start,
|
||||
fdt_resource_size(&priv->dbi_res),
|
||||
MAP_NOCACHE);
|
||||
priv->cfg_size = fdt_resource_size(&priv->cfg_res);
|
||||
priv->cfg_base = map_physmem(priv->cfg_res.start,
|
||||
priv->cfg_size, MAP_NOCACHE);
|
||||
|
||||
ret = clk_enable(&priv->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = reset_deassert(&priv->rst);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to deassert reset: %d\n", ret);
|
||||
goto out_clk_release;
|
||||
}
|
||||
|
||||
ret = generic_phy_init(&priv->phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize phy: %d\n", ret);
|
||||
goto out_reset_release;
|
||||
}
|
||||
|
||||
ret = generic_phy_power_on(&priv->phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to power on phy: %d\n", ret);
|
||||
goto out_phy_exit;
|
||||
}
|
||||
|
||||
uniphier_pcie_init_rc(priv);
|
||||
|
||||
/* set DBI to read only */
|
||||
writel(0, priv->dbi_base + PCIE_MISC_CONTROL_1_OFF);
|
||||
|
||||
uniphier_pcie_setup_rc(priv, hose);
|
||||
|
||||
if (uniphier_pcie_establish_link(priv)) {
|
||||
printf("PCIE-%d: Link down\n", dev_seq(dev));
|
||||
} else {
|
||||
printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
|
||||
dev_seq(dev), pcie_dw_get_link_speed(priv),
|
||||
pcie_dw_get_link_width(priv), hose->first_busno);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_phy_exit:
|
||||
generic_phy_exit(&priv->phy);
|
||||
out_reset_release:
|
||||
reset_release_all(&priv->rst, 1);
|
||||
out_clk_release:
|
||||
clk_release_all(&priv->clk, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uniphier_pcie_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct uniphier_pcie_priv *priv = dev_get_priv(dev);
|
||||
const void *fdt = gd->fdt_blob;
|
||||
int node = dev_of_offset(dev);
|
||||
int ret;
|
||||
|
||||
ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
|
||||
"link", &priv->link_res);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get link regs: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
|
||||
"dbi", &priv->dbi_res);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get dbi regs: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
|
||||
"config", &priv->cfg_res);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get config regs: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get clocks property: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_get_by_index(dev, 0, &priv->rst);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get resets property: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = generic_phy_get_by_index(dev, 0, &priv->phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get phy property: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_pci_ops uniphier_pcie_ops = {
|
||||
.read_config = uniphier_pcie_read_config,
|
||||
.write_config = uniphier_pcie_write_config,
|
||||
};
|
||||
|
||||
static const struct udevice_id uniphier_pcie_ids[] = {
|
||||
{ .compatible = "socionext,uniphier-pcie", },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pcie_uniphier) = {
|
||||
.name = "uniphier-pcie",
|
||||
.id = UCLASS_PCI,
|
||||
.of_match = uniphier_pcie_ids,
|
||||
.probe = uniphier_pcie_probe,
|
||||
.ops = &uniphier_pcie_ops,
|
||||
.of_to_plat = uniphier_pcie_of_to_plat,
|
||||
.priv_auto = sizeof(struct uniphier_pcie_priv),
|
||||
};
|
@ -64,6 +64,12 @@ config MIPI_DPHY_HELPERS
|
||||
help
|
||||
Provides a number of helpers a core functions for MIPI D-PHY drivers.
|
||||
|
||||
config AB8500_USB_PHY
|
||||
bool "AB8500 USB PHY Driver"
|
||||
depends on PHY && PMIC_AB8500
|
||||
help
|
||||
Support for the USB OTG PHY in ST-Ericsson AB8500.
|
||||
|
||||
config BCM6318_USBH_PHY
|
||||
bool "BCM6318 USBH PHY support"
|
||||
depends on PHY && ARCH_BMIPS
|
||||
|
@ -6,6 +6,7 @@
|
||||
obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o
|
||||
obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o
|
||||
obj-$(CONFIG_MIPI_DPHY_HELPERS) += phy-core-mipi-dphy.o
|
||||
obj-$(CONFIG_AB8500_USB_PHY) += phy-ab8500-usb.o
|
||||
obj-$(CONFIG_BCM6318_USBH_PHY) += bcm6318-usbh-phy.o
|
||||
obj-$(CONFIG_BCM6348_USBH_PHY) += bcm6348-usbh-phy.o
|
||||
obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o
|
||||
|
52
drivers/phy/phy-ab8500-usb.c
Normal file
52
drivers/phy/phy-ab8500-usb.c
Normal file
@ -0,0 +1,52 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* Copyright (C) 2019 Stephan Gerhold */
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <generic-phy.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/ab8500.h>
|
||||
|
||||
#define AB8500_USB_PHY_CTRL_REG AB8500_USB(0x8A)
|
||||
#define AB8500_BIT_PHY_CTRL_HOST_EN BIT(0)
|
||||
#define AB8500_BIT_PHY_CTRL_DEVICE_EN BIT(1)
|
||||
#define AB8500_USB_PHY_CTRL_MASK (AB8500_BIT_PHY_CTRL_HOST_EN |\
|
||||
AB8500_BIT_PHY_CTRL_DEVICE_EN)
|
||||
|
||||
static int ab8500_usb_phy_power_on(struct phy *phy)
|
||||
{
|
||||
struct udevice *dev = phy->dev;
|
||||
uint set = AB8500_BIT_PHY_CTRL_DEVICE_EN;
|
||||
|
||||
if (CONFIG_IS_ENABLED(USB_MUSB_HOST))
|
||||
set = AB8500_BIT_PHY_CTRL_HOST_EN;
|
||||
|
||||
return pmic_clrsetbits(dev->parent, AB8500_USB_PHY_CTRL_REG,
|
||||
AB8500_USB_PHY_CTRL_MASK, set);
|
||||
}
|
||||
|
||||
static int ab8500_usb_phy_power_off(struct phy *phy)
|
||||
{
|
||||
struct udevice *dev = phy->dev;
|
||||
|
||||
return pmic_clrsetbits(dev->parent, AB8500_USB_PHY_CTRL_REG,
|
||||
AB8500_USB_PHY_CTRL_MASK, 0);
|
||||
}
|
||||
|
||||
struct phy_ops ab8500_usb_phy_ops = {
|
||||
.power_on = ab8500_usb_phy_power_on,
|
||||
.power_off = ab8500_usb_phy_power_off,
|
||||
};
|
||||
|
||||
static const struct udevice_id ab8500_usb_phy_ids[] = {
|
||||
{ .compatible = "stericsson,ab8500-usb" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(ab8500_usb_phy) = {
|
||||
.name = "ab8500_usb_phy",
|
||||
.id = UCLASS_PHY,
|
||||
.of_match = ab8500_usb_phy_ids,
|
||||
.ops = &ab8500_usb_phy_ops,
|
||||
};
|
12
drivers/phy/socionext/Kconfig
Normal file
12
drivers/phy/socionext/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# PHY drivers for Socionext platforms.
|
||||
#
|
||||
|
||||
config PHY_UNIPHIER_PCIE
|
||||
bool "UniPhier PCIe PHY driver"
|
||||
depends on PHY && ARCH_UNIPHIER
|
||||
imply REGMAP
|
||||
help
|
||||
Enable this to support PHY implemented in PCIe controller
|
||||
on UniPhier SoCs.
|
6
drivers/phy/socionext/Makefile
Normal file
6
drivers/phy/socionext/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for the phy drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_PHY_UNIPHIER_PCIE) += phy-uniphier-pcie.o
|
59
drivers/phy/socionext/phy-uniphier-pcie.c
Normal file
59
drivers/phy/socionext/phy-uniphier-pcie.c
Normal file
@ -0,0 +1,59 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* phy_uniphier_pcie.c - Socionext UniPhier PCIe PHY driver
|
||||
* Copyright 2019-2021 Socionext, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <generic-phy.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/compat.h>
|
||||
#include <regmap.h>
|
||||
#include <syscon.h>
|
||||
|
||||
/* SG */
|
||||
#define SG_USBPCIESEL 0x590
|
||||
#define SG_USBPCIESEL_PCIE BIT(0)
|
||||
|
||||
struct uniphier_pciephy_priv {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
static int uniphier_pciephy_init(struct phy *phy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uniphier_pciephy_probe(struct udevice *dev)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = syscon_regmap_lookup_by_phandle(dev,
|
||||
"socionext,syscon");
|
||||
if (!IS_ERR(regmap))
|
||||
regmap_update_bits(regmap, SG_USBPCIESEL,
|
||||
SG_USBPCIESEL_PCIE, SG_USBPCIESEL_PCIE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_ops uniphier_pciephy_ops = {
|
||||
.init = uniphier_pciephy_init,
|
||||
};
|
||||
|
||||
static const struct udevice_id uniphier_pciephy_ids[] = {
|
||||
{ .compatible = "socionext,uniphier-pro5-pcie-phy" },
|
||||
{ .compatible = "socionext,uniphier-ld20-pcie-phy" },
|
||||
{ .compatible = "socionext,uniphier-pxs3-pcie-phy" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(uniphier_pcie_phy) = {
|
||||
.name = "uniphier-pcie-phy",
|
||||
.id = UCLASS_PHY,
|
||||
.of_match = uniphier_pciephy_ids,
|
||||
.ops = &uniphier_pciephy_ops,
|
||||
.probe = uniphier_pciephy_probe,
|
||||
.priv_auto = sizeof(struct uniphier_pciephy_priv),
|
||||
};
|
@ -31,6 +31,16 @@ config SPL_PMIC_CHILDREN
|
||||
to call your regulator code (e.g. see rk8xx.c for direct functions
|
||||
for use in SPL).
|
||||
|
||||
config PMIC_AB8500
|
||||
bool "Enable driver for ST-Ericsson AB8500 PMIC via PRCMU"
|
||||
depends on DM_PMIC
|
||||
select REGMAP
|
||||
select SYSCON
|
||||
help
|
||||
Enable support for the ST-Ericsson AB8500 (Analog Baseband) PMIC.
|
||||
It connects with the ST-Ericsson DB8500 SoC via an I2C bus managed by
|
||||
the power/reset/clock management unit (PRCMU) firmware.
|
||||
|
||||
config PMIC_ACT8846
|
||||
bool "Enable support for the active-semi 8846 PMIC"
|
||||
depends on DM_PMIC && DM_I2C
|
||||
|
@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
|
||||
obj-$(CONFIG_$(SPL_)DM_PMIC_PCA9450) += pca9450.o
|
||||
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
|
||||
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
|
||||
obj-$(CONFIG_PMIC_AB8500) += ab8500.o
|
||||
obj-$(CONFIG_PMIC_ACT8846) += act8846.o
|
||||
obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
|
||||
obj-$(CONFIG_PMIC_MAX8997) += max8997.o
|
||||
|
268
drivers/power/pmic/ab8500.c
Normal file
268
drivers/power/pmic/ab8500.c
Normal file
@ -0,0 +1,268 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2019 Stephan Gerhold
|
||||
*
|
||||
* Adapted from old U-Boot and Linux kernel implementation:
|
||||
* Copyright (C) STMicroelectronics 2009
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <regmap.h>
|
||||
#include <syscon.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
#include <power/ab8500.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
/* CPU mailbox registers */
|
||||
#define PRCM_MBOX_CPU_VAL 0x0fc
|
||||
#define PRCM_MBOX_CPU_SET 0x100
|
||||
#define PRCM_MBOX_CPU_CLR 0x104
|
||||
|
||||
#define PRCM_ARM_IT1_CLR 0x48C
|
||||
#define PRCM_ARM_IT1_VAL 0x494
|
||||
|
||||
#define PRCM_TCDM_RANGE 2
|
||||
#define PRCM_REQ_MB5 0xE44
|
||||
#define PRCM_ACK_MB5 0xDF4
|
||||
#define _PRCM_MBOX_HEADER 0xFE8
|
||||
#define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5)
|
||||
#define PRCMU_I2C_MBOX_BIT BIT(5)
|
||||
|
||||
/* Mailbox 5 Requests */
|
||||
#define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0)
|
||||
#define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1)
|
||||
#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2)
|
||||
#define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3)
|
||||
#define PRCMU_I2C(bank) (((bank) << 1) | BIT(6))
|
||||
#define PRCMU_I2C_WRITE 0
|
||||
#define PRCMU_I2C_READ 1
|
||||
#define PRCMU_I2C_STOP_EN BIT(3)
|
||||
|
||||
/* Mailbox 5 ACKs */
|
||||
#define PRCM_ACK_MB5_I2C_STATUS (PRCM_ACK_MB5 + 0x1)
|
||||
#define PRCM_ACK_MB5_I2C_VAL (PRCM_ACK_MB5 + 0x3)
|
||||
#define PRCMU_I2C_WR_OK 0x1
|
||||
#define PRCMU_I2C_RD_OK 0x2
|
||||
|
||||
/* AB8500 version registers */
|
||||
#define AB8500_MISC_REV_REG AB8500_MISC(0x80)
|
||||
#define AB8500_MISC_IC_NAME_REG AB8500_MISC(0x82)
|
||||
|
||||
struct ab8500_priv {
|
||||
struct ab8500 ab8500;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static inline int prcmu_tcdm_readb(struct regmap *map, uint offset, u8 *valp)
|
||||
{
|
||||
return regmap_raw_read_range(map, PRCM_TCDM_RANGE, offset,
|
||||
valp, sizeof(*valp));
|
||||
}
|
||||
|
||||
static inline int prcmu_tcdm_writeb(struct regmap *map, uint offset, u8 val)
|
||||
{
|
||||
return regmap_raw_write_range(map, PRCM_TCDM_RANGE, offset,
|
||||
&val, sizeof(val));
|
||||
}
|
||||
|
||||
static int prcmu_wait_i2c_mbx_ready(struct ab8500_priv *priv)
|
||||
{
|
||||
uint val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(priv->regmap, PRCM_ARM_IT1_VAL, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & PRCMU_I2C_MBOX_BIT) {
|
||||
printf("ab8500: warning: PRCMU i2c mailbox was not acked\n");
|
||||
/* clear mailbox 5 ack irq */
|
||||
ret = regmap_write(priv->regmap, PRCM_ARM_IT1_CLR,
|
||||
PRCMU_I2C_MBOX_BIT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* wait for on-going transaction, use 1s timeout */
|
||||
return regmap_read_poll_timeout(priv->regmap, PRCM_MBOX_CPU_VAL, val,
|
||||
!(val & PRCMU_I2C_MBOX_BIT), 0, 1000);
|
||||
}
|
||||
|
||||
static int prcmu_wait_i2c_mbx_done(struct ab8500_priv *priv)
|
||||
{
|
||||
uint val;
|
||||
int ret;
|
||||
|
||||
/* set interrupt to XP70 */
|
||||
ret = regmap_write(priv->regmap, PRCM_MBOX_CPU_SET, PRCMU_I2C_MBOX_BIT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* wait for mailbox 5 (i2c) ack, use 1s timeout */
|
||||
return regmap_read_poll_timeout(priv->regmap, PRCM_ARM_IT1_VAL, val,
|
||||
(val & PRCMU_I2C_MBOX_BIT), 0, 1000);
|
||||
}
|
||||
|
||||
static int ab8500_transfer(struct udevice *dev, uint bank_reg, u8 *val,
|
||||
u8 op, u8 expected_status)
|
||||
{
|
||||
struct ab8500_priv *priv = dev_get_priv(dev);
|
||||
u8 reg = bank_reg & 0xff;
|
||||
u8 bank = bank_reg >> 8;
|
||||
u8 status;
|
||||
int ret;
|
||||
|
||||
ret = prcmu_wait_i2c_mbx_ready(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = prcmu_tcdm_writeb(priv->regmap, PRCM_MBOX_HEADER_REQ_MB5, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_SLAVE_OP,
|
||||
PRCMU_I2C(bank) | op);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_HW_BITS,
|
||||
PRCMU_I2C_STOP_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_REG, reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = prcmu_tcdm_writeb(priv->regmap, PRCM_REQ_MB5_I2C_VAL, *val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = prcmu_wait_i2c_mbx_done(priv);
|
||||
if (ret) {
|
||||
printf("%s: mailbox request timed out\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read transfer result */
|
||||
ret = prcmu_tcdm_readb(priv->regmap, PRCM_ACK_MB5_I2C_STATUS, &status);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = prcmu_tcdm_readb(priv->regmap, PRCM_ACK_MB5_I2C_VAL, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Clear mailbox 5 ack irq. Note that the transfer is already complete
|
||||
* here so checking for errors does not make sense. Clearing the irq
|
||||
* will be retried in prcmu_wait_i2c_mbx_ready() on the next transfer.
|
||||
*/
|
||||
regmap_write(priv->regmap, PRCM_ARM_IT1_CLR, PRCMU_I2C_MBOX_BIT);
|
||||
|
||||
if (status != expected_status) {
|
||||
/*
|
||||
* AB8500 does not have the AB8500_MISC_IC_NAME_REG register,
|
||||
* but we need to try reading it to detect AB8505.
|
||||
* In case of an error, assume that we have AB8500.
|
||||
*/
|
||||
if (op == PRCMU_I2C_READ && bank_reg == AB8500_MISC_IC_NAME_REG) {
|
||||
*val = AB8500_VERSION_AB8500;
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("%s: return status %d\n", __func__, status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ab8500_reg_count(struct udevice *dev)
|
||||
{
|
||||
return AB8500_NUM_REGISTERS;
|
||||
}
|
||||
|
||||
static int ab8500_read(struct udevice *dev, uint reg, uint8_t *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (len != 1)
|
||||
return -EINVAL;
|
||||
|
||||
*buf = 0;
|
||||
ret = ab8500_transfer(dev, reg, buf, PRCMU_I2C_READ, PRCMU_I2C_RD_OK);
|
||||
if (ret) {
|
||||
printf("%s failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ab8500_write(struct udevice *dev, uint reg, const uint8_t *buf, int len)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (len != 1)
|
||||
return -EINVAL;
|
||||
|
||||
val = *buf;
|
||||
ret = ab8500_transfer(dev, reg, &val, PRCMU_I2C_WRITE, PRCMU_I2C_WR_OK);
|
||||
if (ret) {
|
||||
printf("%s failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops ab8500_ops = {
|
||||
.reg_count = ab8500_reg_count,
|
||||
.read = ab8500_read,
|
||||
.write = ab8500_write,
|
||||
};
|
||||
|
||||
static int ab8500_probe(struct udevice *dev)
|
||||
{
|
||||
struct ab8500_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
/* get regmap from the PRCMU parent device (syscon in U-Boot) */
|
||||
priv->regmap = syscon_get_regmap(dev->parent);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
|
||||
ret = pmic_reg_read(dev, AB8500_MISC_IC_NAME_REG);
|
||||
if (ret < 0) {
|
||||
printf("ab8500: failed to read chip version: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
priv->ab8500.version = ret;
|
||||
|
||||
ret = pmic_reg_read(dev, AB8500_MISC_REV_REG);
|
||||
if (ret < 0) {
|
||||
printf("ab8500: failed to read chip id: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
priv->ab8500.chip_id = ret;
|
||||
|
||||
debug("ab8500: version: %#x, chip id: %#x\n",
|
||||
priv->ab8500.version, priv->ab8500.chip_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id ab8500_ids[] = {
|
||||
{ .compatible = "stericsson,ab8500" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_ab8500) = {
|
||||
.name = "pmic_ab8500",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = ab8500_ids,
|
||||
.bind = dm_scan_fdt_dev,
|
||||
.probe = ab8500_probe,
|
||||
.ops = &ab8500_ops,
|
||||
.priv_auto = sizeof(struct ab8500_priv),
|
||||
};
|
@ -50,6 +50,7 @@ static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
|
||||
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO */
|
||||
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
|
||||
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
|
||||
UNIPHIER_RESETX(24, 0x2008, 2), /* PCIE */
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
@ -79,6 +80,7 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
|
||||
UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */
|
||||
UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */
|
||||
UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */
|
||||
UNIPHIER_RESETX(24, 0x200c, 4), /* PCIE */
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
@ -95,6 +97,7 @@ static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = {
|
||||
UNIPHIER_RESETX(18, 0x200c, 20), /* USB30-PHY2 */
|
||||
UNIPHIER_RESETX(20, 0x200c, 17), /* USB31-PHY0 */
|
||||
UNIPHIER_RESETX(21, 0x200c, 19), /* USB31-PHY1 */
|
||||
UNIPHIER_RESETX(24, 0x200c, 3), /* PCIE */
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
|
@ -67,14 +67,11 @@ static int nomadik_mtu_probe(struct udevice *dev)
|
||||
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
struct nomadik_mtu_priv *priv = dev_get_priv(dev);
|
||||
struct nomadik_mtu_regs *mtu;
|
||||
fdt_addr_t addr;
|
||||
u32 prescale;
|
||||
|
||||
addr = dev_read_addr(dev);
|
||||
if (addr == FDT_ADDR_T_NONE)
|
||||
mtu = dev_read_addr_ptr(dev);
|
||||
if (!mtu)
|
||||
return -EINVAL;
|
||||
|
||||
mtu = (struct nomadik_mtu_regs *)addr;
|
||||
priv->timer = mtu->timers; /* Use first timer */
|
||||
|
||||
if (!uc_priv->clock_rate)
|
||||
|
@ -72,6 +72,15 @@ config USB_MUSB_SUNXI
|
||||
Say y here to enable support for the sunxi OTG / DRC USB controller
|
||||
used on almost all sunxi boards.
|
||||
|
||||
config USB_MUSB_UX500
|
||||
bool "Enable ST-Ericsson Ux500 USB controller"
|
||||
depends on DM_USB && DM_USB_GADGET && ARCH_U8500
|
||||
default y
|
||||
help
|
||||
Say y to enable support for the MUSB OTG USB controller used in
|
||||
ST-Ericsson Ux500. The driver supports either gadget or host mode
|
||||
based on the selection of CONFIG_USB_MUSB_HOST.
|
||||
|
||||
config USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
|
||||
bool "Disable MUSB bulk split/combine"
|
||||
default y
|
||||
@ -85,7 +94,7 @@ endif
|
||||
|
||||
config USB_MUSB_PIO_ONLY
|
||||
bool "Disable DMA (always use PIO)"
|
||||
default y if USB_MUSB_AM35X || USB_MUSB_PIC32 || USB_MUSB_OMAP2PLUS || USB_MUSB_DSPS || USB_MUSB_SUNXI || USB_MUSB_MT85XX
|
||||
default y if USB_MUSB_AM35X || USB_MUSB_PIC32 || USB_MUSB_OMAP2PLUS || USB_MUSB_DSPS || USB_MUSB_SUNXI || USB_MUSB_MT85XX || USB_MUSB_UX500
|
||||
help
|
||||
All data is copied between memory and FIFO by the CPU.
|
||||
DMA controllers are ignored.
|
||||
|
@ -13,6 +13,7 @@ obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o
|
||||
obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o
|
||||
obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
|
||||
obj-$(CONFIG_USB_MUSB_TI) += ti-musb.o
|
||||
obj-$(CONFIG_USB_MUSB_UX500) += ux500.o
|
||||
|
||||
ccflags-y := $(call cc-option,-Wno-unused-variable) \
|
||||
$(call cc-option,-Wno-unused-but-set-variable) \
|
||||
|
@ -1526,7 +1526,7 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
|
||||
defined(CONFIG_ARCH_OMAP4)
|
||||
defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
|
||||
|
||||
static irqreturn_t generic_interrupt(int irq, void *__hci)
|
||||
{
|
||||
|
179
drivers/usb/musb-new/ux500.c
Normal file
179
drivers/usb/musb-new/ux500.c
Normal file
@ -0,0 +1,179 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* Copyright (C) 2019 Stephan Gerhold */
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <generic-phy.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include "musb_uboot.h"
|
||||
|
||||
static struct musb_hdrc_config ux500_musb_hdrc_config = {
|
||||
.multipoint = true,
|
||||
.dyn_fifo = true,
|
||||
.num_eps = 16,
|
||||
.ram_bits = 16,
|
||||
};
|
||||
|
||||
struct ux500_glue {
|
||||
struct musb_host_data mdata;
|
||||
struct device dev;
|
||||
struct phy phy;
|
||||
bool enabled;
|
||||
};
|
||||
#define to_ux500_glue(d) container_of(d, struct ux500_glue, dev)
|
||||
|
||||
static int ux500_musb_enable(struct musb *musb)
|
||||
{
|
||||
struct ux500_glue *glue = to_ux500_glue(musb->controller);
|
||||
int ret;
|
||||
|
||||
if (glue->enabled)
|
||||
return 0;
|
||||
|
||||
ret = generic_phy_power_on(&glue->phy);
|
||||
if (ret) {
|
||||
printf("%s: failed to power on USB PHY\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
glue->enabled = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ux500_musb_disable(struct musb *musb)
|
||||
{
|
||||
struct ux500_glue *glue = to_ux500_glue(musb->controller);
|
||||
int ret;
|
||||
|
||||
if (!glue->enabled)
|
||||
return;
|
||||
|
||||
ret = generic_phy_power_off(&glue->phy);
|
||||
if (ret) {
|
||||
printf("%s: failed to power off USB PHY\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
glue->enabled = false;
|
||||
}
|
||||
|
||||
static int ux500_musb_init(struct musb *musb)
|
||||
{
|
||||
struct ux500_glue *glue = to_ux500_glue(musb->controller);
|
||||
int ret;
|
||||
|
||||
ret = generic_phy_init(&glue->phy);
|
||||
if (ret) {
|
||||
printf("%s: failed to init USB PHY\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ux500_musb_exit(struct musb *musb)
|
||||
{
|
||||
struct ux500_glue *glue = to_ux500_glue(musb->controller);
|
||||
int ret;
|
||||
|
||||
ret = generic_phy_exit(&glue->phy);
|
||||
if (ret) {
|
||||
printf("%s: failed to exit USB PHY\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct musb_platform_ops ux500_musb_ops = {
|
||||
.init = ux500_musb_init,
|
||||
.exit = ux500_musb_exit,
|
||||
.enable = ux500_musb_enable,
|
||||
.disable = ux500_musb_disable,
|
||||
};
|
||||
|
||||
int dm_usb_gadget_handle_interrupts(struct udevice *dev)
|
||||
{
|
||||
struct ux500_glue *glue = dev_get_priv(dev);
|
||||
|
||||
glue->mdata.host->isr(0, glue->mdata.host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ux500_musb_probe(struct udevice *dev)
|
||||
{
|
||||
#ifdef CONFIG_USB_MUSB_HOST
|
||||
struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
|
||||
#endif
|
||||
struct ux500_glue *glue = dev_get_priv(dev);
|
||||
struct musb_host_data *host = &glue->mdata;
|
||||
struct musb_hdrc_platform_data pdata;
|
||||
void *base = dev_read_addr_ptr(dev);
|
||||
int ret;
|
||||
|
||||
if (!base)
|
||||
return -EINVAL;
|
||||
|
||||
ret = generic_phy_get_by_name(dev, "usb", &glue->phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get USB PHY: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&pdata, 0, sizeof(pdata));
|
||||
pdata.platform_ops = &ux500_musb_ops;
|
||||
pdata.config = &ux500_musb_hdrc_config;
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_HOST
|
||||
priv->desc_before_addr = true;
|
||||
pdata.mode = MUSB_HOST;
|
||||
|
||||
host->host = musb_init_controller(&pdata, &glue->dev, base);
|
||||
if (!host->host)
|
||||
return -EIO;
|
||||
|
||||
return musb_lowlevel_init(host);
|
||||
#else
|
||||
pdata.mode = MUSB_PERIPHERAL;
|
||||
host->host = musb_init_controller(&pdata, &glue->dev, base);
|
||||
if (!host->host)
|
||||
return -EIO;
|
||||
|
||||
return usb_add_gadget_udc(&glue->dev, &host->host->g);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ux500_musb_remove(struct udevice *dev)
|
||||
{
|
||||
struct ux500_glue *glue = dev_get_priv(dev);
|
||||
struct musb_host_data *host = &glue->mdata;
|
||||
|
||||
usb_del_gadget_udc(&host->host->g);
|
||||
musb_stop(host->host);
|
||||
free(host->host);
|
||||
host->host = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id ux500_musb_ids[] = {
|
||||
{ .compatible = "stericsson,db8500-musb" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(ux500_musb) = {
|
||||
.name = "ux500-musb",
|
||||
#ifdef CONFIG_USB_MUSB_HOST
|
||||
.id = UCLASS_USB,
|
||||
#else
|
||||
.id = UCLASS_USB_GADGET_GENERIC,
|
||||
#endif
|
||||
.of_match = ux500_musb_ids,
|
||||
.probe = ux500_musb_probe,
|
||||
.remove = ux500_musb_remove,
|
||||
#ifdef CONFIG_USB_MUSB_HOST
|
||||
.ops = &musb_usb_ops,
|
||||
#endif
|
||||
.plat_auto = sizeof(struct usb_plat),
|
||||
.priv_auto = sizeof(struct ux500_glue),
|
||||
};
|
@ -7,23 +7,23 @@
|
||||
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#define CONFIG_SKIP_LOWLEVEL_INIT /* Loaded by another bootloader */
|
||||
#define CONFIG_SYS_MALLOC_LEN SZ_2M
|
||||
/*
|
||||
* The "stemmy" U-Boot port is designed to be chainloaded by the Samsung
|
||||
* bootloader on devices based on ST-Ericsson Ux500. Therefore, we skip most
|
||||
* low-level initialization and rely on configuration provided by the Samsung
|
||||
* bootloader. New images are loaded at the same address for compatibility.
|
||||
*/
|
||||
#define CONFIG_SKIP_LOWLEVEL_INIT
|
||||
#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_TEXT_BASE
|
||||
#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_TEXT_BASE
|
||||
|
||||
/* Physical Memory Map */
|
||||
#define PHYS_SDRAM_1 0x00000000 /* DDR-SDRAM Bank #1 */
|
||||
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
|
||||
#define CONFIG_SYS_SDRAM_SIZE SZ_1G
|
||||
#define CONFIG_SYS_INIT_RAM_SIZE 0x00100000
|
||||
#define CONFIG_SYS_GBL_DATA_OFFSET (CONFIG_SYS_SDRAM_BASE + \
|
||||
CONFIG_SYS_INIT_RAM_SIZE - \
|
||||
GENERATED_GBL_DATA_SIZE)
|
||||
#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_GBL_DATA_OFFSET
|
||||
#define CONFIG_SYS_MALLOC_LEN SZ_2M
|
||||
|
||||
/* FIXME: This should be loaded from device tree... */
|
||||
#define CONFIG_SYS_L2_PL310
|
||||
#define CONFIG_SYS_PL310_BASE 0xa0412000
|
||||
|
||||
#define CONFIG_SYS_LOAD_ADDR 0x00100000
|
||||
/* Generate initrd atag for downstream kernel (others are copied in stemmy.c) */
|
||||
#define CONFIG_INITRD_TAG
|
||||
|
||||
#endif
|
||||
|
@ -210,4 +210,6 @@
|
||||
|
||||
#define CONFIG_SPL_PAD_TO 0x20000
|
||||
|
||||
#define CONFIG_SYS_PCI_64BIT
|
||||
|
||||
#endif /* __CONFIG_UNIPHIER_H__ */
|
||||
|
125
include/power/ab8500.h
Normal file
125
include/power/ab8500.h
Normal file
@ -0,0 +1,125 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Based on include/linux/mfd/abx500/ab8500.h from Linux
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
|
||||
*/
|
||||
|
||||
#ifndef _PMIC_AB8500_H_
|
||||
#define _PMIC_AB8500_H_
|
||||
|
||||
/*
|
||||
* AB IC versions
|
||||
*
|
||||
* AB8500_VERSION_AB8500 should be 0xFF but will never be read as need a
|
||||
* non-supported multi-byte I2C access via PRCMU. Set to 0x00 to ease the
|
||||
* print of version string.
|
||||
*/
|
||||
enum ab8500_version {
|
||||
AB8500_VERSION_AB8500 = 0x0,
|
||||
AB8500_VERSION_AB8505 = 0x1,
|
||||
AB8500_VERSION_AB9540 = 0x2,
|
||||
AB8500_VERSION_AB8540 = 0x4,
|
||||
AB8500_VERSION_UNDEFINED,
|
||||
};
|
||||
|
||||
/* AB8500 CIDs*/
|
||||
#define AB8500_CUTEARLY 0x00
|
||||
#define AB8500_CUT1P0 0x10
|
||||
#define AB8500_CUT1P1 0x11
|
||||
#define AB8500_CUT1P2 0x12 /* Only valid for AB8540 */
|
||||
#define AB8500_CUT2P0 0x20
|
||||
#define AB8500_CUT3P0 0x30
|
||||
#define AB8500_CUT3P3 0x33
|
||||
|
||||
/*
|
||||
* AB8500 bank addresses
|
||||
*/
|
||||
#define AB8500_BANK(bank, reg) (((bank) << 8) | (reg))
|
||||
#define AB8500_M_FSM_RANK(reg) AB8500_BANK(0x0, reg)
|
||||
#define AB8500_SYS_CTRL1_BLOCK(reg) AB8500_BANK(0x1, reg)
|
||||
#define AB8500_SYS_CTRL2_BLOCK(reg) AB8500_BANK(0x2, reg)
|
||||
#define AB8500_REGU_CTRL1(reg) AB8500_BANK(0x3, reg)
|
||||
#define AB8500_REGU_CTRL2(reg) AB8500_BANK(0x4, reg)
|
||||
#define AB8500_USB(reg) AB8500_BANK(0x5, reg)
|
||||
#define AB8500_TVOUT(reg) AB8500_BANK(0x6, reg)
|
||||
#define AB8500_DBI(reg) AB8500_BANK(0x7, reg)
|
||||
#define AB8500_ECI_AV_ACC(reg) AB8500_BANK(0x8, reg)
|
||||
#define AB8500_RESERVED(reg) AB8500_BANK(0x9, reg)
|
||||
#define AB8500_GPADC(reg) AB8500_BANK(0xA, reg)
|
||||
#define AB8500_CHARGER(reg) AB8500_BANK(0xB, reg)
|
||||
#define AB8500_GAS_GAUGE(reg) AB8500_BANK(0xC, reg)
|
||||
#define AB8500_AUDIO(reg) AB8500_BANK(0xD, reg)
|
||||
#define AB8500_INTERRUPT(reg) AB8500_BANK(0xE, reg)
|
||||
#define AB8500_RTC(reg) AB8500_BANK(0xF, reg)
|
||||
#define AB8500_GPIO(reg) AB8500_BANK(0x10, reg)
|
||||
#define AB8500_MISC(reg) AB8500_BANK(0x10, reg)
|
||||
#define AB8500_DEVELOPMENT(reg) AB8500_BANK(0x11, reg)
|
||||
#define AB8500_DEBUG(reg) AB8500_BANK(0x12, reg)
|
||||
#define AB8500_PROD_TEST(reg) AB8500_BANK(0x13, reg)
|
||||
#define AB8500_STE_TEST(reg) AB8500_BANK(0x14, reg)
|
||||
#define AB8500_OTP_EMUL(reg) AB8500_BANK(0x15, reg)
|
||||
|
||||
#define AB8500_NUM_BANKS 0x16
|
||||
#define AB8500_NUM_REGISTERS AB8500_BANK(AB8500_NUM_BANKS, 0)
|
||||
|
||||
struct ab8500 {
|
||||
enum ab8500_version version;
|
||||
u8 chip_id;
|
||||
};
|
||||
|
||||
static inline int is_ab8500(struct ab8500 *ab)
|
||||
{
|
||||
return ab->version == AB8500_VERSION_AB8500;
|
||||
}
|
||||
|
||||
static inline int is_ab8505(struct ab8500 *ab)
|
||||
{
|
||||
return ab->version == AB8500_VERSION_AB8505;
|
||||
}
|
||||
|
||||
/* exclude also ab8505, ab9540... */
|
||||
static inline int is_ab8500_1p0_or_earlier(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P0));
|
||||
}
|
||||
|
||||
/* exclude also ab8505, ab9540... */
|
||||
static inline int is_ab8500_1p1_or_earlier(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P1));
|
||||
}
|
||||
|
||||
/* exclude also ab8505, ab9540... */
|
||||
static inline int is_ab8500_2p0_or_earlier(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT2P0));
|
||||
}
|
||||
|
||||
static inline int is_ab8500_3p3_or_earlier(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT3P3));
|
||||
}
|
||||
|
||||
/* exclude also ab8505, ab9540... */
|
||||
static inline int is_ab8500_2p0(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
|
||||
}
|
||||
|
||||
static inline int is_ab8505_1p0_or_earlier(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8505(ab) && (ab->chip_id <= AB8500_CUT1P0));
|
||||
}
|
||||
|
||||
static inline int is_ab8505_2p0(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8505(ab) && (ab->chip_id == AB8500_CUT2P0));
|
||||
}
|
||||
|
||||
static inline int is_ab8505_2p0_earlier(struct ab8500 *ab)
|
||||
{
|
||||
return (is_ab8505(ab) && (ab->chip_id < AB8500_CUT2P0));
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user