- Assorted updates
This commit is contained in:
Tom Rini
2025-12-02 12:19:52 -06:00
35 changed files with 2089 additions and 64 deletions

View File

@@ -2,7 +2,7 @@ if ARCH_EXYNOS
config BOARD_COMMON
def_bool y
depends on !TARGET_SMDKV310 && !TARGET_ARNDALE && !TARGET_E850_96
depends on !TARGET_SMDKV310 && !TARGET_ARNDALE && !TARGET_EXYNOS_MOBILE && !TARGET_E850_96
config SPI_BOOTING
bool
@@ -252,6 +252,14 @@ config TARGET_E850_96
endchoice
endif
config TARGET_EXYNOS_MOBILE
bool "Samsung Exynos Generic Boards (for mobile devices)"
select ARM64
select BOARD_EARLY_INIT_F
select CLK_EXYNOS
select LINUX_KERNEL_IMAGE_HEADER
select OF_CONTROL
config SYS_SOC
default "exynos"
@@ -277,5 +285,6 @@ source "board/samsung/smdk5420/Kconfig"
source "board/samsung/espresso7420/Kconfig"
source "board/samsung/axy17lte/Kconfig"
source "board/samsung/e850-96/Kconfig"
source "board/samsung/exynos-mobile/Kconfig"
endif

View File

@@ -3,4 +3,4 @@
# Copyright (C) 2024, Linaro Limited
# Sam Protsenko <semen.protsenko@linaro.org>
obj-y := e850-96.o fw.o acpm.o pmic.o
obj-y := e850-96.o fw.o acpm.o pmic.o bootdev.o

View File

@@ -0,0 +1,99 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2025 Linaro Ltd.
* Author: Sam Protsenko <semen.protsenko@linaro.org>
*
* Routines for checking current boot device.
*/
#include <linux/arm-smccc.h>
#include <vsprintf.h>
#include "bootdev.h"
/* Flag from BL2 bootloader in RAM */
#define BL2_TAG_ADDR 0x80000000 /* DRAM base */
#define BL2_TAG 0xabcdef
/* Boot device info location in iRAM (only accessible from EL3) */
#define IRAM_BASE 0x02020000
#define BOOTDEVICE_INFO_ADDR (IRAM_BASE + 0x64)
/* SMC call for getting boot device information from EL3 monitor */
#define SMC_CMD_CHECK_SECOND_BOOT -233
/* Boot device constants for the encoded boot device info value */
#define BD_NO_DEVICE 0x0
#define BD_UFS 0x1
#define BD_EMMC 0x2
#define BD_ERROR 0x3
#define BD_USB 0x4
#define BD_SDMMC 0x5
#define BD_UFS_CARD 0x6
#define BD_SPI 0x7
/* If BL2 bootloader wasn't executed, it means U-Boot is running via JTAG */
static bool bootdev_is_jtag_session(void)
{
u32 bl2_tag_val = *(u32 *)BL2_TAG_ADDR;
return bl2_tag_val != BL2_TAG;
}
/* Obtain boot device information encoded in 32-bit value */
static u32 bootdev_get_info(void)
{
u32 info;
/*
* On regular boot U-Boot is executed by BL2 bootloader, and is running
* in EL1 mode, so the boot device information has to be obtained via
* SMC call from EL3 software (EL3 monitor), which can read that info
* from the protected iRAM memory. If U-Boot is running via TRACE32 JTAG
* (in EL3 mode), read the boot device info directly from iRAM, as EL3
* software might not be available.
*/
if (bootdev_is_jtag_session()) {
info = *(u32 *)BOOTDEVICE_INFO_ADDR;
} else {
struct arm_smccc_res res;
arm_smccc_smc(SMC_CMD_CHECK_SECOND_BOOT, 0, 0, 0, 0, 0, 0, 0,
&res);
info = (u32)res.a2;
}
return info;
}
enum bootdev bootdev_get_current(void)
{
u32 info, magic, order, dev;
info = bootdev_get_info();
magic = info >> 24;
order = info & 0xf;
dev = (info >> (4 * order)) & 0xf;
if (magic != 0xcb)
panic("Abnormal boot");
switch (dev) {
case BD_UFS:
return BOOTDEV_UFS;
case BD_EMMC:
return BOOTDEV_EMMC;
case BD_USB:
return BOOTDEV_USB;
case BD_SDMMC:
return BOOTDEV_SD;
default:
return BOOTDEV_ERROR;
}
return BOOTDEV_ERROR;
}
bool bootdev_is_usb(void)
{
return bootdev_get_current() == BOOTDEV_USB;
}

View File

@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2025 Linaro Ltd.
* Sam Protsenko <semen.protsenko@linaro.org>
*/
#ifndef __E850_96_BOOTDEV_H
#define __E850_96_BOOTDEV_H
#include <stdbool.h>
enum bootdev {
BOOTDEV_ERROR,
BOOTDEV_SD,
BOOTDEV_EMMC,
BOOTDEV_USB,
BOOTDEV_UFS,
};
enum bootdev bootdev_get_current(void);
bool bootdev_is_usb(void);
#endif /* __E850_96_BOOTDEV_H */

View File

@@ -11,6 +11,7 @@
#include <net.h>
#include <usb.h>
#include <asm/io.h>
#include "bootdev.h"
#include "fw.h"
#include "pmic.h"
@@ -31,6 +32,10 @@
#define EMMC_DEV_NUM 0
#define EMMC_ESP_PART 1
/* Firmware size */
#define LDFW_MAX_SIZE SZ_4M
#define SP_MAX_SIZE SZ_1M
struct efi_fw_image fw_images[] = {
{
.image_type_id = E850_96_FWBL1_IMAGE_GUID,
@@ -77,16 +82,6 @@ static struct acpm acpm = {
.ipc_ch = EXYNOS850_IPC_AP_I3C,
};
int dram_init(void)
{
return fdtdec_setup_mem_size_base();
}
int dram_init_banksize(void)
{
return fdtdec_setup_memory_banksize();
}
/* Read the unique SoC ID from OTP registers */
static u64 get_chip_id(void)
{
@@ -137,11 +132,34 @@ static void setup_ethaddr(void)
eth_env_set_enetaddr("ethaddr", mac_addr);
}
static void load_firmware_usb(void)
{
int err;
printf("Loading LDFW firmware (over USB)...\n");
err = load_image_usb(USB_DN_IMAGE_LDFW, LDFW_NWD_ADDR, LDFW_MAX_SIZE);
if (err) {
printf("ERROR: LDFW loading failed (%d)\n", err);
return;
}
err = init_ldfw(LDFW_NWD_ADDR);
if (err) {
printf("ERROR: LDFW init failed (%d)\n", err);
/* Do not return, still need to download SP */
}
printf("Loading SP firmware (over USB)...\n");
err = load_image_usb(USB_DN_IMAGE_SP, LDFW_NWD_ADDR, SP_MAX_SIZE);
if (err)
printf("ERROR: SP loading failed (%d)\n", err);
}
/*
* Call this in board_late_init() to avoid probing block devices before
* efi_init_early().
*/
void load_firmware(void)
static void load_firmware_blk(void)
{
const char *ifname;
ulong dev, part;
@@ -161,16 +179,41 @@ void load_firmware(void)
}
printf("Loading LDFW firmware (from %s %ld)...\n", ifname, dev);
err = load_ldfw(ifname, dev, part, LDFW_NWD_ADDR);
if (err)
err = load_ldfw_from_blk(ifname, dev, part, LDFW_NWD_ADDR);
if (err) {
printf("ERROR: LDFW loading failed (%d)\n", err);
return;
}
err = init_ldfw(LDFW_NWD_ADDR);
if (err)
printf("ERROR: LDFW init failed (%d)\n", err);
}
int dram_init(void)
{
return fdtdec_setup_mem_size_base();
}
int dram_init_banksize(void)
{
return fdtdec_setup_memory_banksize();
}
int board_late_init(void)
{
setup_serial();
setup_ethaddr();
load_firmware();
if (bootdev_is_usb())
load_firmware_usb();
else
load_firmware_blk();
if (bootdev_is_usb()) {
env_set("bootcmd", "echo \"Entering DFU mode...\"; "
"dfu 0 mmc 0");
env_set("bootdelay", "0");
}
return 0;
}

View File

@@ -11,14 +11,19 @@
#include <linux/arm-smccc.h>
#include "fw.h"
#define LDFW_RAW_PART "ldfw"
#define LDFW_FAT_PATH "/EFI/firmware/ldfw.bin"
#define LDFW_RAW_PART "ldfw"
#define LDFW_FAT_PATH "/EFI/firmware/ldfw.bin"
#define LDFW_MAGIC 0x10adab1e
#define LDFW_MAGIC 0x10adab1e
#define SMC_CMD_LOAD_LDFW -0x500
#define SDM_HW_RESET_STATUS 0x1230
#define SDM_SW_RESET_STATUS 0x1231
#define SB_ERROR_PREFIX 0xfdaa0000
/* SMC command for providing LDFW to EL3 monitor */
#define SMC_CMD_LOAD_LDFW -0x500
/* SMC command for loading some binary over USB */
#define SMC_CMD_LOAD_IMAGE_BY_USB -0x512
/* Error codes for SMC_CMD_LOAD_LDFW */
#define SDM_HW_RESET_STATUS 0x1230
#define SDM_SW_RESET_STATUS 0x1231
#define SB_ERROR_PREFIX 0xfdaa0000
struct ldfw_header {
u32 magic;
@@ -94,7 +99,27 @@ static int read_fw_from_raw(const char *ifname, int dev, const char *part_name,
}
/**
* load_ldfw - Load the loadable firmware (LDFW)
* load_image_usb - Load some binary over USB during USB boot
* @type: Image type
* @addr: Memory address where the image should be downloaded to
* @size: Image size
*
* Return: 0 on success or a negative value on error.
*/
int load_image_usb(enum usb_dn_image type, phys_addr_t addr, phys_size_t size)
{
struct arm_smccc_res res;
arm_smccc_smc(SMC_CMD_LOAD_IMAGE_BY_USB, (u64)type, addr, size,
0, 0, 0, 0, &res);
if (res.a0)
return -EIO;
return 0;
}
/**
* load_ldfw_from_blk - Load the loadable firmware (LDFW) from block device
* @ifname: Interface name of the block device to load the firmware from
* @dev: Device number
* @part: Partition number
@@ -102,24 +127,37 @@ static int read_fw_from_raw(const char *ifname, int dev, const char *part_name,
*
* Return: 0 on success or a negative value on error.
*/
int load_ldfw(const char *ifname, int dev, int part, phys_addr_t addr)
int load_ldfw_from_blk(const char *ifname, int dev, int part, phys_addr_t addr)
{
struct ldfw_header *hdr;
struct arm_smccc_res res;
void *buf = (void *)addr;
u64 size = 0;
int err, i;
int err;
/* First try to read LDFW from EFI partition, then from the raw one */
err = read_fw_from_fat(ifname, dev, part, LDFW_FAT_PATH, buf);
if (err) {
err = read_fw_from_raw(ifname, dev, LDFW_RAW_PART, buf);
if (err)
return err;
}
if (err)
return read_fw_from_raw(ifname, dev, LDFW_RAW_PART, buf);
return 0;
}
/**
* init_ldfw - Provide the LDFW (loaded to RAM) to EL3 monitor to make use of it
* @addr: Memory address where LDFW resides
*
* EL3 monitor will copy the LDFW from the provided Normal World memory @addr to
* Secure World location, and start using it.
*
* Return: 0 on success or a negative value on error.
*/
int init_ldfw(phys_addr_t addr)
{
struct ldfw_header *hdr;
struct arm_smccc_res res;
u64 size = 0;
int err, i;
/* Validate LDFW by magic number in its header */
hdr = buf;
hdr = (struct ldfw_header *)addr;
if (hdr->magic != LDFW_MAGIC) {
debug("%s: Wrong LDFW magic; is LDFW flashed?\n", __func__);
return -EINVAL;

View File

@@ -9,6 +9,14 @@
#include <asm/types.h>
int load_ldfw(const char *ifname, int dev, int part, phys_addr_t addr);
/* Image types for downloading over USB */
enum usb_dn_image {
USB_DN_IMAGE_LDFW = 1, /* Loadable Firmware */
USB_DN_IMAGE_SP = 2, /* Secure Payload (tzsw.img) */
};
int load_image_usb(enum usb_dn_image type, phys_addr_t addr, phys_size_t size);
int load_ldfw_from_blk(const char *ifname, int dev, int part, phys_addr_t addr);
int init_ldfw(phys_addr_t addr);
#endif /* __E850_96_FW_H */

View File

@@ -0,0 +1,18 @@
if TARGET_EXYNOS_MOBILE
config ENV_SOURCE_FILE
default "exynos-mobile"
config LNX_KRNL_IMG_TEXT_OFFSET_BASE
default TEXT_BASE
config SYS_BOARD
default "exynos-mobile"
config SYS_CONFIG_NAME
default "exynos-mobile"
config SYS_VENDOR
default "samsung"
endif # TARGET_EXYNOS_MOBILE

View File

@@ -0,0 +1,6 @@
Exynos Generic Boards (for mobile devices)
M: Kaustabh Chakraborty <kauschluss@disroot.org>
S: Maintained
F: board/samsung/exynos-mobile/
F: configs/exynos-mobile_defconfig
F: include/configs/exynos-mobile.h

View File

@@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) 2025 Kaustabh Chakraborty <kauschluss@disroot.org>
obj-y := exynos-mobile.o

View File

@@ -0,0 +1,7 @@
CONFIG_DEBUG_UART=y
CONFIG_DEBUG_UART_BASE=0x13820000
CONFIG_DEBUG_UART_CLOCK=133250000
CONFIG_DEBUG_UART_S5P=y
CONFIG_LOG=y
CONFIG_LOG_CONSOLE=y
CONFIG_LOG_MAX_LEVEL=8

View File

@@ -0,0 +1,403 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Samsung Exynos Generic Board Source (for mobile devices)
*
* Copyright (c) 2025 Kaustabh Chakraborty <kauschluss@disroot.org>
*/
#include <asm/armv8/mmu.h>
#include <blk.h>
#include <bootflow.h>
#include <ctype.h>
#include <dm/ofnode.h>
#include <env.h>
#include <errno.h>
#include <init.h>
#include <limits.h>
#include <linux/sizes.h>
#include <lmb.h>
#include <part.h>
#include <stdbool.h>
DECLARE_GLOBAL_DATA_PTR;
#define lmb_alloc(size, addr) \
lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
struct exynos_board_info {
const char *name;
const char *chip;
const u64 *const dram_bank_bases;
char serial[64];
int (*const match)(struct exynos_board_info *);
const char *match_model;
const u8 match_max_rev;
};
/*
* The memory mapping includes all DRAM banks, along with the
* peripheral block, and a sentinel at the end. This is filled in
* dynamically.
*/
static struct mm_region exynos_mem_map[CONFIG_NR_DRAM_BANKS + 2] = {
{
/* Peripheral MMIO block */
.virt = 0x10000000UL,
.phys = 0x10000000UL,
.size = 0x10000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN,
},
};
struct mm_region *mem_map = exynos_mem_map;
static const u64 exynos7870_common_dram_bank_bases[CONFIG_NR_DRAM_BANKS] = {
0x40000000, 0x80000000, 0x100000000,
};
static const char *exynos_prev_bl_get_bootargs(void)
{
void *prev_bl_fdt_base = (void *)get_prev_bl_fdt_addr();
int chosen_node_offset, ret;
const struct fdt_property *bootargs_prop;
ret = fdt_check_header(prev_bl_fdt_base);
if (ret < 0) {
log_err("%s: FDT is invalid (FDT_ERR %d)\n", __func__, ret);
return NULL;
}
ret = fdt_path_offset(prev_bl_fdt_base, "/chosen");
chosen_node_offset = ret;
if (ret < 0) {
log_err("%s: /chosen node not found (FDT_ERR %d)\n", __func__,
ret);
return NULL;
}
bootargs_prop = fdt_get_property(prev_bl_fdt_base, chosen_node_offset,
"bootargs", &ret);
if (!bootargs_prop) {
log_err("%s: /chosen/bootargs property not found (FDT_ERR %d)\n",
__func__, ret);
return NULL;
}
return bootargs_prop->data;
}
static int exynos7870_fdt_match(struct exynos_board_info *board_info)
{
const char *prev_bl_bootargs;
int val, ret;
prev_bl_bootargs = exynos_prev_bl_get_bootargs();
if (!prev_bl_bootargs)
return -1;
/*
* Read the cmdline property which stores the
* bootloader/firmware version. An example value of the option
* can be: "J600GDXU3ARH5". This can be used to verify the model
* of the device.
*/
ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.bootloader", &val);
if (ret < 0) {
log_err("%s: unable to find property for bootloader version (%d)\n",
__func__, ret);
return -1;
}
if (strncmp(prev_bl_bootargs + val, board_info->match_model,
strlen(board_info->match_model)))
return -1;
/*
* Read the cmdline property which stores the hardware revision.
* This is required to allow selecting one of multiple dtbs
* available of a single device, varying in hardware changes in
* different revisions.
*/
ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.revision", &val);
if (ret < 0)
ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.hw_rev", &val);
if (ret < 0) {
log_err("%s: unable to find property for bootloader revision (%d)\n",
__func__, ret);
return -1;
}
if (strtoul(prev_bl_bootargs + val, NULL, 10) > board_info->match_max_rev)
return -1;
/*
* Read the cmdline property which stores the serial number.
* Store this in the board info struct.
*/
ret = cmdline_get_arg(prev_bl_bootargs, "androidboot.serialno", &val);
if (ret > 0)
strlcpy(board_info->serial, prev_bl_bootargs + val, ret);
return 0;
}
/*
* This array is used for matching the models and revisions with the
* devicetree used by U-Boot. This allows a single U-Boot to work on
* multiple devices.
*
* Entries are kept in lexicographical order of board SoCs, followed by
* board names.
*/
static struct exynos_board_info exynos_board_info_match[] = {
{
/* Samsung Galaxy A2 Core */
.name = "a2corelte",
.chip = "exynos7870",
.dram_bank_bases = exynos7870_common_dram_bank_bases,
.match = exynos7870_fdt_match,
.match_model = "A260",
.match_max_rev = U8_MAX,
}, {
/* Samsung Galaxy J6 */
.name = "j6lte",
.chip = "exynos7870",
.dram_bank_bases = exynos7870_common_dram_bank_bases,
.match = exynos7870_fdt_match,
.match_model = "J600",
.match_max_rev = U8_MAX,
}, {
/* Samsung Galaxy J7 Prime */
.name = "on7xelte",
.chip = "exynos7870",
.dram_bank_bases = exynos7870_common_dram_bank_bases,
.match = exynos7870_fdt_match,
.match_model = "G610",
.match_max_rev = U8_MAX,
},
};
static void exynos_parse_dram_banks(const struct exynos_board_info *board_info,
const void *fdt_base)
{
u64 mem_addr, mem_size = 0;
u32 na, ns, i, j;
int offset;
if (fdt_check_header(fdt_base) < 0)
return;
/* #address-cells and #size-cells as defined in the fdt root. */
na = fdt_address_cells(fdt_base, 0);
ns = fdt_size_cells(fdt_base, 0);
fdt_for_each_subnode(offset, fdt_base, 0) {
if (strncmp(fdt_get_name(fdt_base, offset, NULL), "memory", 6))
continue;
for (i = 0; ; i++) {
mem_addr = fdtdec_get_addr_size_fixed(fdt_base, offset,
"reg", i, na, ns,
&mem_size, false);
if (mem_addr == FDT_ADDR_T_NONE)
break;
if (!mem_size)
continue;
for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) {
if (board_info->dram_bank_bases[j] != mem_addr)
continue;
mem_map[j + 1].phys = mem_addr;
mem_map[j + 1].virt = mem_addr;
mem_map[j + 1].size = mem_size;
mem_map[j + 1].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE;
break;
}
}
}
}
static int exynos_fastboot_setup(void)
{
struct blk_desc *blk_dev;
struct disk_partition info = {0};
char buf[128];
phys_addr_t addr;
int offset, i, j;
/* Allocate and define buffer address for fastboot interface. */
if (lmb_alloc(CONFIG_FASTBOOT_BUF_SIZE, &addr)) {
log_err("%s: failed to allocate fastboot buffer\n", __func__);
return -ENOMEM;
}
env_set_hex("fastboot_addr_r", addr);
blk_dev = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!blk_dev) {
log_err("%s: required mmc device not available\n", __func__);
return -ENODEV;
}
strcpy(buf, "fastboot_partition_alias_");
offset = strlen(buf);
for (i = 1; i < CONFIG_EFI_PARTITION_ENTRIES_NUMBERS; i++) {
if (part_get_info(blk_dev, i, &info))
continue;
/*
* The partition name must be lowercase (stored in buf[]),
* as is expected in all fastboot partitions ...
*/
strlcpy(buf + offset, info.name, sizeof(buf) - offset);
for (j = offset; buf[j]; j++)
buf[j] = tolower(buf[j]);
if (!strcmp(buf + offset, info.name))
continue;
/*
* ... However, if that isn't the case, a fastboot
* partition alias must be defined to establish it.
*/
env_set(buf, info.name);
}
return 0;
}
int board_fit_config_name_match(const char *name)
{
struct exynos_board_info *board_info;
char buf[128];
unsigned int i;
int ret;
/*
* Iterate over exynos_board_info_match[] to select the
* appropriate board info struct. If not found, exit.
*/
for (i = 0; i < ARRAY_SIZE(exynos_board_info_match); i++) {
board_info = exynos_board_info_match + i;
snprintf(buf, sizeof(buf), "%s-%s", board_info->chip,
board_info->name);
if (!strcmp(name, buf))
break;
}
if (i == ARRAY_SIZE(exynos_board_info_match))
return -1;
/*
* Execute match logic for the target board. This is separated
* as the process may be different for multiple boards.
*/
ret = board_info->match(board_info);
if (ret)
return ret;
/*
* Store the correct board info struct in gd->board_type to
* allow other functions to access it.
*/
gd->board_type = (ulong)board_info;
log_debug("%s: device detected: %s\n", __func__, name);
return 0;
}
int timer_init(void)
{
ofnode timer_node;
/*
* In a lot of Exynos devices, the previous bootloader does not
* set CNTFRQ_EL0 properly. However, the timer node in
* devicetree has the correct frequency, use that instead.
*/
timer_node = ofnode_by_compatible(ofnode_null(), "arm,armv8-timer");
gd->arch.timer_rate_hz = ofnode_read_u32_default(timer_node,
"clock-frequency", 0);
return 0;
}
int board_early_init_f(void)
{
const struct exynos_board_info *board_info;
if (!gd->board_type)
return -ENODATA;
board_info = (const struct exynos_board_info *)gd->board_type;
exynos_parse_dram_banks(board_info, gd->fdt_blob);
/*
* Some devices have multiple variants based on the amount of
* memory and internal storage. The lowest bank base has been
* observed to have the same memory range in all board variants.
* For variants with more memory, the previous bootloader should
* overlay the devicetree with the required extra memory ranges.
*/
exynos_parse_dram_banks(board_info, (const void *)get_prev_bl_fdt_addr());
return 0;
}
int dram_init(void)
{
unsigned int i;
/* Select the largest RAM bank for U-Boot. */
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
if (gd->ram_size < mem_map[i + 1].size) {
gd->ram_base = mem_map[i + 1].phys;
gd->ram_size = mem_map[i + 1].size;
}
}
return 0;
}
int dram_init_banksize(void)
{
unsigned int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = mem_map[i + 1].phys;
gd->bd->bi_dram[i].size = mem_map[i + 1].size;
}
return 0;
}
int board_init(void)
{
return 0;
}
int misc_init_r(void)
{
const struct exynos_board_info *board_info;
char buf[128];
if (!gd->board_type)
return -ENODATA;
board_info = (const struct exynos_board_info *)gd->board_type;
env_set("platform", board_info->chip);
env_set("board", board_info->name);
if (strlen(board_info->serial))
env_set("serial#", board_info->serial);
/* EFI booting requires the path to correct dtb, specify it here. */
snprintf(buf, sizeof(buf), "exynos/%s-%s.dtb", board_info->chip,
board_info->name);
env_set("fdtfile", buf);
return exynos_fastboot_setup();
}

View File

@@ -0,0 +1,18 @@
stdin=serial,button-kbd
stdout=serial,vidconsole
stderr=serial,vidconsole
bootdelay=0
bootcmd=bootefi bootmgr; pause; bootmenu
fastbootcmd=echo "Fastboot Mode";
fastboot -l $fastboot_addr_r usb 0
bootmenu_0=Continue Boot=boot
bootmenu_1=Enter Fastboot Mode=run fastbootcmd
bootmenu_2=UEFI Maintenance Menu=eficonfig
bootmenu_3=Reboot=reset
bootmenu_4=Power Off=poweroff
button_cmd_0_name=Volume Down Key
button_cmd_0=bootmenu

View File

@@ -0,0 +1,72 @@
CONFIG_ARM=y
CONFIG_SKIP_LOWLEVEL_INIT=y
CONFIG_COUNTER_FREQUENCY=26000000
CONFIG_POSITION_INDEPENDENT=y
CONFIG_ARCH_EXYNOS=y
CONFIG_SYS_MALLOC_LEN=0x2000000
CONFIG_SYS_MALLOC_F_LEN=0x16000
CONFIG_TARGET_EXYNOS_MOBILE=y
CONFIG_NR_DRAM_BANKS=3
CONFIG_DEFAULT_DEVICE_TREE="exynos/exynos7870-a2corelte"
CONFIG_SYS_BOOTM_LEN=0x2000000
CONFIG_SYS_LOAD_ADDR=0x80000000
CONFIG_ARMV8_CNTFRQ_BROKEN=y
# CONFIG_PSCI_RESET is not set
CONFIG_BUTTON_CMD=y
CONFIG_SAVE_PREV_BL_FDT_ADDR=y
CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y
CONFIG_SYS_PBSIZE=1024
CONFIG_BOARD_TYPES=y
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_MISC_INIT_R=y
CONFIG_HUSH_PARSER=y
CONFIG_CMD_BOOTMENU=y
CONFIG_CMD_POWEROFF=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_EFI_PARTITION=y
CONFIG_OF_UPSTREAM=y
CONFIG_OF_LIST="exynos/exynos7870-a2corelte exynos/exynos7870-j6lte exynos/exynos7870-on7xelte"
CONFIG_MULTI_DTB_FIT=y
CONFIG_BUTTON=y
CONFIG_BUTTON_REMAP_PHONE_KEYS=y
CONFIG_CLK=y
CONFIG_CLK_CCF=y
CONFIG_CLK_EXYNOS7870=y
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_BUF_ADDR=0xdead0000
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
CONFIG_SYS_I2C_S3C24X0=y
CONFIG_BUTTON_KEYBOARD=y
CONFIG_MISC=y
CONFIG_MMC_BROKEN_CD=y
CONFIG_MMC_IO_VOLTAGE=y
CONFIG_MMC_UHS_SUPPORT=y
CONFIG_MMC_HS400_SUPPORT=y
CONFIG_MMC_DW=y
CONFIG_PHY=y
CONFIG_PHY_EXYNOS_USBDRD=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_EXYNOS78x0=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_S2MPS11=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_REGULATOR_S2MPS11=y
CONFIG_SOC_SAMSUNG=y
CONFIG_EXYNOS_PMU=y
CONFIG_SYSRESET=y
CONFIG_SYSRESET_CMD_POWEROFF=y
CONFIG_SYSRESET_SYSCON=y
CONFIG_USB=y
CONFIG_DM_USB_GADGET=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Samsung"
CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
CONFIG_USB_GADGET_PRODUCT_NUM=0x6602
CONFIG_VIDEO=y
CONFIG_VIDEO_SIMPLE=y
CONFIG_FS_EXT4=y
CONFIG_FS_FAT=y

View File

@@ -0,0 +1,45 @@
.. SPDX-License-Identifier: GPL-2.0+
.. sectionauthor:: Kaustabh Chakraborty <kauschluss@disroot.org>
Samsung Exynos Generic ARMv8 Boards (for mobile devices)
========================================================
Overview
--------
This document describes how to build and run U-Boot for Samsung Exynos generic
boards. Boards are expected to boot with a primary bootloader, such as S-BOOT or
S-LK, which hands off control to U-Boot. Presently, only ARMv8 devices are
supported.
The U-Boot image is built with all device tree blobs packed in a single FIT
image. During boot, it uses simple heuristics to detect the target board, and
subsequently the appropriate FDT is selected.
Installation
------------
Building
^^^^^^^^
If a cross-compiler is required, install it and set it up like so:
.. prompt:: bash $
export CROSS_COMPILE=aarch64-linux-gnu-
Then, run the following commands to build U-Boot:
.. prompt:: bash $
make O=.output exynos-mobile_defconfig
make O=.output -j$(nproc)
If successful, the U-Boot binary will be present in ``.output/u-boot.bin``.
Preparation and Flashing
^^^^^^^^^^^^^^^^^^^^^^^^
Since U-Boot supports multiple boards, and devices have different requirements,
this step will vary depending on your target.
.. toctree::
:maxdepth: 1
exynos-mobile/exynos7870

View File

@@ -0,0 +1,85 @@
.. SPDX-License-Identifier: GPL-2.0+
.. sectionauthor:: Kaustabh Chakraborty <kauschluss@disroot.org>
Samsung Exynos 7870 Boards
==========================
Preparation
-----------
Create the following device tree (named ``stub.dts``)
.. code-block:: devicetree
/dts-v1/;
/ {
compatible = "samsung,exynos7870";
#address-cells = <2>;
#size-cells = <1>;
model_info-chip = <7870>;
model_info-hw_rev = <0>;
model_info-hw_rev_end = <255>;
chosen {
};
memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0>;
};
memory@100000000 {
device_type = "memory";
reg = <0x1 0x00000000 0x0>;
};
};
The chosen node and memory ranges are populated by S-BOOT. A certain device
model may have multiple variants, with differing amounts of RAM and storage. The
RAM capacity information is graciously provided by S-BOOT's device tree
overlays.
Compile it to a device tree blob, then pack it in the QCDT format [1]_ using
``dtbTool-exynos`` [2]_ by issuing the following commands:
.. prompt:: bash $
dtc -I dts -O dtb -o stub.dtb stub.dts
dtbTool-exynos -o stub-dt.img stub.dtb
Finally, use ``mkbootimg`` by osm0sis [3]_ to generate the boot image:
.. prompt:: bash $
mkbootimg -o u-boot.img \
--kernel .output/u-boot.bin \
--dt stub-dt.img
Offsets are not provided to ``mkbootimg`` as S-BOOT ignores them.
Flashing
--------
If flashing for the first time, it must be done via Samsung's Download (Odin)
mode. Heimdall [4]_ can be used for flashing, like so:
.. prompt:: bash $
heimdall flash --BOOT u-boot.img
However, if U-Boot is already installed, you may also use its fastboot interface
for flashing. Boot into the boot menu by holding the volume down key. Enable
fastboot mode from there, connect the device to your host, then run:
.. prompt:: bash $
fastboot flash boot u-boot.img
To flash an OS image in internal storage, fastboot is a reliable option.
References
----------
.. [1] https://wiki.postmarketos.org/wiki/QCDT
.. [2] https://github.com/dsankouski/dtbtool-exynos
.. [3] https://github.com/osm0sis/mkbootimg
.. [4] https://git.sr.ht/~grimler/Heimdall

View File

@@ -8,4 +8,5 @@ Samsung
axy17lte
e850-96
exynos-mobile
n1

View File

@@ -594,12 +594,13 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
if (!clk_valid(clk))
return 0;
ops = clk_dev_ops(clk->dev);
clk_get_priv(clk, &clkp);
/* Try to find parents which can set rate */
while (!ops->set_rate) {
struct clk *parent;
if (!(clk->flags & CLK_SET_RATE_PARENT))
if (!(clkp->flags & CLK_SET_RATE_PARENT))
return -ENOSYS;
parent = clk_get_parent(clk);
@@ -608,10 +609,9 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
clk = parent;
ops = clk_dev_ops(clk->dev);
clk_get_priv(clk, &clkp);
}
/* get private clock struct used for cache */
clk_get_priv(clk, &clkp);
/* Clean up cached rates for us and all child clocks */
clk_clean_rate_cache(clkp);

View File

@@ -15,6 +15,13 @@ config CLK_EXYNOS7420
This enables common clock driver support for platforms based
on Samsung Exynos7420 SoC.
config CLK_EXYNOS7870
bool "Clock driver for Samsung's Exynos7870 SoC"
select CLK_CCF
help
This enables common clock driver support for platforms based
on Samsung Exynos7870 SoC.
config CLK_EXYNOS850
bool "Clock driver for Samsung's Exynos850 SoC"
select CLK_CCF

View File

@@ -9,4 +9,5 @@
obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk.o clk-pll.o
obj-$(CONFIG_CLK_EXYNOS7420) += clk-exynos7420.o
obj-$(CONFIG_CLK_EXYNOS7870) += clk-exynos7870.o
obj-$(CONFIG_CLK_EXYNOS850) += clk-exynos850.o

View File

@@ -0,0 +1,929 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Samsung Exynos7870 clock driver.
* Copyright (C) 2015 Samsung Electronics Co., Ltd.
* Author: Kaustabh Chakraborty <kauschluss@disroot.org>
*/
#include "linux/clk-provider.h"
#include <dm.h>
#include <asm/io.h>
#include <dt-bindings/clock/samsung,exynos7870-cmu.h>
#include "clk.h"
enum exynos7870_cmu_id {
CMU_MIF,
CMU_FSYS,
CMU_PERI,
};
/*
* Register offsets for CMU_MIF (0x10460000)
*/
#define PLL_LOCKTIME_MIF_MEM_PLL 0x0000
#define PLL_LOCKTIME_MIF_MEDIA_PLL 0x0020
#define PLL_LOCKTIME_MIF_BUS_PLL 0x0040
#define PLL_CON0_MIF_MEM_PLL 0x0100
#define PLL_CON0_MIF_MEDIA_PLL 0x0120
#define PLL_CON0_MIF_BUS_PLL 0x0140
#define CLK_CON_GAT_MIF_MUX_MEM_PLL 0x0200
#define CLK_CON_GAT_MIF_MUX_MEM_PLL_CON 0x0200
#define CLK_CON_GAT_MIF_MUX_MEDIA_PLL 0x0204
#define CLK_CON_GAT_MIF_MUX_MEDIA_PLL_CON 0x0204
#define CLK_CON_GAT_MIF_MUX_BUS_PLL 0x0208
#define CLK_CON_GAT_MIF_MUX_BUS_PLL_CON 0x0208
#define CLK_CON_GAT_MIF_MUX_BUSD 0x0220
#define CLK_CON_MUX_MIF_BUSD 0x0220
#define CLK_CON_GAT_MIF_MUX_CMU_ISP_VRA 0x0264
#define CLK_CON_MUX_MIF_CMU_ISP_VRA 0x0264
#define CLK_CON_GAT_MIF_MUX_CMU_ISP_CAM 0x0268
#define CLK_CON_MUX_MIF_CMU_ISP_CAM 0x0268
#define CLK_CON_GAT_MIF_MUX_CMU_ISP_ISP 0x026c
#define CLK_CON_MUX_MIF_CMU_ISP_ISP 0x026c
#define CLK_CON_GAT_MIF_MUX_CMU_DISPAUD_BUS 0x0270
#define CLK_CON_MUX_MIF_CMU_DISPAUD_BUS 0x0270
#define CLK_CON_GAT_MIF_MUX_CMU_DISPAUD_DECON_VCLK 0x0274
#define CLK_CON_MUX_MIF_CMU_DISPAUD_DECON_VCLK 0x0274
#define CLK_CON_GAT_MIF_MUX_CMU_DISPAUD_DECON_ECLK 0x0278
#define CLK_CON_MUX_MIF_CMU_DISPAUD_DECON_ECLK 0x0278
#define CLK_CON_GAT_MIF_MUX_CMU_MFCMSCL_MSCL 0x027c
#define CLK_CON_MUX_MIF_CMU_MFCMSCL_MSCL 0x027c
#define CLK_CON_GAT_MIF_MUX_CMU_MFCMSCL_MFC 0x0280
#define CLK_CON_MUX_MIF_CMU_MFCMSCL_MFC 0x0280
#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_BUS 0x0284
#define CLK_CON_MUX_MIF_CMU_FSYS_BUS 0x0284
#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC0 0x0288
#define CLK_CON_MUX_MIF_CMU_FSYS_MMC0 0x0288
#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC1 0x028c
#define CLK_CON_MUX_MIF_CMU_FSYS_MMC1 0x028c
#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC2 0x0290
#define CLK_CON_MUX_MIF_CMU_FSYS_MMC2 0x0290
#define CLK_CON_GAT_MIF_MUX_CMU_FSYS_USB20DRD_REFCLK 0x029c
#define CLK_CON_MUX_MIF_CMU_FSYS_USB20DRD_REFCLK 0x029c
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_BUS 0x02a0
#define CLK_CON_MUX_MIF_CMU_PERI_BUS 0x02a0
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_UART1 0x02a4
#define CLK_CON_MUX_MIF_CMU_PERI_UART1 0x02a4
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_UART2 0x02a8
#define CLK_CON_MUX_MIF_CMU_PERI_UART2 0x02a8
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_UART0 0x02ac
#define CLK_CON_MUX_MIF_CMU_PERI_UART0 0x02ac
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI2 0x02b0
#define CLK_CON_MUX_MIF_CMU_PERI_SPI2 0x02b0
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI1 0x02b4
#define CLK_CON_MUX_MIF_CMU_PERI_SPI1 0x02b4
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI0 0x02b8
#define CLK_CON_MUX_MIF_CMU_PERI_SPI0 0x02b8
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI3 0x02bc
#define CLK_CON_MUX_MIF_CMU_PERI_SPI3 0x02bc
#define CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI4 0x02c0
#define CLK_CON_MUX_MIF_CMU_PERI_SPI4 0x02c0
#define CLK_CON_GAT_MIF_MUX_CMU_ISP_SENSOR0 0x02c4
#define CLK_CON_MUX_MIF_CMU_ISP_SENSOR0 0x02c4
#define CLK_CON_GAT_MIF_MUX_CMU_ISP_SENSOR1 0x02c8
#define CLK_CON_MUX_MIF_CMU_ISP_SENSOR1 0x02c8
#define CLK_CON_GAT_MIF_MUX_CMU_ISP_SENSOR2 0x02cc
#define CLK_CON_MUX_MIF_CMU_ISP_SENSOR2 0x02cc
#define CLK_CON_DIV_MIF_BUSD 0x0420
#define CLK_CON_DIV_MIF_APB 0x0424
#define CLK_CON_DIV_MIF_HSI2C 0x0430
#define CLK_CON_DIV_MIF_CMU_G3D_SWITCH 0x0460
#define CLK_CON_DIV_MIF_CMU_ISP_VRA 0x0464
#define CLK_CON_DIV_MIF_CMU_ISP_CAM 0x0468
#define CLK_CON_DIV_MIF_CMU_ISP_ISP 0x046c
#define CLK_CON_DIV_MIF_CMU_DISPAUD_BUS 0x0470
#define CLK_CON_DIV_MIF_CMU_DISPAUD_DECON_VCLK 0x0474
#define CLK_CON_DIV_MIF_CMU_DISPAUD_DECON_ECLK 0x0478
#define CLK_CON_DIV_MIF_CMU_MFCMSCL_MSCL 0x047c
#define CLK_CON_DIV_MIF_CMU_MFCMSCL_MFC 0x0480
#define CLK_CON_DIV_MIF_CMU_FSYS_BUS 0x0484
#define CLK_CON_DIV_MIF_CMU_FSYS_MMC0 0x0488
#define CLK_CON_DIV_MIF_CMU_FSYS_MMC1 0x048c
#define CLK_CON_DIV_MIF_CMU_FSYS_MMC2 0x0490
#define CLK_CON_DIV_MIF_CMU_FSYS_USB20DRD_REFCLK 0x049c
#define CLK_CON_DIV_MIF_CMU_PERI_BUS 0x04a0
#define CLK_CON_DIV_MIF_CMU_PERI_UART1 0x04a4
#define CLK_CON_DIV_MIF_CMU_PERI_UART2 0x04a8
#define CLK_CON_DIV_MIF_CMU_PERI_UART0 0x04ac
#define CLK_CON_DIV_MIF_CMU_PERI_SPI2 0x04b0
#define CLK_CON_DIV_MIF_CMU_PERI_SPI1 0x04b4
#define CLK_CON_DIV_MIF_CMU_PERI_SPI0 0x04b8
#define CLK_CON_DIV_MIF_CMU_PERI_SPI3 0x04bc
#define CLK_CON_DIV_MIF_CMU_PERI_SPI4 0x04c0
#define CLK_CON_DIV_MIF_CMU_ISP_SENSOR0 0x04c4
#define CLK_CON_DIV_MIF_CMU_ISP_SENSOR1 0x04c8
#define CLK_CON_DIV_MIF_CMU_ISP_SENSOR2 0x04cc
#define CLK_CON_GAT_MIF_WRAP_ADC_IF_OSC_SYS 0x080c
#define CLK_CON_GAT_MIF_HSI2C_AP_PCLKS 0x0828
#define CLK_CON_GAT_MIF_HSI2C_CP_PCLKS 0x0828
#define CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S0 0x0828
#define CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S1 0x0828
#define CLK_CON_GAT_MIF_CP_PCLK_HSI2C 0x0840
#define CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_0 0x0840
#define CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_1 0x0840
#define CLK_CON_GAT_MIF_HSI2C_AP_PCLKM 0x0840
#define CLK_CON_GAT_MIF_HSI2C_CP_PCLKM 0x0840
#define CLK_CON_GAT_MIF_HSI2C_IPCLK 0x0840
#define CLK_CON_GAT_MIF_HSI2C_ITCLK 0x0840
#define CLK_CON_GAT_MIF_CMU_G3D_SWITCH 0x0860
#define CLK_CON_GAT_MIF_CMU_ISP_VRA 0x0864
#define CLK_CON_GAT_MIF_CMU_ISP_CAM 0x0868
#define CLK_CON_GAT_MIF_CMU_ISP_ISP 0x086c
#define CLK_CON_GAT_MIF_CMU_DISPAUD_BUS 0x0870
#define CLK_CON_GAT_MIF_CMU_DISPAUD_DECON_VCLK 0x0874
#define CLK_CON_GAT_MIF_CMU_DISPAUD_DECON_ECLK 0x0878
#define CLK_CON_GAT_MIF_CMU_MFCMSCL_MSCL 0x087c
#define CLK_CON_GAT_MIF_CMU_MFCMSCL_MFC 0x0880
#define CLK_CON_GAT_MIF_CMU_FSYS_BUS 0x0884
#define CLK_CON_GAT_MIF_CMU_FSYS_MMC0 0x0888
#define CLK_CON_GAT_MIF_CMU_FSYS_MMC1 0x088c
#define CLK_CON_GAT_MIF_CMU_FSYS_MMC2 0x0890
#define CLK_CON_GAT_MIF_CMU_FSYS_USB20DRD_REFCLK 0x089c
#define CLK_CON_GAT_MIF_CMU_PERI_BUS 0x08a0
#define CLK_CON_GAT_MIF_CMU_PERI_UART1 0x08a4
#define CLK_CON_GAT_MIF_CMU_PERI_UART2 0x08a8
#define CLK_CON_GAT_MIF_CMU_PERI_UART0 0x08ac
#define CLK_CON_GAT_MIF_CMU_PERI_SPI2 0x08b0
#define CLK_CON_GAT_MIF_CMU_PERI_SPI1 0x08b4
#define CLK_CON_GAT_MIF_CMU_PERI_SPI0 0x08b8
#define CLK_CON_GAT_MIF_CMU_PERI_SPI3 0x08bc
#define CLK_CON_GAT_MIF_CMU_PERI_SPI4 0x08c0
#define CLK_CON_GAT_MIF_CMU_ISP_SENSOR0 0x08c4
#define CLK_CON_GAT_MIF_CMU_ISP_SENSOR1 0x08c8
#define CLK_CON_GAT_MIF_CMU_ISP_SENSOR2 0x08cc
static const struct samsung_pll_clock mif_pll_clks[] = {
PLL(pll_1417x, CLK_FOUT_MIF_BUS_PLL, "fout_mif_bus_pll", "oscclk",
PLL_CON0_MIF_BUS_PLL),
PLL(pll_1417x, CLK_FOUT_MIF_MEDIA_PLL, "fout_mif_media_pll", "oscclk",
PLL_CON0_MIF_MEDIA_PLL),
PLL(pll_1417x, CLK_FOUT_MIF_MEM_PLL, "fout_mif_mem_pll", "oscclk",
PLL_CON0_MIF_MEM_PLL),
};
static const struct samsung_gate_clock mif_pll_gate_clks[] = {
GATE(CLK_GOUT_MIF_MUX_BUS_PLL_CON,
"gout_mif_mux_bus_pll_con", "fout_mif_bus_pll",
CLK_CON_GAT_MIF_MUX_BUS_PLL_CON, 12,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_MEDIA_PLL_CON,
"gout_mif_mux_media_pll_con", "fout_mif_media_pll",
CLK_CON_GAT_MIF_MUX_MEDIA_PLL_CON, 12,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_MEM_PLL_CON,
"gout_mif_mux_mem_pll_con", "fout_mif_mem_pll",
CLK_CON_GAT_MIF_MUX_MEM_PLL_CON, 12,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_BUS_PLL,
"gout_mif_mux_bus_pll", "gout_mif_mux_bus_pll_con",
CLK_CON_GAT_MIF_MUX_BUS_PLL, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_MEM_PLL,
"gout_mif_mux_mem_pll", "gout_mif_mux_mem_pll_con",
CLK_CON_GAT_MIF_MUX_MEM_PLL, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_MEDIA_PLL,
"gout_mif_mux_media_pll", "gout_mif_mux_media_pll_con",
CLK_CON_GAT_MIF_MUX_MEDIA_PLL, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_fixed_factor_clock mif_fixed_factor_clks[] = {
FFACTOR(0, "ffac_mif_mux_bus_pll_div2", "gout_mif_mux_bus_pll_con",
1, 2, 0),
FFACTOR(0, "ffac_mif_mux_media_pll_div2", "gout_mif_mux_media_pll_con",
1, 2, 0),
FFACTOR(0, "ffac_mif_mux_mem_pll_div2", "gout_mif_mux_mem_pll_con",
1, 2, 0),
};
/* List of parent clocks for muxes in CMU_MIF */
PNAME(mout_mif_busd_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2",
"ffac_mif_mux_mem_pll_div2" };
PNAME(mout_mif_cmu_fsys_bus_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_fsys_mmc0_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_fsys_mmc1_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_fsys_mmc2_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_fsys_usb20drd_refclk_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_peri_bus_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_peri_spi0_p) = { "ffac_mif_mux_bus_pll_div2",
"oscclk" };
PNAME(mout_mif_cmu_peri_spi1_p) = { "ffac_mif_mux_bus_pll_div2",
"oscclk" };
PNAME(mout_mif_cmu_peri_spi2_p) = { "ffac_mif_mux_bus_pll_div2",
"oscclk" };
PNAME(mout_mif_cmu_peri_spi3_p) = { "ffac_mif_mux_bus_pll_div2",
"oscclk" };
PNAME(mout_mif_cmu_peri_spi4_p) = { "ffac_mif_mux_bus_pll_div2",
"oscclk" };
PNAME(mout_mif_cmu_peri_uart2_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_peri_uart0_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
PNAME(mout_mif_cmu_peri_uart1_p) = { "ffac_mif_mux_bus_pll_div2",
"ffac_mif_mux_media_pll_div2" };
static const struct samsung_mux_clock mif_mux_clks[] = {
MUX(CLK_MOUT_MIF_BUSD,
"mout_mif_busd", mout_mif_busd_p,
CLK_CON_MUX_MIF_BUSD, 12, 2),
MUX(CLK_MOUT_MIF_CMU_FSYS_BUS,
"mout_mif_cmu_fsys_bus", mout_mif_cmu_fsys_bus_p,
CLK_CON_MUX_MIF_CMU_FSYS_BUS, 12, 1),
MUX(CLK_MOUT_MIF_CMU_FSYS_MMC0,
"mout_mif_cmu_fsys_mmc0", mout_mif_cmu_fsys_mmc0_p,
CLK_CON_MUX_MIF_CMU_FSYS_MMC0, 12, 1),
MUX(CLK_MOUT_MIF_CMU_FSYS_MMC1,
"mout_mif_cmu_fsys_mmc1", mout_mif_cmu_fsys_mmc1_p,
CLK_CON_MUX_MIF_CMU_FSYS_MMC1, 12, 1),
MUX(CLK_MOUT_MIF_CMU_FSYS_MMC2,
"mout_mif_cmu_fsys_mmc2", mout_mif_cmu_fsys_mmc2_p,
CLK_CON_MUX_MIF_CMU_FSYS_MMC2, 12, 1),
MUX(CLK_MOUT_MIF_CMU_FSYS_USB20DRD_REFCLK,
"mout_mif_cmu_fsys_usb20drd_refclk", mout_mif_cmu_fsys_usb20drd_refclk_p,
CLK_CON_MUX_MIF_CMU_FSYS_USB20DRD_REFCLK, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_BUS,
"mout_mif_cmu_peri_bus", mout_mif_cmu_peri_bus_p,
CLK_CON_MUX_MIF_CMU_PERI_BUS, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_SPI0,
"mout_mif_cmu_peri_spi0", mout_mif_cmu_peri_spi0_p,
CLK_CON_MUX_MIF_CMU_PERI_SPI0, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_SPI1,
"mout_mif_cmu_peri_spi1", mout_mif_cmu_peri_spi1_p,
CLK_CON_MUX_MIF_CMU_PERI_SPI1, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_SPI2,
"mout_mif_cmu_peri_spi2", mout_mif_cmu_peri_spi2_p,
CLK_CON_MUX_MIF_CMU_PERI_SPI2, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_SPI3,
"mout_mif_cmu_peri_spi3", mout_mif_cmu_peri_spi3_p,
CLK_CON_MUX_MIF_CMU_PERI_SPI3, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_SPI4,
"mout_mif_cmu_peri_spi4", mout_mif_cmu_peri_spi4_p,
CLK_CON_MUX_MIF_CMU_PERI_SPI4, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_UART0,
"mout_mif_cmu_peri_uart0", mout_mif_cmu_peri_uart0_p,
CLK_CON_MUX_MIF_CMU_PERI_UART0, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_UART1,
"mout_mif_cmu_peri_uart1", mout_mif_cmu_peri_uart1_p,
CLK_CON_MUX_MIF_CMU_PERI_UART1, 12, 1),
MUX(CLK_MOUT_MIF_CMU_PERI_UART2,
"mout_mif_cmu_peri_uart2", mout_mif_cmu_peri_uart2_p,
CLK_CON_MUX_MIF_CMU_PERI_UART2, 12, 1),
};
static const struct samsung_gate_clock mif_mux_gate_clks[] = {
GATE(CLK_GOUT_MIF_MUX_BUSD,
"gout_mif_mux_busd", "mout_mif_busd",
CLK_CON_GAT_MIF_MUX_BUSD, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_BUS,
"gout_mif_mux_cmu_fsys_bus", "mout_mif_cmu_fsys_bus",
CLK_CON_GAT_MIF_MUX_CMU_FSYS_BUS, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_MMC0,
"gout_mif_mux_cmu_fsys_mmc0", "mout_mif_cmu_fsys_mmc0",
CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC0, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_MMC1,
"gout_mif_mux_cmu_fsys_mmc1", "mout_mif_cmu_fsys_mmc1",
CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC1, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_MMC2,
"gout_mif_mux_cmu_fsys_mmc2", "mout_mif_cmu_fsys_mmc2",
CLK_CON_GAT_MIF_MUX_CMU_FSYS_MMC2, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_FSYS_USB20DRD_REFCLK,
"gout_mif_mux_cmu_fsys_usb20drd_refclk", "mout_mif_cmu_fsys_usb20drd_refclk",
CLK_CON_GAT_MIF_MUX_CMU_FSYS_USB20DRD_REFCLK, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_BUS,
"gout_mif_mux_cmu_peri_bus", "mout_mif_cmu_peri_bus",
CLK_CON_GAT_MIF_MUX_CMU_PERI_BUS, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI0,
"gout_mif_mux_cmu_peri_spi0", "mout_mif_cmu_peri_spi0",
CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI0, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI1,
"gout_mif_mux_cmu_peri_spi1", "mout_mif_cmu_peri_spi1",
CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI1, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI2,
"gout_mif_mux_cmu_peri_spi2", "mout_mif_cmu_peri_spi2",
CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI2, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI3,
"gout_mif_mux_cmu_peri_spi3", "mout_mif_cmu_peri_spi3",
CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI3, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_SPI4,
"gout_mif_mux_cmu_peri_spi4", "mout_mif_cmu_peri_spi4",
CLK_CON_GAT_MIF_MUX_CMU_PERI_SPI4, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_UART0,
"gout_mif_mux_cmu_peri_uart0", "mout_mif_cmu_peri_uart0",
CLK_CON_GAT_MIF_MUX_CMU_PERI_UART0, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_UART1,
"gout_mif_mux_cmu_peri_uart1", "mout_mif_cmu_peri_uart1",
CLK_CON_GAT_MIF_MUX_CMU_PERI_UART1, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_MUX_CMU_PERI_UART2,
"gout_mif_mux_cmu_peri_uart2", "mout_mif_cmu_peri_uart2",
CLK_CON_GAT_MIF_MUX_CMU_PERI_UART2, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_div_clock mif_div_clks[] = {
DIV(CLK_DOUT_MIF_HSI2C,
"dout_mif_hsi2c", "ffac_mif_mux_media_pll_div2",
CLK_CON_DIV_MIF_HSI2C, 0, 4),
DIV(CLK_DOUT_MIF_BUSD,
"dout_mif_busd", "gout_mif_mux_busd",
CLK_CON_DIV_MIF_BUSD, 0, 4),
DIV(CLK_DOUT_MIF_CMU_FSYS_BUS,
"dout_mif_cmu_fsys_bus", "gout_mif_mux_cmu_fsys_bus",
CLK_CON_DIV_MIF_CMU_FSYS_BUS, 0, 4),
DIV(CLK_DOUT_MIF_CMU_FSYS_MMC0,
"dout_mif_cmu_fsys_mmc0", "gout_mif_mux_cmu_fsys_mmc0",
CLK_CON_DIV_MIF_CMU_FSYS_MMC0, 0, 10),
DIV(CLK_DOUT_MIF_CMU_FSYS_MMC1,
"dout_mif_cmu_fsys_mmc1", "gout_mif_mux_cmu_fsys_mmc1",
CLK_CON_DIV_MIF_CMU_FSYS_MMC1, 0, 10),
DIV(CLK_DOUT_MIF_CMU_FSYS_MMC2,
"dout_mif_cmu_fsys_mmc2", "gout_mif_mux_cmu_fsys_mmc2",
CLK_CON_DIV_MIF_CMU_FSYS_MMC2, 0, 10),
DIV(CLK_DOUT_MIF_CMU_FSYS_USB20DRD_REFCLK,
"dout_mif_cmu_fsys_usb20drd_refclk", "gout_mif_mux_cmu_fsys_usb20drd_refclk",
CLK_CON_DIV_MIF_CMU_FSYS_USB20DRD_REFCLK, 0, 4),
DIV(CLK_DOUT_MIF_CMU_PERI_BUS,
"dout_mif_cmu_peri_bus", "gout_mif_mux_cmu_peri_bus",
CLK_CON_DIV_MIF_CMU_PERI_BUS, 0, 4),
DIV(CLK_DOUT_MIF_CMU_PERI_SPI0,
"dout_mif_cmu_peri_spi0", "gout_mif_mux_cmu_peri_spi0",
CLK_CON_DIV_MIF_CMU_PERI_SPI0, 0, 6),
DIV(CLK_DOUT_MIF_CMU_PERI_SPI1,
"dout_mif_cmu_peri_spi1", "gout_mif_mux_cmu_peri_spi1",
CLK_CON_DIV_MIF_CMU_PERI_SPI1, 0, 6),
DIV(CLK_DOUT_MIF_CMU_PERI_SPI2,
"dout_mif_cmu_peri_spi2", "gout_mif_mux_cmu_peri_spi2",
CLK_CON_DIV_MIF_CMU_PERI_SPI2, 0, 6),
DIV(CLK_DOUT_MIF_CMU_PERI_SPI3,
"dout_mif_cmu_peri_spi3", "gout_mif_mux_cmu_peri_spi3",
CLK_CON_DIV_MIF_CMU_PERI_SPI3, 0, 6),
DIV(CLK_DOUT_MIF_CMU_PERI_SPI4,
"dout_mif_cmu_peri_spi4", "gout_mif_mux_cmu_peri_spi4",
CLK_CON_DIV_MIF_CMU_PERI_SPI4, 0, 6),
DIV(CLK_DOUT_MIF_CMU_PERI_UART0,
"dout_mif_cmu_peri_uart0", "gout_mif_mux_cmu_peri_uart0",
CLK_CON_DIV_MIF_CMU_PERI_UART0, 0, 4),
DIV(CLK_DOUT_MIF_CMU_PERI_UART1,
"dout_mif_cmu_peri_uart1", "gout_mif_mux_cmu_peri_uart1",
CLK_CON_DIV_MIF_CMU_PERI_UART1, 0, 4),
DIV(CLK_DOUT_MIF_CMU_PERI_UART2,
"dout_mif_cmu_peri_uart2", "gout_mif_mux_cmu_peri_uart2",
CLK_CON_DIV_MIF_CMU_PERI_UART2, 0, 4),
DIV(CLK_DOUT_MIF_APB,
"dout_mif_apb", "dout_mif_busd",
CLK_CON_DIV_MIF_APB, 0, 2),
};
static const struct samsung_gate_clock mif_gate_clks[] = {
GATE(CLK_GOUT_MIF_WRAP_ADC_IF_OSC_SYS,
"gout_mif_wrap_adc_if_osc_sys", "oscclk",
CLK_CON_GAT_MIF_WRAP_ADC_IF_OSC_SYS, 3,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_HSI2C_AP_PCLKS,
"gout_mif_hsi2c_ap_pclks", "dout_mif_apb",
CLK_CON_GAT_MIF_HSI2C_AP_PCLKS, 14,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_HSI2C_CP_PCLKS,
"gout_mif_hsi2c_cp_pclks", "dout_mif_apb",
CLK_CON_GAT_MIF_HSI2C_CP_PCLKS, 15,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_WRAP_ADC_IF_PCLK_S0,
"gout_mif_wrap_adc_if_pclk_s0", "dout_mif_apb",
CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S0, 20,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_WRAP_ADC_IF_PCLK_S1,
"gout_mif_wrap_adc_if_pclk_s1", "dout_mif_apb",
CLK_CON_GAT_MIF_WRAP_ADC_IF_PCLK_S1, 21,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_FSYS_BUS,
"gout_mif_cmu_fsys_bus", "dout_mif_cmu_fsys_bus",
CLK_CON_GAT_MIF_CMU_FSYS_BUS, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_FSYS_MMC0,
"gout_mif_cmu_fsys_mmc0", "dout_mif_cmu_fsys_mmc0",
CLK_CON_GAT_MIF_CMU_FSYS_MMC0, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_FSYS_MMC1,
"gout_mif_cmu_fsys_mmc1", "dout_mif_cmu_fsys_mmc1",
CLK_CON_GAT_MIF_CMU_FSYS_MMC1, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_FSYS_MMC2,
"gout_mif_cmu_fsys_mmc2", "dout_mif_cmu_fsys_mmc2",
CLK_CON_GAT_MIF_CMU_FSYS_MMC2, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_FSYS_USB20DRD_REFCLK,
"gout_mif_cmu_fsys_usb20drd_refclk", "dout_mif_cmu_fsys_usb20drd_refclk",
CLK_CON_GAT_MIF_CMU_FSYS_USB20DRD_REFCLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_BUS,
"gout_mif_cmu_peri_bus", "dout_mif_cmu_peri_bus",
CLK_CON_GAT_MIF_CMU_PERI_BUS, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_SPI0,
"gout_mif_cmu_peri_spi0", "dout_mif_cmu_peri_spi0",
CLK_CON_GAT_MIF_CMU_PERI_SPI0, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_SPI1,
"gout_mif_cmu_peri_spi1", "dout_mif_cmu_peri_spi1",
CLK_CON_GAT_MIF_CMU_PERI_SPI1, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_SPI2,
"gout_mif_cmu_peri_spi2", "dout_mif_cmu_peri_spi2",
CLK_CON_GAT_MIF_CMU_PERI_SPI2, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_SPI3,
"gout_mif_cmu_peri_spi3", "dout_mif_cmu_peri_spi3",
CLK_CON_GAT_MIF_CMU_PERI_SPI3, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_SPI4,
"gout_mif_cmu_peri_spi4", "dout_mif_cmu_peri_spi4",
CLK_CON_GAT_MIF_CMU_PERI_SPI4, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_UART0,
"gout_mif_cmu_peri_uart0", "dout_mif_cmu_peri_uart0",
CLK_CON_GAT_MIF_CMU_PERI_UART0, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_UART1,
"gout_mif_cmu_peri_uart1", "dout_mif_cmu_peri_uart1",
CLK_CON_GAT_MIF_CMU_PERI_UART1, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CMU_PERI_UART2,
"gout_mif_cmu_peri_uart2", "dout_mif_cmu_peri_uart2",
CLK_CON_GAT_MIF_CMU_PERI_UART2, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CP_PCLK_HSI2C,
"gout_mif_cp_pclk_hsi2c", "dout_mif_hsi2c",
CLK_CON_GAT_MIF_CP_PCLK_HSI2C, 6,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CP_PCLK_HSI2C_BAT_0,
"gout_mif_cp_pclk_hsi2c_bat_0", "dout_mif_hsi2c",
CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_0, 4,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_CP_PCLK_HSI2C_BAT_1,
"gout_mif_cp_pclk_hsi2c_bat_1", "dout_mif_hsi2c",
CLK_CON_GAT_MIF_CP_PCLK_HSI2C_BAT_1, 5,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_HSI2C_AP_PCLKM,
"gout_mif_hsi2c_ap_pclkm", "dout_mif_hsi2c",
CLK_CON_GAT_MIF_HSI2C_AP_PCLKM, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_HSI2C_CP_PCLKM,
"gout_mif_hsi2c_cp_pclkm", "dout_mif_hsi2c",
CLK_CON_GAT_MIF_HSI2C_CP_PCLKM, 1,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_HSI2C_IPCLK,
"gout_mif_hsi2c_ipclk", "dout_mif_hsi2c",
CLK_CON_GAT_MIF_HSI2C_IPCLK, 2,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_MIF_HSI2C_ITCLK,
"gout_mif_hsi2c_itclk", "dout_mif_hsi2c",
CLK_CON_GAT_MIF_HSI2C_ITCLK, 3,
CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_clk_group mif_cmu_clks[] = {
{ S_CLK_PLL, mif_pll_clks, ARRAY_SIZE(mif_pll_clks) },
{ S_CLK_GATE, mif_pll_gate_clks, ARRAY_SIZE(mif_pll_gate_clks) },
{ S_CLK_FFACTOR, mif_fixed_factor_clks, ARRAY_SIZE(mif_fixed_factor_clks) },
{ S_CLK_MUX, mif_mux_clks, ARRAY_SIZE(mif_mux_clks) },
{ S_CLK_GATE, mif_mux_gate_clks, ARRAY_SIZE(mif_mux_gate_clks) },
{ S_CLK_DIV, mif_div_clks, ARRAY_SIZE(mif_div_clks) },
{ S_CLK_GATE, mif_gate_clks, ARRAY_SIZE(mif_gate_clks) },
};
static int exynos7870_cmu_mif_probe(struct udevice *dev)
{
return samsung_register_cmu(dev, CMU_MIF, mif_cmu_clks,
exynos7870_cmu_mif);
}
static const struct udevice_id exynos7870_cmu_mif_ids[] = {
{ .compatible = "samsung,exynos7870-cmu-mif" },
{ }
};
SAMSUNG_CLK_OPS(exynos7870_cmu_mif, CMU_MIF);
U_BOOT_DRIVER(exynos7870_cmu_mif) = {
.name = "exynos7870-cmu-mif",
.id = UCLASS_CLK,
.of_match = exynos7870_cmu_mif_ids,
.ops = &exynos7870_cmu_mif_clk_ops,
.probe = exynos7870_cmu_mif_probe,
.flags = DM_FLAG_PRE_RELOC,
};
/*
* Register offsets for CMU_FSYS (0x13730000)
*/
#define PLL_LOCKTIME_FSYS_USB_PLL 0x0000
#define PLL_CON0_FSYS_USB_PLL 0x0100
#define CLK_CON_GAT_FSYS_MUX_USB_PLL 0x0200
#define CLK_CON_GAT_FSYS_MUX_USB_PLL_CON 0x0200
#define CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER 0x0230
#define CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER_CON 0x0230
#define CLK_CON_GAT_FSYS_BUSP3_HCLK 0x0804
#define CLK_CON_GAT_FSYS_MMC0_ACLK 0x0804
#define CLK_CON_GAT_FSYS_MMC1_ACLK 0x0804
#define CLK_CON_GAT_FSYS_MMC2_ACLK 0x0804
#define CLK_CON_GAT_FSYS_PDMA0_ACLK_PDMA0 0x0804
#define CLK_CON_GAT_FSYS_PPMU_ACLK 0x0804
#define CLK_CON_GAT_FSYS_PPMU_PCLK 0x0804
#define CLK_CON_GAT_FSYS_SROMC_HCLK 0x0804
#define CLK_CON_GAT_FSYS_UPSIZER_BUS1_ACLK 0x0804
#define CLK_CON_GAT_FSYS_USB20DRD_ACLK_HSDRD 0x0804
#define CLK_CON_GAT_FSYS_USB20DRD_HCLK_USB20_CTRL 0x0804
#define CLK_CON_GAT_FSYS_USB20DRD_HSDRD_REF_CLK 0x0828
static const struct samsung_fixed_rate_clock fsys_fixed_rate_clks[] = {
FRATE(0, "frat_fsys_usb20drd_phyclock", 60000000),
};
static const struct samsung_pll_clock fsys_pll_clks[] = {
PLL(pll_1417x, CLK_FOUT_FSYS_USB_PLL, "fout_fsys_usb_pll", "oscclk",
PLL_CON0_FSYS_USB_PLL),
};
static const struct samsung_gate_clock fsys_gate_clks[] = {
GATE(CLK_GOUT_FSYS_BUSP3_HCLK,
"gout_fsys_busp3_hclk", "bus",
CLK_CON_GAT_FSYS_BUSP3_HCLK, 2,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_UPSIZER_BUS1_ACLK,
"gout_fsys_upsizer_bus1_aclk", "bus",
CLK_CON_GAT_FSYS_UPSIZER_BUS1_ACLK, 12,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_PPMU_ACLK,
"gout_fsys_ppmu_aclk", "bus",
CLK_CON_GAT_FSYS_PPMU_ACLK, 17,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_PPMU_PCLK,
"gout_fsys_ppmu_pclk", "bus",
CLK_CON_GAT_FSYS_PPMU_PCLK, 18,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_USB20DRD_HSDRD_REF_CLK,
"gout_fsys_usb20drd_hsdrd_ref_clk", "usb20drd",
CLK_CON_GAT_FSYS_USB20DRD_HSDRD_REF_CLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_MUX_USB20DRD_PHYCLOCK_USER_CON,
"gout_fsys_mux_usb20drd_phyclock_user_con", "frat_fsys_usb20drd_phyclock",
CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER_CON, 12,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_MUX_USB_PLL_CON,
"gout_fsys_mux_usb_pll_con", "fout_fsys_usb_pll",
CLK_CON_GAT_FSYS_MUX_USB_PLL_CON, 12,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_MMC0_ACLK,
"gout_fsys_mmc0_aclk", "gout_fsys_busp3_hclk",
CLK_CON_GAT_FSYS_MMC0_ACLK, 8,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_MMC1_ACLK,
"gout_fsys_mmc1_aclk", "gout_fsys_busp3_hclk",
CLK_CON_GAT_FSYS_MMC1_ACLK, 9,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_MMC2_ACLK,
"gout_fsys_mmc2_aclk", "gout_fsys_busp3_hclk",
CLK_CON_GAT_FSYS_MMC2_ACLK, 10,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_USB20DRD_ACLK_HSDRD,
"gout_fsys_usb20drd_aclk_hsdrd", "gout_fsys_busp3_hclk",
CLK_CON_GAT_FSYS_USB20DRD_ACLK_HSDRD, 20,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_SROMC_HCLK,
"gout_fsys_sromc_hclk", "gout_fsys_busp3_hclk",
CLK_CON_GAT_FSYS_SROMC_HCLK, 6,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_USB20DRD_HCLK_USB20_CTRL,
"gout_fsys_usb20drd_hclk_usb20_ctrl", "gout_fsys_busp3_hclk",
CLK_CON_GAT_FSYS_USB20DRD_HCLK_USB20_CTRL, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_MUX_USB_PLL,
"gout_fsys_mux_usb_pll", "gout_fsys_mux_usb_pll_con",
CLK_CON_GAT_FSYS_MUX_USB_PLL, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_MUX_USB20DRD_PHYCLOCK_USER,
"gout_fsys_mux_usb20drd_phyclock_user", "gout_fsys_mux_usb20drd_phyclock_user_con",
CLK_CON_GAT_FSYS_MUX_USB20DRD_PHYCLOCK_USER, 21,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_FSYS_PDMA0_ACLK_PDMA0,
"gout_fsys_pdma0_aclk_pdma0", "gout_fsys_upsizer_bus1_aclk",
CLK_CON_GAT_FSYS_PDMA0_ACLK_PDMA0, 7,
CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_clk_group fsys_cmu_clks[] = {
{ S_CLK_FRATE, fsys_fixed_rate_clks, ARRAY_SIZE(fsys_fixed_rate_clks) },
{ S_CLK_PLL, fsys_pll_clks, ARRAY_SIZE(fsys_pll_clks) },
{ S_CLK_GATE, fsys_gate_clks, ARRAY_SIZE(fsys_gate_clks) },
};
static int exynos7870_cmu_fsys_probe(struct udevice *dev)
{
return samsung_register_cmu(dev, CMU_FSYS, fsys_cmu_clks,
exynos7870_cmu_fsys);
}
static const struct udevice_id exynos7870_cmu_fsys_ids[] = {
{ .compatible = "samsung,exynos7870-cmu-fsys" },
{ }
};
SAMSUNG_CLK_OPS(exynos7870_cmu_fsys, CMU_FSYS);
U_BOOT_DRIVER(exynos7870_cmu_fsys) = {
.name = "exynos7870-cmu-fsys",
.id = UCLASS_CLK,
.of_match = exynos7870_cmu_fsys_ids,
.ops = &exynos7870_cmu_fsys_clk_ops,
.probe = exynos7870_cmu_fsys_probe,
.flags = DM_FLAG_PRE_RELOC,
};
/*
* Register offsets for CMU_PERI (0x101f0000)
*/
#define CLK_CON_GAT_PERI_PWM_MOTOR_OSCCLK 0x0800
#define CLK_CON_GAT_PERI_TMU_CLK 0x0800
#define CLK_CON_GAT_PERI_TMU_CPUCL0_CLK 0x0800
#define CLK_CON_GAT_PERI_TMU_CPUCL1_CLK 0x0800
#define CLK_CON_GAT_PERI_BUSP1_PERIC0_HCLK 0x0810
#define CLK_CON_GAT_PERI_GPIO2_PCLK 0x0810
#define CLK_CON_GAT_PERI_GPIO5_PCLK 0x0810
#define CLK_CON_GAT_PERI_GPIO6_PCLK 0x0810
#define CLK_CON_GAT_PERI_GPIO7_PCLK 0x0810
#define CLK_CON_GAT_PERI_HSI2C1_IPCLK 0x0810
#define CLK_CON_GAT_PERI_HSI2C2_IPCLK 0x0810
#define CLK_CON_GAT_PERI_HSI2C3_IPCLK 0x0810
#define CLK_CON_GAT_PERI_HSI2C4_IPCLK 0x0810
#define CLK_CON_GAT_PERI_HSI2C5_IPCLK 0x0810
#define CLK_CON_GAT_PERI_HSI2C6_IPCLK 0x0810
#define CLK_CON_GAT_PERI_I2C0_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C1_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C2_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C3_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C4_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C5_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C6_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C7_PCLK 0x0810
#define CLK_CON_GAT_PERI_I2C8_PCLK 0x0810
#define CLK_CON_GAT_PERI_MCT_PCLK 0x0810
#define CLK_CON_GAT_PERI_PWM_MOTOR_PCLK_S0 0x0810
#define CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL0_PCLK 0x0814
#define CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL1_PCLK 0x0814
#define CLK_CON_GAT_PERI_SFRIF_TMU_PCLK 0x0814
#define CLK_CON_GAT_PERI_SPI0_PCLK 0x0814
#define CLK_CON_GAT_PERI_SPI1_PCLK 0x0814
#define CLK_CON_GAT_PERI_SPI2_PCLK 0x0814
#define CLK_CON_GAT_PERI_SPI3_PCLK 0x0814
#define CLK_CON_GAT_PERI_SPI4_PCLK 0x0814
#define CLK_CON_GAT_PERI_UART0_PCLK 0x0814
#define CLK_CON_GAT_PERI_UART1_PCLK 0x0814
#define CLK_CON_GAT_PERI_UART2_PCLK 0x0814
#define CLK_CON_GAT_PERI_WDT_CPUCL0_PCLK 0x0814
#define CLK_CON_GAT_PERI_WDT_CPUCL1_PCLK 0x0814
#define CLK_CON_GAT_PERI_UART1_EXT_UCLK 0x0830
#define CLK_CON_GAT_PERI_UART2_EXT_UCLK 0x0834
#define CLK_CON_GAT_PERI_UART0_EXT_UCLK 0x0838
#define CLK_CON_GAT_PERI_SPI2_SPI_EXT_CLK 0x083c
#define CLK_CON_GAT_PERI_SPI1_SPI_EXT_CLK 0x0840
#define CLK_CON_GAT_PERI_SPI0_SPI_EXT_CLK 0x0844
#define CLK_CON_GAT_PERI_SPI3_SPI_EXT_CLK 0x0848
#define CLK_CON_GAT_PERI_SPI4_SPI_EXT_CLK 0x084c
static const struct samsung_gate_clock peri_gate_clks[] = {
GATE(CLK_GOUT_PERI_PWM_MOTOR_OSCCLK,
"gout_peri_pwm_motor_oscclk", "oscclk",
CLK_CON_GAT_PERI_PWM_MOTOR_OSCCLK, 2,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_TMU_CLK,
"gout_peri_tmu_clk", "oscclk",
CLK_CON_GAT_PERI_TMU_CLK, 6,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_TMU_CPUCL0_CLK,
"gout_peri_tmu_cpucl0_clk", "oscclk",
CLK_CON_GAT_PERI_TMU_CPUCL0_CLK, 4,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_TMU_CPUCL1_CLK,
"gout_peri_tmu_cpucl1_clk", "oscclk",
CLK_CON_GAT_PERI_TMU_CPUCL1_CLK, 5,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_BUSP1_PERIC0_HCLK,
"gout_peri_busp1_peric0_hclk", "bus",
CLK_CON_GAT_PERI_BUSP1_PERIC0_HCLK, 3,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_GPIO2_PCLK,
"gout_peri_gpio2_pclk", "bus",
CLK_CON_GAT_PERI_GPIO2_PCLK, 7,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_GPIO5_PCLK,
"gout_peri_gpio5_pclk", "bus",
CLK_CON_GAT_PERI_GPIO5_PCLK, 8,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_GPIO6_PCLK,
"gout_peri_gpio6_pclk", "bus",
CLK_CON_GAT_PERI_GPIO6_PCLK, 9,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_GPIO7_PCLK,
"gout_peri_gpio7_pclk", "bus",
CLK_CON_GAT_PERI_GPIO7_PCLK, 10,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_HSI2C5_IPCLK,
"gout_peri_hsi2c5_ipclk", "bus",
CLK_CON_GAT_PERI_HSI2C5_IPCLK, 15,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_HSI2C6_IPCLK,
"gout_peri_hsi2c6_ipclk", "bus",
CLK_CON_GAT_PERI_HSI2C6_IPCLK, 16,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_MCT_PCLK,
"gout_peri_mct_pclk", "bus",
CLK_CON_GAT_PERI_MCT_PCLK, 26,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_PWM_MOTOR_PCLK_S0,
"gout_peri_pwm_motor_pclk_s0", "bus",
CLK_CON_GAT_PERI_PWM_MOTOR_PCLK_S0, 29,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SFRIF_TMU_CPUCL0_PCLK,
"gout_peri_sfrif_tmu_cpucl0_pclk", "bus",
CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL0_PCLK, 1,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SFRIF_TMU_CPUCL1_PCLK,
"gout_peri_sfrif_tmu_cpucl1_pclk", "bus",
CLK_CON_GAT_PERI_SFRIF_TMU_CPUCL1_PCLK, 2,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SFRIF_TMU_PCLK,
"gout_peri_sfrif_tmu_pclk", "bus",
CLK_CON_GAT_PERI_SFRIF_TMU_PCLK, 3,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI0_PCLK,
"gout_peri_spi0_pclk", "bus",
CLK_CON_GAT_PERI_SPI0_PCLK, 6,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI1_PCLK,
"gout_peri_spi1_pclk", "bus",
CLK_CON_GAT_PERI_SPI1_PCLK, 5,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI2_PCLK,
"gout_peri_spi2_pclk", "bus",
CLK_CON_GAT_PERI_SPI2_PCLK, 4,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI3_PCLK,
"gout_peri_spi3_pclk", "bus",
CLK_CON_GAT_PERI_SPI3_PCLK, 7,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI4_PCLK,
"gout_peri_spi4_pclk", "bus",
CLK_CON_GAT_PERI_SPI4_PCLK, 8,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_WDT_CPUCL0_PCLK,
"gout_peri_wdt_cpucl0_pclk", "bus",
CLK_CON_GAT_PERI_WDT_CPUCL0_PCLK, 13,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_WDT_CPUCL1_PCLK,
"gout_peri_wdt_cpucl1_pclk", "bus",
CLK_CON_GAT_PERI_WDT_CPUCL1_PCLK, 14,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI0_SPI_EXT_CLK,
"gout_peri_spi0_spi_ext_clk", "spi0",
CLK_CON_GAT_PERI_SPI0_SPI_EXT_CLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI1_SPI_EXT_CLK,
"gout_peri_spi1_spi_ext_clk", "spi1",
CLK_CON_GAT_PERI_SPI1_SPI_EXT_CLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI2_SPI_EXT_CLK,
"gout_peri_spi2_spi_ext_clk", "spi2",
CLK_CON_GAT_PERI_SPI2_SPI_EXT_CLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI3_SPI_EXT_CLK,
"gout_peri_spi3_spi_ext_clk", "spi3",
CLK_CON_GAT_PERI_SPI3_SPI_EXT_CLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_SPI4_SPI_EXT_CLK,
"gout_peri_spi4_spi_ext_clk", "spi4",
CLK_CON_GAT_PERI_SPI4_SPI_EXT_CLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_UART0_EXT_UCLK,
"gout_peri_uart0_ext_uclk", "uart0",
CLK_CON_GAT_PERI_UART0_EXT_UCLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_UART1_EXT_UCLK,
"gout_peri_uart1_ext_uclk", "uart1",
CLK_CON_GAT_PERI_UART1_EXT_UCLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_UART2_EXT_UCLK,
"gout_peri_uart2_ext_uclk", "uart2",
CLK_CON_GAT_PERI_UART2_EXT_UCLK, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_HSI2C1_IPCLK,
"gout_peri_hsi2c1_ipclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_HSI2C1_IPCLK, 11,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_HSI2C2_IPCLK,
"gout_peri_hsi2c2_ipclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_HSI2C2_IPCLK, 12,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_HSI2C3_IPCLK,
"gout_peri_hsi2c3_ipclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_HSI2C3_IPCLK, 13,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_HSI2C4_IPCLK,
"gout_peri_hsi2c4_ipclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_HSI2C4_IPCLK, 14,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C0_PCLK,
"gout_peri_i2c0_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C0_PCLK, 21,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C1_PCLK,
"gout_peri_i2c1_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C1_PCLK, 23,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C2_PCLK,
"gout_peri_i2c2_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C2_PCLK, 22,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C3_PCLK,
"gout_peri_i2c3_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C3_PCLK, 20,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C4_PCLK,
"gout_peri_i2c4_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C4_PCLK, 17,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C5_PCLK,
"gout_peri_i2c5_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C5_PCLK, 18,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C6_PCLK,
"gout_peri_i2c6_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C6_PCLK, 19,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C7_PCLK,
"gout_peri_i2c7_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C7_PCLK, 24,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_I2C8_PCLK,
"gout_peri_i2c8_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_I2C8_PCLK, 25,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_UART0_PCLK,
"gout_peri_uart0_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_UART0_PCLK, 10,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_UART1_PCLK,
"gout_peri_uart1_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_UART1_PCLK, 11,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERI_UART2_PCLK,
"gout_peri_uart2_pclk", "gout_peri_busp1_peric0_hclk",
CLK_CON_GAT_PERI_UART2_PCLK, 12,
CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_clk_group peri_cmu_clks[] = {
{ S_CLK_GATE, peri_gate_clks, ARRAY_SIZE(peri_gate_clks) },
};
static int exynos7870_cmu_peri_probe(struct udevice *dev)
{
return samsung_register_cmu(dev, CMU_PERI, peri_cmu_clks,
exynos7870_cmu_peri);
}
static const struct udevice_id exynos7870_cmu_peri_ids[] = {
{ .compatible = "samsung,exynos7870-cmu-peri" },
{ }
};
SAMSUNG_CLK_OPS(exynos7870_cmu_peri, CMU_PERI);
U_BOOT_DRIVER(exynos7870_cmu_peri) = {
.name = "exynos7870-cmu-peri",
.id = UCLASS_CLK,
.of_match = exynos7870_cmu_peri_ids,
.ops = &exynos7870_cmu_peri_clk_ops,
.probe = exynos7870_cmu_peri_probe,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@@ -117,6 +117,7 @@ static struct clk *_samsung_clk_register_pll(void __iomem *base,
switch (pll_clk->type) {
case pll_0822x:
case pll_1417x:
drv_name = UBOOT_DM_CLK_SAMSUNG_PLL0822X;
break;
case pll_0831x:
@@ -136,7 +137,8 @@ static struct clk *_samsung_clk_register_pll(void __iomem *base,
return clk;
}
void samsung_clk_register_pll(void __iomem *base, unsigned int cmu_id,
void samsung_clk_register_pll(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_pll_clock *clk_list,
unsigned int nr_clk)
{

View File

@@ -20,9 +20,11 @@ struct samsung_pll_clock;
enum samsung_pll_type {
pll_0822x,
pll_0831x,
pll_1417x,
};
void samsung_clk_register_pll(void __iomem *base, unsigned int cmu_id,
void samsung_clk_register_pll(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_pll_clock *clk_list,
unsigned int nr_clk);

View File

@@ -10,7 +10,62 @@
#include <dm.h>
#include "clk.h"
static void samsung_clk_register_mux(void __iomem *base, unsigned int cmu_id,
int samsung_clk_request(struct clk *clk)
{
struct clk *c;
int ret;
ret = clk_get_by_id(clk->id, &c);
if (ret)
return ret;
clk->dev = c->dev;
return 0;
}
static void
samsung_clk_register_fixed_rate(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_fixed_rate_clock *clk_list,
unsigned int nr_clk)
{
unsigned int cnt;
for (cnt = 0; cnt < nr_clk; cnt++) {
struct clk *clk;
const struct samsung_fixed_rate_clock *m;
unsigned long clk_id;
m = &clk_list[cnt];
clk = clk_register_fixed_rate(NULL, m->name, m->fixed_rate);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, m->id);
clk_dm(clk_id, clk);
}
}
static void
samsung_clk_register_fixed_factor(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_fixed_factor_clock *clk_list,
unsigned int nr_clk)
{
unsigned int cnt;
for (cnt = 0; cnt < nr_clk; cnt++) {
struct clk *clk;
const struct samsung_fixed_factor_clock *m;
unsigned long clk_id;
m = &clk_list[cnt];
clk = clk_register_fixed_factor(dev, m->name, m->parent_name,
m->flags, m->mult, m->div);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, m->id);
clk_dm(clk_id, clk);
}
}
static void samsung_clk_register_mux(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_mux_clock *clk_list,
unsigned int nr_clk)
{
@@ -22,15 +77,17 @@ static void samsung_clk_register_mux(void __iomem *base, unsigned int cmu_id,
unsigned long clk_id;
m = &clk_list[cnt];
clk = clk_register_mux(NULL, m->name, m->parent_names,
m->num_parents, m->flags, base + m->offset, m->shift,
m->width, m->mux_flags);
clk = clk_register_mux(dev, m->name, m->parent_names,
m->num_parents, m->flags,
base + m->offset, m->shift, m->width,
m->mux_flags);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, m->id);
clk_dm(clk_id, clk);
}
}
static void samsung_clk_register_div(void __iomem *base, unsigned int cmu_id,
static void samsung_clk_register_div(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_div_clock *clk_list,
unsigned int nr_clk)
{
@@ -42,15 +99,16 @@ static void samsung_clk_register_div(void __iomem *base, unsigned int cmu_id,
unsigned long clk_id;
d = &clk_list[cnt];
clk = clk_register_divider(NULL, d->name, d->parent_name,
d->flags, base + d->offset, d->shift,
d->width, d->div_flags);
clk = clk_register_divider(dev, d->name, d->parent_name,
d->flags, base + d->offset, d->shift,
d->width, d->div_flags);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, d->id);
clk_dm(clk_id, clk);
}
}
static void samsung_clk_register_gate(void __iomem *base, unsigned int cmu_id,
static void samsung_clk_register_gate(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_gate_clock *clk_list,
unsigned int nr_clk)
{
@@ -62,19 +120,21 @@ static void samsung_clk_register_gate(void __iomem *base, unsigned int cmu_id,
unsigned long clk_id;
g = &clk_list[cnt];
clk = clk_register_gate(NULL, g->name, g->parent_name,
g->flags, base + g->offset, g->bit_idx,
g->gate_flags, NULL);
clk = clk_register_gate(dev, g->name, g->parent_name,
g->flags, base + g->offset, g->bit_idx,
g->gate_flags, NULL);
clk_id = SAMSUNG_TO_CLK_ID(cmu_id, g->id);
clk_dm(clk_id, clk);
}
}
typedef void (*samsung_clk_register_fn)(void __iomem *base, unsigned int cmu_id,
const void *clk_list,
typedef void (*samsung_clk_register_fn)(struct udevice *dev, void __iomem *base,
unsigned int cmu_id, const void *clk_list,
unsigned int nr_clk);
static const samsung_clk_register_fn samsung_clk_register_fns[] = {
[S_CLK_FRATE] = (samsung_clk_register_fn)samsung_clk_register_fixed_rate,
[S_CLK_FFACTOR] = (samsung_clk_register_fn)samsung_clk_register_fixed_factor,
[S_CLK_MUX] = (samsung_clk_register_fn)samsung_clk_register_mux,
[S_CLK_DIV] = (samsung_clk_register_fn)samsung_clk_register_div,
[S_CLK_GATE] = (samsung_clk_register_fn)samsung_clk_register_gate,
@@ -91,16 +151,17 @@ static const samsung_clk_register_fn samsung_clk_register_fns[] = {
* Having the array of clock groups @clk_groups makes it possible to keep a
* correct clocks registration order.
*/
static void samsung_cmu_register_clocks(void __iomem *base, unsigned int cmu_id,
const struct samsung_clk_group *clk_groups,
unsigned int nr_groups)
static void samsung_cmu_register_clocks(struct udevice *dev, void __iomem *base,
unsigned int cmu_id,
const struct samsung_clk_group *clk_groups,
unsigned int nr_groups)
{
unsigned int i;
for (i = 0; i < nr_groups; i++) {
const struct samsung_clk_group *g = &clk_groups[i];
samsung_clk_register_fns[g->type](base, cmu_id,
samsung_clk_register_fns[g->type](dev, base, cmu_id,
g->clk_list, g->nr_clk);
}
}
@@ -124,7 +185,7 @@ int samsung_cmu_register_one(struct udevice *dev, unsigned int cmu_id,
if (!base)
return -EINVAL;
samsung_cmu_register_clocks(base, cmu_id, clk_groups, nr_groups);
samsung_cmu_register_clocks(dev, base, cmu_id, clk_groups, nr_groups);
return 0;
}

View File

@@ -9,10 +9,13 @@
#ifndef __EXYNOS_CLK_H
#define __EXYNOS_CLK_H
#include <clk.h>
#include <errno.h>
#include <linux/clk-provider.h>
#include "clk-pll.h"
int samsung_clk_request(struct clk *clk);
#define _SAMSUNG_CLK_OPS(_name, _cmu) \
static int _name##_of_xlate(struct clk *clk, \
struct ofnode_phandle_args *args) \
@@ -37,6 +40,7 @@ static const struct clk_ops _name##_clk_ops = { \
.enable = ccf_clk_enable, \
.disable = ccf_clk_disable, \
.of_xlate = _name##_of_xlate, \
.request = samsung_clk_request, \
}
/**
@@ -58,6 +62,53 @@ static const struct clk_ops _name##_clk_ops = { \
*/
#define SAMSUNG_TO_CLK_ID(_cmu, _id) (((_cmu) << 8) | ((_id) & 0xff))
/**
* struct samsung_fixed_rate_clock - information about fixed-rate clock
* @id: platform specific id of the clock
* @name: name of this fixed-rate clock
* @fixed_rate: fixed clock rate of this clock
*/
struct samsung_fixed_rate_clock {
unsigned int id;
const char *name;
unsigned long fixed_rate;
};
#define FRATE(_id, cname, frate) \
{ \
.id = _id, \
.name = cname, \
.fixed_rate = frate, \
}
/**
* struct samsung_fixed_factor_clock - information about fixed-factor clock
* @id: platform specific id of the clock
* @name: name of this fixed-factor clock
* @parent_name: parent clock name
* @mult: fixed multiplication factor
* @div: fixed division factor
* @flags: optional fixed-factor clock flags
*/
struct samsung_fixed_factor_clock {
unsigned int id;
const char *name;
const char *parent_name;
unsigned long mult;
unsigned long div;
unsigned long flags;
};
#define FFACTOR(_id, cname, pname, m, d, f) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.mult = m, \
.div = d, \
.flags = f, \
}
/**
* struct samsung_mux_clock - information about mux clock
* @id: platform specific id of the clock
@@ -206,6 +257,8 @@ struct samsung_pll_clock {
}
enum samsung_clock_type {
S_CLK_FRATE,
S_CLK_FFACTOR,
S_CLK_MUX,
S_CLK_DIV,
S_CLK_GATE,

View File

@@ -319,7 +319,7 @@ static int gpio_exynos_bind(struct udevice *parent)
base = dev_read_addr_ptr(parent);
for (node = fdt_first_subnode(blob, dev_of_offset(parent)), bank = base;
node > 0;
node = fdt_next_subnode(blob, node), bank++) {
node = fdt_next_subnode(blob, node)) {
struct exynos_gpio_plat *plat;
struct udevice *dev;
fdt_addr_t reg;
@@ -341,9 +341,8 @@ static int gpio_exynos_bind(struct udevice *parent)
if (reg != FDT_ADDR_T_NONE)
bank = (struct s5p_gpio_bank *)((ulong)base + reg);
plat->bank = bank;
debug("dev at %p: %s\n", bank, plat->bank_name);
plat->bank = bank++;
}
return 0;

View File

@@ -7,6 +7,7 @@
#include <log.h>
#include <dm.h>
#include <dm/lists.h>
#include <errno.h>
#include <asm/io.h>
#include "pinctrl-exynos.h"
@@ -178,3 +179,13 @@ int exynos_pinctrl_probe(struct udevice *dev)
return 0;
}
int exynos_pinctrl_bind(struct udevice *dev)
{
/*
* Attempt to bind the Exynos GPIO driver. The GPIOs and
* pin controller descriptors are found in the same OF node.
*/
return device_bind_driver_to_node(dev, "gpio_exynos", "gpio-banks",
dev_ofnode(dev), NULL);
}

View File

@@ -97,5 +97,6 @@ void exynos_pinctrl_setup_peri(struct exynos_pinctrl_config_data *conf,
int exynos_pinctrl_set_state(struct udevice *dev,
struct udevice *config);
int exynos_pinctrl_probe(struct udevice *dev);
int exynos_pinctrl_bind(struct udevice *dev);
#endif /* __PINCTRL_EXYNOS_H_ */

View File

@@ -114,4 +114,5 @@ U_BOOT_DRIVER(pinctrl_exynos7420) = {
.priv_auto = sizeof(struct exynos_pinctrl_priv),
.ops = &exynos7420_pinctrl_ops,
.probe = exynos_pinctrl_probe,
.bind = exynos_pinctrl_bind,
};

View File

@@ -45,6 +45,11 @@ static const struct samsung_pin_bank_data exynos78x0_pin_banks2[] = {
EXYNOS_PIN_BANK(4, 0x040, "gpz2"),
};
/* pin banks of exynos78x0 pin-controller 3 (ESE) */
static const struct samsung_pin_bank_data exynos78x0_pin_banks3[] = {
EXYNOS_PIN_BANK(5, 0x000, "gpc7"),
};
/* pin banks of exynos78x0 pin-controller 4 (FSYS) */
static const struct samsung_pin_bank_data exynos78x0_pin_banks4[] = {
EXYNOS_PIN_BANK(3, 0x000, "gpr0"),
@@ -54,6 +59,11 @@ static const struct samsung_pin_bank_data exynos78x0_pin_banks4[] = {
EXYNOS_PIN_BANK(6, 0x080, "gpr4"),
};
/* pin banks of exynos78x0 pin-controller 5 (NFC) */
static const struct samsung_pin_bank_data exynos78x0_pin_banks5[] = {
EXYNOS_PIN_BANK(4, 0x000, "gpc2"),
};
/* pin banks of exynos78x0 pin-controller 6 (TOP) */
static const struct samsung_pin_bank_data exynos78x0_pin_banks6[] = {
EXYNOS_PIN_BANK(4, 0x000, "gpb0"),
@@ -77,6 +87,11 @@ static const struct samsung_pin_bank_data exynos78x0_pin_banks6[] = {
EXYNOS_PIN_BANK(5, 0x240, "gpf4"),
};
/* pin banks of exynos7870 pin-controller 7 (TOUCH) */
static const struct samsung_pin_bank_data exynos78x0_pin_banks7[] = {
EXYNOS_PIN_BANK(3, 0x000, "gpc3"),
};
const struct samsung_pin_ctrl exynos78x0_pin_ctrl[] = {
{
/* pin-controller instance 0 Alive data */
@@ -102,9 +117,53 @@ const struct samsung_pin_ctrl exynos78x0_pin_ctrl[] = {
{/* list terminator */}
};
/*
* In Exynos7870, the CCORE block is named as MIF instead. As the
* pinctrl blocks are sorted in lexical order of their names, the
* order isn't the same as Exynos7880.
*/
const struct samsung_pin_ctrl exynos7870_pin_ctrl[] = {
{
/* pin-controller instance 0 Alive data */
.pin_banks = exynos78x0_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks0),
}, {
/* pin-controller instance 1 DISPAUD data */
.pin_banks = exynos78x0_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks2),
}, {
/* pin-controller instance 2 ESE data */
.pin_banks = exynos78x0_pin_banks3,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks3),
}, {
/* pin-controller instance 3 FSYS data */
.pin_banks = exynos78x0_pin_banks4,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks4),
}, {
/* pin-controller instance 4 MIF data */
.pin_banks = exynos78x0_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks1),
}, {
/* pin-controller instance 5 NFC data */
.pin_banks = exynos78x0_pin_banks5,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks5),
}, {
/* pin-controller instance 6 TOP data */
.pin_banks = exynos78x0_pin_banks6,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks6),
}, {
/* pin-controller instance 7 TOUCH data */
.pin_banks = exynos78x0_pin_banks7,
.nr_banks = ARRAY_SIZE(exynos78x0_pin_banks7),
},
{/* list terminator */}
};
static const struct udevice_id exynos78x0_pinctrl_ids[] = {
{ .compatible = "samsung,exynos78x0-pinctrl",
.data = (ulong)exynos78x0_pin_ctrl },
{ .compatible = "samsung,exynos7870-pinctrl",
.data = (ulong)exynos7870_pin_ctrl },
{ }
};
@@ -115,4 +174,5 @@ U_BOOT_DRIVER(pinctrl_exynos78x0) = {
.priv_auto = sizeof(struct exynos_pinctrl_priv),
.ops = &exynos78x0_pinctrl_ops,
.probe = exynos_pinctrl_probe,
.bind = exynos_pinctrl_bind,
};

View File

@@ -122,4 +122,5 @@ U_BOOT_DRIVER(pinctrl_exynos850) = {
.priv_auto = sizeof(struct exynos_pinctrl_priv),
.ops = &exynos850_pinctrl_ops,
.probe = exynos_pinctrl_probe,
.bind = exynos_pinctrl_bind,
};

View File

@@ -258,6 +258,7 @@ static const struct dm_serial_ops s5p_serial_ops = {
static const struct udevice_id s5p_serial_ids[] = {
{ .compatible = "samsung,exynos4210-uart", .data = PORT_S5P },
{ .compatible = "samsung,exynos850-uart", .data = PORT_S5P },
{ .compatible = "samsung,exynos8895-uart", .data = PORT_S5P },
{ .compatible = "apple,s5l-uart", .data = PORT_S5L },
{ }
};

View File

@@ -85,6 +85,9 @@ static int exynos_pmu_probe(struct udevice *dev)
}
static const struct udevice_id exynos_pmu_ids[] = {
{
.compatible = "samsung,exynos7-pmu",
},
{
.compatible = "samsung,exynos850-pmu",
.data = (ulong)&exynos850_pmu_data

View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Samsung Exynos Generic Board Configuration (for mobile devices)
*
* Copyright (C) 2025 Kaustabh Chakraborty <kauschluss@disroot.org>
*/
#ifndef __CONFIG_EXYNOS_MOBILE_H
#define __CONFIG_EXYNOS_MOBILE_H
#define CPU_RELEASE_ADDR secondary_boot_addr
#define CFG_SYS_BAUDRATE_TABLE {9600, 115200}
#endif /* __CONFIG_EXYNOS_MOBILE_H */

View File

@@ -139,7 +139,6 @@
#endif
#define CFG_EXTRA_ENV_SETTINGS \
"fdt_high=0xffffffff\0" \
"initrd_high=0xffffffff\0" \
"rootdev=" __stringify(CONFIG_ROOT_DEV) "\0" \
"rootpart=" __stringify(CONFIG_ROOT_PART) "\0" \