mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 13:11:31 +00:00
Merge git://git.denx.de/u-boot-dm
This commit is contained in:
commit
09849f4a77
77 changed files with 2053 additions and 712 deletions
|
@ -1,6 +1,7 @@
|
|||
#include "skeleton.dtsi"
|
||||
#include <dt-bindings/gpio/tegra-gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/mailbox/tegra-hsp.h>
|
||||
|
||||
/ {
|
||||
compatible = "nvidia,tegra186";
|
||||
|
@ -40,6 +41,18 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
hsp: hsp@3c00000 {
|
||||
compatible = "nvidia,tegra186-hsp";
|
||||
reg = <0x0 0x03c00000 0x0 0xa0000>;
|
||||
interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
|
||||
nvidia,num-SM = <0x8>;
|
||||
nvidia,num-AS = <0x2>;
|
||||
nvidia,num-SS = <0x2>;
|
||||
nvidia,num-DB = <0x7>;
|
||||
nvidia,num-SI = <0x8>;
|
||||
#mbox-cells = <1>;
|
||||
};
|
||||
|
||||
gpio@c2f0000 {
|
||||
compatible = "nvidia,tegra186-gpio-aon";
|
||||
reg-names = "security", "gpio";
|
||||
|
|
|
@ -62,18 +62,6 @@ static inline u32 clk_get_divisor(ulong input_rate, uint output_rate)
|
|||
*/
|
||||
void *rockchip_get_cru(void);
|
||||
|
||||
/**
|
||||
* rkclk_get_clk() - get a pointer to a given clock
|
||||
*
|
||||
* This is an internal function - use outside the clock subsystem indicates
|
||||
* that work is needed!
|
||||
*
|
||||
* @clk_id: Clock requested
|
||||
* @devp: Returns a pointer to that clock
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int rkclk_get_clk(enum rk_clk_id clk_id, struct udevice **devp);
|
||||
|
||||
struct rk3288_cru;
|
||||
struct rk3288_grf;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <dm.h>
|
||||
#include <ram.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/clock.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -54,15 +55,43 @@ void lowlevel_init(void)
|
|||
static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
static const struct {
|
||||
char *name;
|
||||
int id;
|
||||
} clks[] = {
|
||||
{ "osc", CLK_OSC },
|
||||
{ "apll", CLK_ARM },
|
||||
{ "dpll", CLK_DDR },
|
||||
{ "cpll", CLK_CODEC },
|
||||
{ "gpll", CLK_GENERAL },
|
||||
#ifdef CONFIG_ROCKCHIP_RK3036
|
||||
{ "mpll", CLK_NEW },
|
||||
#else
|
||||
{ "npll", CLK_NEW },
|
||||
#endif
|
||||
};
|
||||
int ret, i;
|
||||
struct udevice *dev;
|
||||
|
||||
for (uclass_first_device(UCLASS_CLK, &dev);
|
||||
dev;
|
||||
uclass_next_device(&dev)) {
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
|
||||
if (ret) {
|
||||
printf("clk-uclass not found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clks); i++) {
|
||||
struct clk clk;
|
||||
ulong rate;
|
||||
|
||||
rate = clk_get_rate(dev);
|
||||
printf("%s: %lu\n", dev->name, rate);
|
||||
clk.id = clks[i].id;
|
||||
ret = clk_request(dev, &clk);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
rate = clk_get_rate(&clk);
|
||||
printf("%s: %lu\n", clks[i].name, rate);
|
||||
|
||||
clk_free(&clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -36,7 +36,7 @@ struct chan_info {
|
|||
struct dram_info {
|
||||
struct chan_info chan[2];
|
||||
struct ram_info info;
|
||||
struct udevice *ddr_clk;
|
||||
struct clk ddr_clk;
|
||||
struct rk3288_cru *cru;
|
||||
struct rk3288_grf *grf;
|
||||
struct rk3288_sgrf *sgrf;
|
||||
|
@ -576,7 +576,7 @@ static void dram_all_config(const struct dram_info *dram,
|
|||
rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, sdram_params->base.stride);
|
||||
}
|
||||
|
||||
static int sdram_init(const struct dram_info *dram,
|
||||
static int sdram_init(struct dram_info *dram,
|
||||
const struct rk3288_sdram_params *sdram_params)
|
||||
{
|
||||
int channel;
|
||||
|
@ -592,8 +592,8 @@ static int sdram_init(const struct dram_info *dram,
|
|||
return -E2BIG;
|
||||
}
|
||||
|
||||
debug("ddr clk %s\n", dram->ddr_clk->name);
|
||||
ret = clk_set_rate(dram->ddr_clk, sdram_params->base.ddr_freq);
|
||||
debug("ddr clk dpll\n");
|
||||
ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq);
|
||||
debug("ret=%d\n", ret);
|
||||
if (ret) {
|
||||
debug("Could not set DDR clock\n");
|
||||
|
@ -836,6 +836,7 @@ static int rk3288_dmc_probe(struct udevice *dev)
|
|||
struct dram_info *priv = dev_get_priv(dev);
|
||||
struct regmap *map;
|
||||
int ret;
|
||||
struct udevice *dev_clk;
|
||||
|
||||
map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
|
||||
if (IS_ERR(map))
|
||||
|
@ -856,7 +857,11 @@ static int rk3288_dmc_probe(struct udevice *dev)
|
|||
priv->chan[1].pctl = regmap_get_range(map, 2);
|
||||
priv->chan[1].publ = regmap_get_range(map, 3);
|
||||
|
||||
ret = uclass_get_device(UCLASS_CLK, CLK_DDR, &priv->ddr_clk);
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->ddr_clk.id = CLK_DDR;
|
||||
ret = clk_request(dev_clk, &priv->ddr_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -212,11 +212,11 @@ static int clk_init_uart(struct msm_clk_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ulong msm_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
||||
ulong msm_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(dev);
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
switch (periph) {
|
||||
switch (clk->id) {
|
||||
case 0: /* SDC1 */
|
||||
return clk_init_sdc(priv, 0, rate);
|
||||
break;
|
||||
|
@ -243,7 +243,7 @@ static int msm_clk_probe(struct udevice *dev)
|
|||
}
|
||||
|
||||
static struct clk_ops msm_clk_ops = {
|
||||
.set_periph_rate = msm_set_periph_rate,
|
||||
.set_rate = msm_set_rate,
|
||||
};
|
||||
|
||||
static const struct udevice_id msm_clk_ids[] = {
|
||||
|
|
|
@ -56,8 +56,10 @@ config TEGRA210
|
|||
|
||||
config TEGRA186
|
||||
bool "Tegra186 family"
|
||||
select DM_MAILBOX
|
||||
select TEGRA186_GPIO
|
||||
select TEGRA_ARMV8_COMMON
|
||||
select TEGRA_HSP
|
||||
|
||||
endchoice
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <clk.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/clk.h>
|
||||
|
|
|
@ -23,18 +23,34 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static ulong clk_get_cpu_rate(void)
|
||||
static ulong rate(int id)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
struct clk clk;
|
||||
ulong rate;
|
||||
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
|
||||
if (ret) {
|
||||
panic("uclass-clk: device not found\n");
|
||||
printf("clk-uclass not found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return clk_get_rate(dev);
|
||||
clk.id = id;
|
||||
ret = clk_request(dev, &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
rate = clk_get_rate(&clk);
|
||||
|
||||
clk_free(&clk);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static ulong clk_get_cpu_rate(void)
|
||||
{
|
||||
return rate(PB7CLK);
|
||||
}
|
||||
|
||||
/* initialize prefetch module related to cpu_clk */
|
||||
|
@ -127,30 +143,25 @@ const char *get_core_name(void)
|
|||
}
|
||||
#endif
|
||||
#ifdef CONFIG_CMD_CLK
|
||||
|
||||
int soc_clk_dump(void)
|
||||
{
|
||||
int i, ret;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
|
||||
if (ret) {
|
||||
printf("clk-uclass not found\n");
|
||||
return ret;
|
||||
}
|
||||
int i;
|
||||
|
||||
printf("PLL Speed: %lu MHz\n",
|
||||
CLK_MHZ(clk_get_periph_rate(dev, PLLCLK)));
|
||||
printf("CPU Speed: %lu MHz\n", CLK_MHZ(clk_get_rate(dev)));
|
||||
printf("MPLL Speed: %lu MHz\n",
|
||||
CLK_MHZ(clk_get_periph_rate(dev, MPLL)));
|
||||
CLK_MHZ(rate(PLLCLK)));
|
||||
|
||||
printf("CPU Speed: %lu MHz\n", CLK_MHZ(rate(PB7CLK)));
|
||||
|
||||
printf("MPLL Speed: %lu MHz\n", CLK_MHZ(rate(MPLL)));
|
||||
|
||||
for (i = PB1CLK; i <= PB7CLK; i++)
|
||||
printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK + 1,
|
||||
CLK_MHZ(clk_get_periph_rate(dev, i)));
|
||||
CLK_MHZ(rate(i)));
|
||||
|
||||
for (i = REF1CLK; i <= REF5CLK; i++)
|
||||
printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK + 1,
|
||||
CLK_MHZ(clk_get_periph_rate(dev, i)));
|
||||
CLK_MHZ(rate(i)));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -108,8 +108,23 @@
|
|||
compatible = "denx,u-boot-fdt-test";
|
||||
};
|
||||
|
||||
clk@0 {
|
||||
clk_fixed: clk-fixed {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <1234>;
|
||||
};
|
||||
|
||||
clk_sandbox: clk-sbox {
|
||||
compatible = "sandbox,clk";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
clk-test {
|
||||
compatible = "sandbox,clk-test";
|
||||
clocks = <&clk_fixed>,
|
||||
<&clk_sandbox 1>,
|
||||
<&clk_sandbox 0>;
|
||||
clock-names = "fixed", "i2c", "spi";
|
||||
};
|
||||
|
||||
eth@10002000 {
|
||||
|
@ -259,6 +274,17 @@
|
|||
compatible = "sandbox,reset";
|
||||
};
|
||||
|
||||
resetc: reset-ctl {
|
||||
compatible = "sandbox,reset-ctl";
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
reset-ctl-test {
|
||||
compatible = "sandbox,reset-ctl-test";
|
||||
resets = <&resetc 100>, <&resetc 2>;
|
||||
reset-names = "other", "test";
|
||||
};
|
||||
|
||||
rproc_1: rproc@1 {
|
||||
compatible = "sandbox,test-processor";
|
||||
remoteproc-name = "remoteproc-test-dev1";
|
||||
|
|
111
arch/sandbox/include/asm/clk.h
Normal file
111
arch/sandbox/include/asm/clk.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SANDBOX_CLK_H
|
||||
#define __SANDBOX_CLK_H
|
||||
|
||||
#include <common.h>
|
||||
|
||||
struct udevice;
|
||||
|
||||
/**
|
||||
* enum sandbox_clk_id - Identity of clocks implemented by the sandbox clock
|
||||
* provider.
|
||||
*
|
||||
* These IDs are within/relative-to the clock provider.
|
||||
*/
|
||||
enum sandbox_clk_id {
|
||||
SANDBOX_CLK_ID_SPI,
|
||||
SANDBOX_CLK_ID_I2C,
|
||||
|
||||
SANDBOX_CLK_ID_COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sandbox_clk_test_id - Identity of the clocks consumed by the sandbox
|
||||
* clock test device.
|
||||
*
|
||||
* These are the IDs the clock consumer knows the clocks as.
|
||||
*/
|
||||
enum sandbox_clk_test_id {
|
||||
SANDBOX_CLK_TEST_ID_FIXED,
|
||||
SANDBOX_CLK_TEST_ID_SPI,
|
||||
SANDBOX_CLK_TEST_ID_I2C,
|
||||
|
||||
SANDBOX_CLK_TEST_ID_COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* sandbox_clk_query_rate - Query the current rate of a sandbox clock.
|
||||
*
|
||||
* @dev: The sandbox clock provider device.
|
||||
* @id: The clock to query.
|
||||
* @return: The rate of the clock.
|
||||
*/
|
||||
ulong sandbox_clk_query_rate(struct udevice *dev, int id);
|
||||
/**
|
||||
* sandbox_clk_query_enable - Query the enable state of a sandbox clock.
|
||||
*
|
||||
* @dev: The sandbox clock provider device.
|
||||
* @id: The clock to query.
|
||||
* @return: The rate of the clock.
|
||||
*/
|
||||
int sandbox_clk_query_enable(struct udevice *dev, int id);
|
||||
|
||||
/**
|
||||
* sandbox_clk_test_get - Ask the sandbox clock test device to request its
|
||||
* clocks.
|
||||
*
|
||||
* @dev: The sandbox clock test (client) devivce.
|
||||
* @return: 0 if OK, or a negative error code.
|
||||
*/
|
||||
int sandbox_clk_test_get(struct udevice *dev);
|
||||
/**
|
||||
* sandbox_clk_test_get_rate - Ask the sandbox clock test device to query a
|
||||
* clock's rate.
|
||||
*
|
||||
* @dev: The sandbox clock test (client) devivce.
|
||||
* @id: The test device's clock ID to query.
|
||||
* @return: The rate of the clock.
|
||||
*/
|
||||
ulong sandbox_clk_test_get_rate(struct udevice *dev, int id);
|
||||
/**
|
||||
* sandbox_clk_test_set_rate - Ask the sandbox clock test device to set a
|
||||
* clock's rate.
|
||||
*
|
||||
* @dev: The sandbox clock test (client) devivce.
|
||||
* @id: The test device's clock ID to configure.
|
||||
* @return: The new rate of the clock.
|
||||
*/
|
||||
ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate);
|
||||
/**
|
||||
* sandbox_clk_test_enable - Ask the sandbox clock test device to enable a
|
||||
* clock.
|
||||
*
|
||||
* @dev: The sandbox clock test (client) devivce.
|
||||
* @id: The test device's clock ID to configure.
|
||||
* @return: 0 if OK, or a negative error code.
|
||||
*/
|
||||
int sandbox_clk_test_enable(struct udevice *dev, int id);
|
||||
/**
|
||||
* sandbox_clk_test_disable - Ask the sandbox clock test device to disable a
|
||||
* clock.
|
||||
*
|
||||
* @dev: The sandbox clock test (client) devivce.
|
||||
* @id: The test device's clock ID to configure.
|
||||
* @return: 0 if OK, or a negative error code.
|
||||
*/
|
||||
int sandbox_clk_test_disable(struct udevice *dev, int id);
|
||||
/**
|
||||
* sandbox_clk_test_free - Ask the sandbox clock test device to free its
|
||||
* clocks.
|
||||
*
|
||||
* @dev: The sandbox clock test (client) devivce.
|
||||
* @return: 0 if OK, or a negative error code.
|
||||
*/
|
||||
int sandbox_clk_test_free(struct udevice *dev);
|
||||
|
||||
#endif
|
|
@ -26,7 +26,8 @@
|
|||
/**
|
||||
* Return the simulated value of a GPIO (used only in sandbox test code)
|
||||
*
|
||||
* @param gp GPIO number
|
||||
* @param dev device to use
|
||||
* @param offset GPIO offset within bank
|
||||
* @return -1 on error, 0 if GPIO is low, >0 if high
|
||||
*/
|
||||
int sandbox_gpio_get_value(struct udevice *dev, unsigned int offset);
|
||||
|
@ -34,8 +35,9 @@ int sandbox_gpio_get_value(struct udevice *dev, unsigned int offset);
|
|||
/**
|
||||
* Set the simulated value of a GPIO (used only in sandbox test code)
|
||||
*
|
||||
* @param gp GPIO number
|
||||
* @param value value to set (0 for low, non-zero for high)
|
||||
* @param dev device to use
|
||||
* @param offset GPIO offset within bank
|
||||
* @param value value to set (0 for low, non-zero for high)
|
||||
* @return -1 on error, 0 if ok
|
||||
*/
|
||||
int sandbox_gpio_set_value(struct udevice *dev, unsigned int offset, int value);
|
||||
|
@ -63,7 +65,8 @@ int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset);
|
|||
/**
|
||||
* Return the simulated direction of a GPIO (used only in sandbox test code)
|
||||
*
|
||||
* @param gp GPIO number
|
||||
* @param dev device to use
|
||||
* @param offset GPIO offset within bank
|
||||
* @return -1 on error, 0 if GPIO is input, >0 if output
|
||||
*/
|
||||
int sandbox_gpio_get_direction(struct udevice *dev, unsigned int offset);
|
||||
|
@ -71,8 +74,9 @@ int sandbox_gpio_get_direction(struct udevice *dev, unsigned int offset);
|
|||
/**
|
||||
* Set the simulated direction of a GPIO (used only in sandbox test code)
|
||||
*
|
||||
* @param gp GPIO number
|
||||
* @param output 0 to set as input, 1 to set as output
|
||||
* @param dev device to use
|
||||
* @param offset GPIO offset within bank
|
||||
* @param output 0 to set as input, 1 to set as output
|
||||
* @return -1 on error, 0 if ok
|
||||
*/
|
||||
int sandbox_gpio_set_direction(struct udevice *dev, unsigned int offset,
|
||||
|
|
21
arch/sandbox/include/asm/reset.h
Normal file
21
arch/sandbox/include/asm/reset.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SANDBOX_RESET_H
|
||||
#define __SANDBOX_RESET_H
|
||||
|
||||
#include <common.h>
|
||||
|
||||
struct udevice;
|
||||
|
||||
int sandbox_reset_query(struct udevice *dev, unsigned long id);
|
||||
|
||||
int sandbox_reset_test_get(struct udevice *dev);
|
||||
int sandbox_reset_test_assert(struct udevice *dev);
|
||||
int sandbox_reset_test_deassert(struct udevice *dev);
|
||||
int sandbox_reset_test_free(struct udevice *dev);
|
||||
|
||||
#endif
|
|
@ -19,15 +19,6 @@
|
|||
|
||||
#define SANDBOX_CLK_RATE 32768
|
||||
|
||||
enum {
|
||||
PERIPH_ID_FIRST = 0,
|
||||
PERIPH_ID_SPI = PERIPH_ID_FIRST,
|
||||
PERIPH_ID_I2C,
|
||||
PERIPH_ID_PCI,
|
||||
|
||||
PERIPH_ID_COUNT,
|
||||
};
|
||||
|
||||
/* System controller driver data */
|
||||
enum {
|
||||
SYSCON0 = 32,
|
||||
|
|
|
@ -11,20 +11,31 @@
|
|||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <clk.h>
|
||||
#include <dt-bindings/clock/microchip,clock.h>
|
||||
#include <mach/pic32.h>
|
||||
|
||||
#ifdef CONFIG_DISPLAY_BOARDINFO
|
||||
int checkboard(void)
|
||||
{
|
||||
ulong rate = 0;
|
||||
ulong rate;
|
||||
struct udevice *dev;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
printf("Core: %s\n", get_core_name());
|
||||
|
||||
if (!uclass_get_device(UCLASS_CLK, 0, &dev)) {
|
||||
rate = clk_get_rate(dev);
|
||||
printf("CPU Speed: %lu MHz\n", rate / 1000000);
|
||||
}
|
||||
if (uclass_get_device(UCLASS_CLK, 0, &dev))
|
||||
return 0;
|
||||
|
||||
clk.id = PB7CLK;
|
||||
ret = clk_request(dev, &clk);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(&clk);
|
||||
printf("CPU Speed: %lu MHz\n", rate / 1000000);
|
||||
|
||||
clk_free(&clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||
CONFIG_BLK=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="sandbox"
|
||||
|
@ -70,7 +71,6 @@ CONFIG_DEVRES=y
|
|||
CONFIG_DEBUG_DEVRES=y
|
||||
CONFIG_ADC=y
|
||||
CONFIG_ADC_SANDBOX=y
|
||||
CONFIG_BLK=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_CPU=y
|
||||
CONFIG_DM_DEMO=y
|
||||
|
@ -89,6 +89,9 @@ CONFIG_I2C_ARB_GPIO_CHALLENGE=y
|
|||
CONFIG_CROS_EC_KEYB=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_DM_MAILBOX=y
|
||||
CONFIG_SANDBOX_MBOX=y
|
||||
CONFIG_MISC=y
|
||||
CONFIG_CMD_CROS_EC=y
|
||||
CONFIG_CROS_EC=y
|
||||
CONFIG_CROS_EC_I2C=y
|
||||
|
@ -140,6 +143,8 @@ CONFIG_DM_REGULATOR_SANDBOX=y
|
|||
CONFIG_REGULATOR_TPS65090=y
|
||||
CONFIG_RAM=y
|
||||
CONFIG_REMOTEPROC_SANDBOX=y
|
||||
CONFIG_DM_RESET=y
|
||||
CONFIG_SANDBOX_RESET=y
|
||||
CONFIG_DM_RTC=y
|
||||
CONFIG_SANDBOX_SERIAL=y
|
||||
CONFIG_SOUND=y
|
||||
|
@ -170,6 +175,3 @@ CONFIG_UNIT_TEST=y
|
|||
CONFIG_UT_TIME=y
|
||||
CONFIG_UT_DM=y
|
||||
CONFIG_UT_ENV=y
|
||||
CONFIG_MISC=y
|
||||
CONFIG_DM_MAILBOX=y
|
||||
CONFIG_SANDBOX_MBOX=y
|
||||
|
|
75
doc/device-tree-bindings/reset/reset.txt
Normal file
75
doc/device-tree-bindings/reset/reset.txt
Normal file
|
@ -0,0 +1,75 @@
|
|||
= Reset Signal Device Tree Bindings =
|
||||
|
||||
This binding is intended to represent the hardware reset signals present
|
||||
internally in most IC (SoC, FPGA, ...) designs. Reset signals for whole
|
||||
standalone chips are most likely better represented as GPIOs, although there
|
||||
are likely to be exceptions to this rule.
|
||||
|
||||
Hardware blocks typically receive a reset signal. This signal is generated by
|
||||
a reset provider (e.g. power management or clock module) and received by a
|
||||
reset consumer (the module being reset, or a module managing when a sub-
|
||||
ordinate module is reset). This binding exists to represent the provider and
|
||||
consumer, and provide a way to couple the two together.
|
||||
|
||||
A reset signal is represented by the phandle of the provider, plus a reset
|
||||
specifier - a list of DT cells that represents the reset signal within the
|
||||
provider. The length (number of cells) and semantics of the reset specifier
|
||||
are dictated by the binding of the reset provider, although common schemes
|
||||
are described below.
|
||||
|
||||
A word on where to place reset signal consumers in device tree: It is possible
|
||||
in hardware for a reset signal to affect multiple logically separate HW blocks
|
||||
at once. In this case, it would be unwise to represent this reset signal in
|
||||
the DT node of each affected HW block, since if activated, an unrelated block
|
||||
may be reset. Instead, reset signals should be represented in the DT node
|
||||
where it makes most sense to control it; this may be a bus node if all
|
||||
children of the bus are affected by the reset signal, or an individual HW
|
||||
block node for dedicated reset signals. The intent of this binding is to give
|
||||
appropriate software access to the reset signals in order to manage the HW,
|
||||
rather than to slavishly enumerate the reset signal that affects each HW
|
||||
block.
|
||||
|
||||
= Reset providers =
|
||||
|
||||
Required properties:
|
||||
#reset-cells: Number of cells in a reset specifier; Typically 0 for nodes
|
||||
with a single reset output and 1 for nodes with multiple
|
||||
reset outputs.
|
||||
|
||||
For example:
|
||||
|
||||
rst: reset-controller {
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
= Reset consumers =
|
||||
|
||||
Required properties:
|
||||
resets: List of phandle and reset specifier pairs, one pair
|
||||
for each reset signal that affects the device, or that the
|
||||
device manages. Note: if the reset provider specifies '0' for
|
||||
#reset-cells, then only the phandle portion of the pair will
|
||||
appear.
|
||||
|
||||
Optional properties:
|
||||
reset-names: List of reset signal name strings sorted in the same order as
|
||||
the resets property. Consumers drivers will use reset-names to
|
||||
match reset signal names with reset specifiers.
|
||||
|
||||
For example:
|
||||
|
||||
device {
|
||||
resets = <&rst 20>;
|
||||
reset-names = "reset";
|
||||
};
|
||||
|
||||
This represents a device with a single reset signal named "reset".
|
||||
|
||||
bus {
|
||||
resets = <&rst 10> <&rst 11> <&rst 12> <&rst 11>;
|
||||
reset-names = "i2s1", "i2s2", "dma", "mixer";
|
||||
};
|
||||
|
||||
This represents a bus that controls the reset signal of each of four sub-
|
||||
ordinate devices. Consider for example a bus that fails to operate unless no
|
||||
child device has reset asserted.
|
|
@ -56,6 +56,8 @@ source "drivers/ram/Kconfig"
|
|||
|
||||
source "drivers/remoteproc/Kconfig"
|
||||
|
||||
source "drivers/reset/Kconfig"
|
||||
|
||||
source "drivers/rtc/Kconfig"
|
||||
|
||||
source "drivers/serial/Kconfig"
|
||||
|
|
|
@ -68,6 +68,7 @@ obj-$(CONFIG_U_QE) += qe/
|
|||
obj-y += mailbox/
|
||||
obj-y += memory/
|
||||
obj-y += pwm/
|
||||
obj-y += reset/
|
||||
obj-y += input/
|
||||
# SOC specific infrastructure drivers.
|
||||
obj-y += soc/
|
||||
|
|
|
@ -9,6 +9,7 @@ obj-$(CONFIG_CLK) += clk-uclass.o clk_fixed_rate.o
|
|||
obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
|
||||
obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
|
||||
obj-$(CONFIG_SANDBOX) += clk_sandbox.o
|
||||
obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
|
||||
obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
|
||||
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_CLK_EXYNOS) += exynos/
|
||||
|
|
|
@ -1,91 +1,78 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/root.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
ulong clk_get_rate(struct udevice *dev)
|
||||
static inline struct clk_ops *clk_dev_ops(struct udevice *dev)
|
||||
{
|
||||
struct clk_ops *ops = clk_get_ops(dev);
|
||||
|
||||
if (!ops->get_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->get_rate(dev);
|
||||
}
|
||||
|
||||
ulong clk_set_rate(struct udevice *dev, ulong rate)
|
||||
{
|
||||
struct clk_ops *ops = clk_get_ops(dev);
|
||||
|
||||
if (!ops->set_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->set_rate(dev, rate);
|
||||
}
|
||||
|
||||
int clk_enable(struct udevice *dev, int periph)
|
||||
{
|
||||
struct clk_ops *ops = clk_get_ops(dev);
|
||||
|
||||
if (!ops->enable)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->enable(dev, periph);
|
||||
}
|
||||
|
||||
ulong clk_get_periph_rate(struct udevice *dev, int periph)
|
||||
{
|
||||
struct clk_ops *ops = clk_get_ops(dev);
|
||||
|
||||
if (!ops->get_periph_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->get_periph_rate(dev, periph);
|
||||
}
|
||||
|
||||
ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
||||
{
|
||||
struct clk_ops *ops = clk_get_ops(dev);
|
||||
|
||||
if (!ops->set_periph_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->set_periph_rate(dev, periph, rate);
|
||||
return (struct clk_ops *)dev->driver->ops;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp)
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
|
||||
{
|
||||
int ret;
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
u32 cell[2];
|
||||
|
||||
if (index != 0)
|
||||
return -ENOSYS;
|
||||
assert(*clk_devp);
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, clk_devp);
|
||||
assert(clk);
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clocks",
|
||||
cell, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
return cell[1];
|
||||
#else
|
||||
struct fdtdec_phandle_args args;
|
||||
clk->id = cell[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(*clk_devp);
|
||||
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#else
|
||||
static int clk_of_xlate_default(struct clk *clk,
|
||||
struct fdtdec_phandle_args *args)
|
||||
{
|
||||
debug("%s(clk=%p)\n", __func__, clk);
|
||||
|
||||
if (args->args_count > 1) {
|
||||
debug("Invaild args_count: %d\n", args->args_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (args->args_count)
|
||||
clk->id = args->args[0];
|
||||
else
|
||||
clk->id = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
|
||||
{
|
||||
int ret;
|
||||
struct fdtdec_phandle_args args;
|
||||
struct udevice *dev_clk;
|
||||
struct clk_ops *ops;
|
||||
|
||||
debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
|
||||
|
||||
assert(clk);
|
||||
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
|
||||
"clocks", "#clock-cells", 0, index,
|
||||
&args);
|
||||
|
@ -95,16 +82,117 @@ int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp);
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev_clk);
|
||||
if (ret) {
|
||||
debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
return args.args_count > 0 ? args.args[0] : 0;
|
||||
#endif
|
||||
ops = clk_dev_ops(dev_clk);
|
||||
|
||||
if (ops->of_xlate)
|
||||
ret = ops->of_xlate(clk, &args);
|
||||
else
|
||||
ret = clk_of_xlate_default(clk, &args);
|
||||
if (ret) {
|
||||
debug("of_xlate() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return clk_request(dev_clk, clk);
|
||||
}
|
||||
|
||||
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
|
||||
{
|
||||
int index;
|
||||
|
||||
debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
|
||||
|
||||
index = fdt_find_string(gd->fdt_blob, dev->of_offset, "clock-names",
|
||||
name);
|
||||
if (index < 0) {
|
||||
debug("fdt_find_string() failed: %d\n", index);
|
||||
return index;
|
||||
}
|
||||
|
||||
return clk_get_by_index(dev, index, clk);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int clk_request(struct udevice *dev, struct clk *clk)
|
||||
{
|
||||
struct clk_ops *ops = clk_dev_ops(dev);
|
||||
|
||||
debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
|
||||
|
||||
clk->dev = dev;
|
||||
|
||||
if (!ops->request)
|
||||
return 0;
|
||||
|
||||
return ops->request(clk);
|
||||
}
|
||||
|
||||
int clk_free(struct clk *clk)
|
||||
{
|
||||
struct clk_ops *ops = clk_dev_ops(clk->dev);
|
||||
|
||||
debug("%s(clk=%p)\n", __func__, clk);
|
||||
|
||||
if (!ops->free)
|
||||
return 0;
|
||||
|
||||
return ops->free(clk);
|
||||
}
|
||||
|
||||
ulong clk_get_rate(struct clk *clk)
|
||||
{
|
||||
struct clk_ops *ops = clk_dev_ops(clk->dev);
|
||||
|
||||
debug("%s(clk=%p)\n", __func__, clk);
|
||||
|
||||
if (!ops->get_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->get_rate(clk);
|
||||
}
|
||||
|
||||
ulong clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct clk_ops *ops = clk_dev_ops(clk->dev);
|
||||
|
||||
debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
|
||||
|
||||
if (!ops->set_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->set_rate(clk, rate);
|
||||
}
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
struct clk_ops *ops = clk_dev_ops(clk->dev);
|
||||
|
||||
debug("%s(clk=%p)\n", __func__, clk);
|
||||
|
||||
if (!ops->enable)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->enable(clk);
|
||||
}
|
||||
|
||||
int clk_disable(struct clk *clk)
|
||||
{
|
||||
struct clk_ops *ops = clk_dev_ops(clk->dev);
|
||||
|
||||
debug("%s(clk=%p)\n", __func__, clk);
|
||||
|
||||
if (!ops->disable)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->disable(clk);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(clk) = {
|
||||
.id = UCLASS_CLK,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
@ -16,19 +16,16 @@ struct clk_fixed_rate {
|
|||
|
||||
#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev))
|
||||
|
||||
static ulong clk_fixed_rate_get_rate(struct udevice *dev)
|
||||
static ulong clk_fixed_rate_get_rate(struct clk *clk)
|
||||
{
|
||||
return to_clk_fixed_rate(dev)->fixed_rate;
|
||||
}
|
||||
if (clk->id != 0)
|
||||
return -EINVAL;
|
||||
|
||||
static ulong clk_fixed_rate_get_periph_rate(struct udevice *dev, int periph)
|
||||
{
|
||||
return clk_fixed_rate_get_rate(dev);
|
||||
return to_clk_fixed_rate(clk->dev)->fixed_rate;
|
||||
}
|
||||
|
||||
const struct clk_ops clk_fixed_rate_ops = {
|
||||
.get_rate = clk_fixed_rate_get_rate,
|
||||
.get_periph_rate = clk_fixed_rate_get_periph_rate,
|
||||
};
|
||||
|
||||
static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <div64.h>
|
||||
#include <wait_bit.h>
|
||||
|
@ -339,24 +339,17 @@ static void pic32_clk_init(struct udevice *dev)
|
|||
pic32_mpll_init(priv);
|
||||
}
|
||||
|
||||
static ulong pic32_clk_get_rate(struct udevice *dev)
|
||||
static ulong pic32_get_rate(struct clk *clk)
|
||||
{
|
||||
struct pic32_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return pic32_get_cpuclk(priv);
|
||||
}
|
||||
|
||||
static ulong pic32_get_periph_rate(struct udevice *dev, int periph)
|
||||
{
|
||||
struct pic32_clk_priv *priv = dev_get_priv(dev);
|
||||
struct pic32_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
ulong rate;
|
||||
|
||||
switch (periph) {
|
||||
switch (clk->id) {
|
||||
case PB1CLK ... PB7CLK:
|
||||
rate = pic32_get_pbclk(priv, periph);
|
||||
rate = pic32_get_pbclk(priv, clk->id);
|
||||
break;
|
||||
case REF1CLK ... REF5CLK:
|
||||
rate = pic32_get_refclk(priv, periph);
|
||||
rate = pic32_get_refclk(priv, clk->id);
|
||||
break;
|
||||
case PLLCLK:
|
||||
rate = pic32_get_pll_rate(priv);
|
||||
|
@ -372,15 +365,15 @@ static ulong pic32_get_periph_rate(struct udevice *dev, int periph)
|
|||
return rate;
|
||||
}
|
||||
|
||||
static ulong pic32_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
||||
static ulong pic32_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct pic32_clk_priv *priv = dev_get_priv(dev);
|
||||
struct pic32_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
ulong pll_hz;
|
||||
|
||||
switch (periph) {
|
||||
switch (clk->id) {
|
||||
case REF1CLK ... REF5CLK:
|
||||
pll_hz = pic32_get_pll_rate(priv);
|
||||
pic32_set_refclk(priv, periph, pll_hz, rate, ROCLK_SRC_SPLL);
|
||||
pic32_set_refclk(priv, clk->id, pll_hz, rate, ROCLK_SRC_SPLL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -390,9 +383,8 @@ static ulong pic32_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
|||
}
|
||||
|
||||
static struct clk_ops pic32_pic32_clk_ops = {
|
||||
.get_rate = pic32_clk_get_rate,
|
||||
.set_periph_rate = pic32_set_periph_rate,
|
||||
.get_periph_rate = pic32_get_periph_rate,
|
||||
.set_rate = pic32_set_rate,
|
||||
.get_rate = pic32_get_rate,
|
||||
};
|
||||
|
||||
static int pic32_clk_probe(struct udevice *dev)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <syscon.h>
|
||||
|
@ -18,10 +18,6 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct rk3036_clk_plat {
|
||||
enum rk_clk_id clk_id;
|
||||
};
|
||||
|
||||
struct rk3036_clk_priv {
|
||||
struct rk3036_cru *cru;
|
||||
ulong rate;
|
||||
|
@ -315,31 +311,30 @@ static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate,
|
|||
return rockchip_mmc_get_clk(cru, clk_general_rate, periph);
|
||||
}
|
||||
|
||||
static ulong rk3036_clk_get_rate(struct udevice *dev)
|
||||
static ulong rk3036_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
struct rk3036_clk_plat *plat = dev_get_platdata(dev);
|
||||
struct rk3036_clk_priv *priv = dev_get_priv(dev);
|
||||
struct rk3036_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
debug("%s\n", dev->name);
|
||||
return rkclk_pll_get_rate(priv->cru, plat->clk_id);
|
||||
switch (clk->id) {
|
||||
case 0 ... 63:
|
||||
return rkclk_pll_get_rate(priv->cru, clk->id);
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
static ulong rk3036_clk_set_rate(struct udevice *dev, ulong rate)
|
||||
static ulong rk3036_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
debug("%s\n", dev->name);
|
||||
struct rk3036_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
ulong new_rate, gclk_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
||||
{
|
||||
struct rk3036_clk_priv *priv = dev_get_priv(dev);
|
||||
ulong new_rate;
|
||||
|
||||
switch (periph) {
|
||||
gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
|
||||
switch (clk->id) {
|
||||
case 0 ... 63:
|
||||
return 0;
|
||||
case HCLK_EMMC:
|
||||
new_rate = rockchip_mmc_set_clk(priv->cru, clk_get_rate(dev),
|
||||
periph, rate);
|
||||
new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate,
|
||||
clk->id, rate);
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
|
@ -351,60 +346,21 @@ static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
|||
static struct clk_ops rk3036_clk_ops = {
|
||||
.get_rate = rk3036_clk_get_rate,
|
||||
.set_rate = rk3036_clk_set_rate,
|
||||
.set_periph_rate = rk3036_set_periph_rate,
|
||||
};
|
||||
|
||||
static int rk3036_clk_probe(struct udevice *dev)
|
||||
{
|
||||
struct rk3036_clk_plat *plat = dev_get_platdata(dev);
|
||||
struct rk3036_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (plat->clk_id != CLK_OSC) {
|
||||
struct rk3036_clk_priv *parent_priv = dev_get_priv(dev->parent);
|
||||
|
||||
priv->cru = parent_priv->cru;
|
||||
return 0;
|
||||
}
|
||||
priv->cru = (struct rk3036_cru *)dev_get_addr(dev);
|
||||
rkclk_init(priv->cru);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const clk_name[] = {
|
||||
"osc",
|
||||
"apll",
|
||||
"dpll",
|
||||
"cpll",
|
||||
"gpll",
|
||||
"mpll",
|
||||
};
|
||||
|
||||
static int rk3036_clk_bind(struct udevice *dev)
|
||||
{
|
||||
struct rk3036_clk_plat *plat = dev_get_platdata(dev);
|
||||
int pll, ret;
|
||||
|
||||
/* We only need to set up the root clock */
|
||||
if (dev->of_offset == -1) {
|
||||
plat->clk_id = CLK_OSC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create devices for P main clocks */
|
||||
for (pll = 1; pll < CLK_COUNT; pll++) {
|
||||
struct udevice *child;
|
||||
struct rk3036_clk_plat *cplat;
|
||||
|
||||
debug("%s %s\n", __func__, clk_name[pll]);
|
||||
ret = device_bind_driver(dev, "clk_rk3036", clk_name[pll],
|
||||
&child);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cplat = dev_get_platdata(child);
|
||||
cplat->clk_id = pll;
|
||||
}
|
||||
int ret;
|
||||
|
||||
/* The reset driver does not have a device node, so bind it here */
|
||||
ret = device_bind_driver(gd->dm_root, "rk3036_sysreset", "reset", &dev);
|
||||
|
@ -424,7 +380,6 @@ U_BOOT_DRIVER(clk_rk3036) = {
|
|||
.id = UCLASS_CLK,
|
||||
.of_match = rk3036_clk_ids,
|
||||
.priv_auto_alloc_size = sizeof(struct rk3036_clk_priv),
|
||||
.platdata_auto_alloc_size = sizeof(struct rk3036_clk_plat),
|
||||
.ops = &rk3036_clk_ops,
|
||||
.bind = rk3036_clk_bind,
|
||||
.probe = rk3036_clk_probe,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <syscon.h>
|
||||
|
@ -21,10 +21,6 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct rk3288_clk_plat {
|
||||
enum rk_clk_id clk_id;
|
||||
};
|
||||
|
||||
struct rk3288_clk_priv {
|
||||
struct rk3288_grf *grf;
|
||||
struct rk3288_cru *cru;
|
||||
|
@ -135,34 +131,18 @@ static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 1);
|
|||
static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
|
||||
static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
|
||||
|
||||
int rkclk_get_clk(enum rk_clk_id clk_id, struct udevice **devp)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
||||
for (uclass_find_first_device(UCLASS_CLK, &dev);
|
||||
dev;
|
||||
uclass_find_next_device(&dev)) {
|
||||
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
|
||||
|
||||
if (plat->clk_id == clk_id) {
|
||||
*devp = dev;
|
||||
return device_probe(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void *rockchip_get_cru(void)
|
||||
{
|
||||
struct rk3288_clk_priv *priv;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = rkclk_get_clk(CLK_GENERAL, &dev);
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
priv = dev_get_priv(dev);
|
||||
|
||||
return priv->cru;
|
||||
}
|
||||
|
||||
|
@ -539,32 +519,6 @@ static uint32_t rkclk_pll_get_rate(struct rk3288_cru *cru,
|
|||
}
|
||||
}
|
||||
|
||||
static ulong rk3288_clk_get_rate(struct udevice *dev)
|
||||
{
|
||||
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
|
||||
struct rk3288_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
debug("%s\n", dev->name);
|
||||
return rkclk_pll_get_rate(priv->cru, plat->clk_id);
|
||||
}
|
||||
|
||||
static ulong rk3288_clk_set_rate(struct udevice *dev, ulong rate)
|
||||
{
|
||||
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
|
||||
struct rk3288_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
debug("%s\n", dev->name);
|
||||
switch (plat->clk_id) {
|
||||
case CLK_DDR:
|
||||
rkclk_configure_ddr(priv->cru, priv->grf, rate);
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint gclk_rate,
|
||||
int periph)
|
||||
{
|
||||
|
@ -710,27 +664,25 @@ static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint gclk_rate,
|
|||
return rockchip_spi_get_clk(cru, gclk_rate, periph);
|
||||
}
|
||||
|
||||
static ulong rk3288_get_periph_rate(struct udevice *dev, int periph)
|
||||
static ulong rk3288_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
struct rk3288_clk_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *gclk;
|
||||
struct rk3288_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
ulong new_rate, gclk_rate;
|
||||
int ret;
|
||||
|
||||
ret = rkclk_get_clk(CLK_GENERAL, &gclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
gclk_rate = clk_get_rate(gclk);
|
||||
switch (periph) {
|
||||
gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
|
||||
switch (clk->id) {
|
||||
case 0 ... 63:
|
||||
new_rate = rkclk_pll_get_rate(priv->cru, clk->id);
|
||||
break;
|
||||
case HCLK_EMMC:
|
||||
case HCLK_SDMMC:
|
||||
case HCLK_SDIO0:
|
||||
new_rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, periph);
|
||||
new_rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, clk->id);
|
||||
break;
|
||||
case SCLK_SPI0:
|
||||
case SCLK_SPI1:
|
||||
case SCLK_SPI2:
|
||||
new_rate = rockchip_spi_get_clk(priv->cru, gclk_rate, periph);
|
||||
new_rate = rockchip_spi_get_clk(priv->cru, gclk_rate, clk->id);
|
||||
break;
|
||||
case PCLK_I2C0:
|
||||
case PCLK_I2C1:
|
||||
|
@ -746,36 +698,34 @@ static ulong rk3288_get_periph_rate(struct udevice *dev, int periph)
|
|||
return new_rate;
|
||||
}
|
||||
|
||||
static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
||||
static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct rk3288_clk_priv *priv = dev_get_priv(dev);
|
||||
struct rk3288_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
struct rk3288_cru *cru = priv->cru;
|
||||
struct udevice *gclk;
|
||||
ulong new_rate, gclk_rate;
|
||||
int ret;
|
||||
|
||||
ret = rkclk_get_clk(CLK_GENERAL, &gclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
gclk_rate = clk_get_rate(gclk);
|
||||
switch (periph) {
|
||||
gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
|
||||
switch (clk->id) {
|
||||
case CLK_DDR:
|
||||
new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate);
|
||||
break;
|
||||
case HCLK_EMMC:
|
||||
case HCLK_SDMMC:
|
||||
case HCLK_SDIO0:
|
||||
new_rate = rockchip_mmc_set_clk(cru, gclk_rate, periph, rate);
|
||||
new_rate = rockchip_mmc_set_clk(cru, gclk_rate, clk->id, rate);
|
||||
break;
|
||||
case SCLK_SPI0:
|
||||
case SCLK_SPI1:
|
||||
case SCLK_SPI2:
|
||||
new_rate = rockchip_spi_set_clk(cru, gclk_rate, periph, rate);
|
||||
new_rate = rockchip_spi_set_clk(cru, gclk_rate, clk->id, rate);
|
||||
break;
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
case SCLK_MAC:
|
||||
new_rate = rockchip_mac_set_clk(priv->cru, periph, rate);
|
||||
new_rate = rockchip_mac_set_clk(priv->cru, clk->id, rate);
|
||||
break;
|
||||
case DCLK_VOP0:
|
||||
case DCLK_VOP1:
|
||||
new_rate = rockchip_vop_set_clk(cru, priv->grf, periph, rate);
|
||||
new_rate = rockchip_vop_set_clk(cru, priv->grf, clk->id, rate);
|
||||
break;
|
||||
case SCLK_EDP_24M:
|
||||
/* clk_edp_24M source: 24M */
|
||||
|
@ -795,7 +745,7 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
|||
div = CPLL_HZ / rate;
|
||||
assert((div - 1 < 64) && (div * rate == CPLL_HZ));
|
||||
|
||||
switch (periph) {
|
||||
switch (clk->id) {
|
||||
case ACLK_VOP0:
|
||||
rk_clrsetreg(&cru->cru_clksel_con[31],
|
||||
3 << 6 | 0x1f << 0,
|
||||
|
@ -831,22 +781,12 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
|
|||
static struct clk_ops rk3288_clk_ops = {
|
||||
.get_rate = rk3288_clk_get_rate,
|
||||
.set_rate = rk3288_clk_set_rate,
|
||||
.set_periph_rate = rk3288_set_periph_rate,
|
||||
.get_periph_rate = rk3288_get_periph_rate,
|
||||
};
|
||||
|
||||
static int rk3288_clk_probe(struct udevice *dev)
|
||||
{
|
||||
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
|
||||
struct rk3288_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (plat->clk_id != CLK_OSC) {
|
||||
struct rk3288_clk_priv *parent_priv = dev_get_priv(dev->parent);
|
||||
|
||||
priv->cru = parent_priv->cru;
|
||||
priv->grf = parent_priv->grf;
|
||||
return 0;
|
||||
}
|
||||
priv->cru = (struct rk3288_cru *)dev_get_addr(dev);
|
||||
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
|
@ -856,39 +796,9 @@ static int rk3288_clk_probe(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char *const clk_name[CLK_COUNT] = {
|
||||
"osc",
|
||||
"apll",
|
||||
"dpll",
|
||||
"cpll",
|
||||
"gpll",
|
||||
"npll",
|
||||
};
|
||||
|
||||
static int rk3288_clk_bind(struct udevice *dev)
|
||||
{
|
||||
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
|
||||
int pll, ret;
|
||||
|
||||
/* We only need to set up the root clock */
|
||||
if (dev->of_offset == -1) {
|
||||
plat->clk_id = CLK_OSC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create devices for P main clocks */
|
||||
for (pll = 1; pll < CLK_COUNT; pll++) {
|
||||
struct udevice *child;
|
||||
struct rk3288_clk_plat *cplat;
|
||||
|
||||
debug("%s %s\n", __func__, clk_name[pll]);
|
||||
ret = device_bind_driver(dev, "clk_rk3288", clk_name[pll],
|
||||
&child);
|
||||
if (ret)
|
||||
return ret;
|
||||
cplat = dev_get_platdata(child);
|
||||
cplat->clk_id = pll;
|
||||
}
|
||||
int ret;
|
||||
|
||||
/* The reset driver does not have a device node, so bind it here */
|
||||
ret = device_bind_driver(gd->dm_root, "rk3288_sysreset", "reset", &dev);
|
||||
|
@ -908,7 +818,6 @@ U_BOOT_DRIVER(clk_rk3288) = {
|
|||
.id = UCLASS_CLK,
|
||||
.of_match = rk3288_clk_ids,
|
||||
.priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
|
||||
.platdata_auto_alloc_size = sizeof(struct rk3288_clk_plat),
|
||||
.ops = &rk3288_clk_ops,
|
||||
.bind = rk3288_clk_bind,
|
||||
.probe = rk3288_clk_probe,
|
||||
|
|
|
@ -5,61 +5,63 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <asm/test.h>
|
||||
#include <asm/clk.h>
|
||||
|
||||
struct sandbox_clk_priv {
|
||||
ulong rate;
|
||||
ulong periph_rate[PERIPH_ID_COUNT];
|
||||
ulong rate[SANDBOX_CLK_ID_COUNT];
|
||||
bool enabled[SANDBOX_CLK_ID_COUNT];
|
||||
};
|
||||
|
||||
static ulong sandbox_clk_get_rate(struct udevice *dev)
|
||||
static ulong sandbox_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
return priv->rate;
|
||||
if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return priv->rate[clk->id];
|
||||
}
|
||||
|
||||
static ulong sandbox_clk_set_rate(struct udevice *dev, ulong rate)
|
||||
static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
ulong old_rate;
|
||||
|
||||
if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
priv->rate = rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong sandbox_get_periph_rate(struct udevice *dev, int periph)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT)
|
||||
return -EINVAL;
|
||||
return priv->periph_rate[periph];
|
||||
}
|
||||
|
||||
static ulong sandbox_set_periph_rate(struct udevice *dev, int periph,
|
||||
ulong rate)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
||||
ulong old_rate;
|
||||
|
||||
if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT)
|
||||
return -EINVAL;
|
||||
old_rate = priv->periph_rate[periph];
|
||||
priv->periph_rate[periph] = rate;
|
||||
old_rate = priv->rate[clk->id];
|
||||
priv->rate[clk->id] = rate;
|
||||
|
||||
return old_rate;
|
||||
}
|
||||
|
||||
static int sandbox_clk_probe(struct udevice *dev)
|
||||
static int sandbox_clk_enable(struct clk *clk)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
priv->rate = SANDBOX_CLK_RATE;
|
||||
if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
priv->enabled[clk->id] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_clk_disable(struct clk *clk)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
priv->enabled[clk->id] = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -67,8 +69,8 @@ static int sandbox_clk_probe(struct udevice *dev)
|
|||
static struct clk_ops sandbox_clk_ops = {
|
||||
.get_rate = sandbox_clk_get_rate,
|
||||
.set_rate = sandbox_clk_set_rate,
|
||||
.get_periph_rate = sandbox_get_periph_rate,
|
||||
.set_periph_rate = sandbox_set_periph_rate,
|
||||
.enable = sandbox_clk_enable,
|
||||
.disable = sandbox_clk_disable,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_clk_ids[] = {
|
||||
|
@ -82,5 +84,24 @@ U_BOOT_DRIVER(clk_sandbox) = {
|
|||
.of_match = sandbox_clk_ids,
|
||||
.ops = &sandbox_clk_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_clk_priv),
|
||||
.probe = sandbox_clk_probe,
|
||||
};
|
||||
|
||||
ulong sandbox_clk_query_rate(struct udevice *dev, int id)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return priv->rate[id];
|
||||
}
|
||||
|
||||
int sandbox_clk_query_enable(struct udevice *dev, int id)
|
||||
{
|
||||
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return priv->enabled[id];
|
||||
}
|
||||
|
|
101
drivers/clk/clk_sandbox_test.c
Normal file
101
drivers/clk/clk_sandbox_test.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <clk.h>
|
||||
#include <asm/clk.h>
|
||||
|
||||
struct sandbox_clk_test {
|
||||
struct clk clks[SANDBOX_CLK_TEST_ID_COUNT];
|
||||
};
|
||||
|
||||
static const char * const sandbox_clk_test_names[] = {
|
||||
[SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
|
||||
[SANDBOX_CLK_TEST_ID_SPI] = "spi",
|
||||
[SANDBOX_CLK_TEST_ID_I2C] = "i2c",
|
||||
};
|
||||
|
||||
int sandbox_clk_test_get(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_clk_test *sbct = dev_get_priv(dev);
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
|
||||
ret = clk_get_by_name(dev, sandbox_clk_test_names[i],
|
||||
&sbct->clks[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulong sandbox_clk_test_get_rate(struct udevice *dev, int id)
|
||||
{
|
||||
struct sandbox_clk_test *sbct = dev_get_priv(dev);
|
||||
|
||||
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return clk_get_rate(&sbct->clks[id]);
|
||||
}
|
||||
|
||||
ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate)
|
||||
{
|
||||
struct sandbox_clk_test *sbct = dev_get_priv(dev);
|
||||
|
||||
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return clk_set_rate(&sbct->clks[id], rate);
|
||||
}
|
||||
|
||||
int sandbox_clk_test_enable(struct udevice *dev, int id)
|
||||
{
|
||||
struct sandbox_clk_test *sbct = dev_get_priv(dev);
|
||||
|
||||
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return clk_enable(&sbct->clks[id]);
|
||||
}
|
||||
|
||||
int sandbox_clk_test_disable(struct udevice *dev, int id)
|
||||
{
|
||||
struct sandbox_clk_test *sbct = dev_get_priv(dev);
|
||||
|
||||
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return clk_disable(&sbct->clks[id]);
|
||||
}
|
||||
|
||||
int sandbox_clk_test_free(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_clk_test *sbct = dev_get_priv(dev);
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
|
||||
ret = clk_free(&sbct->clks[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id sandbox_clk_test_ids[] = {
|
||||
{ .compatible = "sandbox,clk-test" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_clk_test) = {
|
||||
.name = "sandbox_clk_test",
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = sandbox_clk_test_ids,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_clk_test),
|
||||
};
|
|
@ -9,7 +9,7 @@
|
|||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <asm/io.h>
|
||||
#include <dt-bindings/clock/exynos7420-clk.h>
|
||||
#include "clk-pll.h"
|
||||
|
@ -67,11 +67,11 @@ struct exynos7420_clk_top0_priv {
|
|||
unsigned long sclk_uart2;
|
||||
};
|
||||
|
||||
static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph)
|
||||
static ulong exynos7420_topc_get_rate(struct clk *clk)
|
||||
{
|
||||
struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev);
|
||||
struct exynos7420_clk_topc_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
switch (periph) {
|
||||
switch (clk->id) {
|
||||
case DOUT_SCLK_BUS0_PLL:
|
||||
case SCLK_BUS0_PLL_A:
|
||||
case SCLK_BUS0_PLL_B:
|
||||
|
@ -86,14 +86,14 @@ static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph)
|
|||
}
|
||||
|
||||
static struct clk_ops exynos7420_clk_topc_ops = {
|
||||
.get_periph_rate = exynos7420_topc_get_periph_rate,
|
||||
.get_rate = exynos7420_topc_get_rate,
|
||||
};
|
||||
|
||||
static int exynos7420_clk_topc_probe(struct udevice *dev)
|
||||
{
|
||||
struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev);
|
||||
struct exynos7420_clk_cmu_topc *topc;
|
||||
struct udevice *clk_dev;
|
||||
struct clk in_clk;
|
||||
unsigned long rate;
|
||||
fdt_addr_t base;
|
||||
int ret;
|
||||
|
@ -105,9 +105,9 @@ static int exynos7420_clk_topc_probe(struct udevice *dev)
|
|||
topc = (struct exynos7420_clk_cmu_topc *)base;
|
||||
priv->topc = topc;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk_dev);
|
||||
ret = clk_get_by_index(dev, 0, &in_clk);
|
||||
if (ret >= 0)
|
||||
priv->fin_freq = clk_get_rate(clk_dev);
|
||||
priv->fin_freq = clk_get_rate(&in_clk);
|
||||
|
||||
rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq);
|
||||
if (readl(&topc->mux_sel[1]) & (1 << 16))
|
||||
|
@ -122,12 +122,12 @@ static int exynos7420_clk_topc_probe(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph)
|
||||
static ulong exynos7420_top0_get_rate(struct clk *clk)
|
||||
{
|
||||
struct exynos7420_clk_top0_priv *priv = dev_get_priv(dev);
|
||||
struct exynos7420_clk_top0_priv *priv = dev_get_priv(clk->dev);
|
||||
struct exynos7420_clk_cmu_top0 *top0 = priv->top0;
|
||||
|
||||
switch (periph) {
|
||||
switch (clk->id) {
|
||||
case CLK_SCLK_UART2:
|
||||
return priv->mout_top0_bus0_pll_half /
|
||||
DIVIDER(&top0->div_peric[3], 8, 0xf);
|
||||
|
@ -137,14 +137,14 @@ static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph)
|
|||
}
|
||||
|
||||
static struct clk_ops exynos7420_clk_top0_ops = {
|
||||
.get_periph_rate = exynos7420_top0_get_periph_rate,
|
||||
.get_rate = exynos7420_top0_get_rate,
|
||||
};
|
||||
|
||||
static int exynos7420_clk_top0_probe(struct udevice *dev)
|
||||
{
|
||||
struct exynos7420_clk_top0_priv *priv;
|
||||
struct exynos7420_clk_cmu_top0 *top0;
|
||||
struct udevice *clk_dev;
|
||||
struct clk in_clk;
|
||||
fdt_addr_t base;
|
||||
int ret;
|
||||
|
||||
|
@ -159,10 +159,10 @@ static int exynos7420_clk_top0_probe(struct udevice *dev)
|
|||
top0 = (struct exynos7420_clk_cmu_top0 *)base;
|
||||
priv->top0 = top0;
|
||||
|
||||
ret = clk_get_by_index(dev, 1, &clk_dev);
|
||||
ret = clk_get_by_index(dev, 1, &in_clk);
|
||||
if (ret >= 0) {
|
||||
priv->mout_top0_bus0_pll_half =
|
||||
clk_get_periph_rate(clk_dev, ret);
|
||||
clk_get_rate(&in_clk);
|
||||
if (readl(&top0->mux_sel[1]) & (1 << 16))
|
||||
priv->mout_top0_bus0_pll_half >>= 1;
|
||||
}
|
||||
|
@ -170,18 +170,18 @@ static int exynos7420_clk_top0_probe(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph)
|
||||
static ulong exynos7420_peric1_get_rate(struct clk *clk)
|
||||
{
|
||||
struct udevice *clk_dev;
|
||||
struct clk in_clk;
|
||||
unsigned int ret;
|
||||
unsigned long freq = 0;
|
||||
|
||||
switch (periph) {
|
||||
switch (clk->id) {
|
||||
case SCLK_UART2:
|
||||
ret = clk_get_by_index(dev, 3, &clk_dev);
|
||||
ret = clk_get_by_index(clk->dev, 3, &in_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
freq = clk_get_periph_rate(clk_dev, ret);
|
||||
freq = clk_get_rate(&in_clk);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph)
|
|||
}
|
||||
|
||||
static struct clk_ops exynos7420_clk_peric1_ops = {
|
||||
.get_periph_rate = exynos7420_peric1_get_periph_rate,
|
||||
.get_rate = exynos7420_peric1_get_rate,
|
||||
};
|
||||
|
||||
static const struct udevice_id exynos7420_clk_topc_compat[] = {
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <clk.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
#include "clk-uniphier.h"
|
||||
|
||||
static int uniphier_clk_enable(struct udevice *dev, int index)
|
||||
static int uniphier_clk_enable(struct clk *clk)
|
||||
{
|
||||
struct uniphier_clk_priv *priv = dev_get_priv(dev);
|
||||
struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
struct uniphier_clk_gate_data *gate = priv->socdata->gate;
|
||||
unsigned int nr_gate = priv->socdata->nr_gate;
|
||||
void __iomem *reg;
|
||||
|
@ -24,7 +24,7 @@ static int uniphier_clk_enable(struct udevice *dev, int index)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < nr_gate; i++) {
|
||||
if (gate[i].index != index)
|
||||
if (gate[i].index != clk->id)
|
||||
continue;
|
||||
|
||||
reg = priv->base + gate[i].reg;
|
||||
|
@ -41,9 +41,9 @@ static int uniphier_clk_enable(struct udevice *dev, int index)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ulong uniphier_clk_get_rate(struct udevice *dev, int index)
|
||||
static ulong uniphier_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
struct uniphier_clk_priv *priv = dev_get_priv(dev);
|
||||
struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
|
||||
unsigned int nr_rdata = priv->socdata->nr_rate;
|
||||
void __iomem *reg;
|
||||
|
@ -52,7 +52,7 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < nr_rdata; i++) {
|
||||
if (rdata[i].index != index)
|
||||
if (rdata[i].index != clk->id)
|
||||
continue;
|
||||
|
||||
if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
|
||||
|
@ -75,9 +75,9 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index)
|
|||
return matched_rate;
|
||||
}
|
||||
|
||||
static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
|
||||
static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct uniphier_clk_priv *priv = dev_get_priv(dev);
|
||||
struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
|
||||
unsigned int nr_rdata = priv->socdata->nr_rate;
|
||||
void __iomem *reg;
|
||||
|
@ -87,7 +87,7 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
|
|||
|
||||
/* first, decide the best match rate */
|
||||
for (i = 0; i < nr_rdata; i++) {
|
||||
if (rdata[i].index != index)
|
||||
if (rdata[i].index != clk->id)
|
||||
continue;
|
||||
|
||||
if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
|
||||
|
@ -105,7 +105,7 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
|
|||
|
||||
/* second, really set registers */
|
||||
for (i = 0; i < nr_rdata; i++) {
|
||||
if (rdata[i].index != index || rdata[i].rate != best_rate)
|
||||
if (rdata[i].index != clk->id || rdata[i].rate != best_rate)
|
||||
continue;
|
||||
|
||||
reg = priv->base + rdata[i].reg;
|
||||
|
@ -124,8 +124,8 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
|
|||
|
||||
const struct clk_ops uniphier_clk_ops = {
|
||||
.enable = uniphier_clk_enable,
|
||||
.get_periph_rate = uniphier_clk_get_rate,
|
||||
.set_periph_rate = uniphier_clk_set_rate,
|
||||
.get_rate = uniphier_clk_get_rate,
|
||||
.set_rate = uniphier_clk_set_rate,
|
||||
};
|
||||
|
||||
int uniphier_clk_probe(struct udevice *dev)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <clk.h>
|
||||
#include <dm/device.h>
|
||||
|
||||
#include "clk-uniphier.h"
|
||||
|
|
|
@ -122,6 +122,20 @@ void fix_uclass(void)
|
|||
entry->ops += gd->reloc_off;
|
||||
}
|
||||
}
|
||||
|
||||
void fix_devices(void)
|
||||
{
|
||||
struct driver_info *dev =
|
||||
ll_entry_start(struct driver_info, driver_info);
|
||||
const int n_ents = ll_entry_count(struct driver_info, driver_info);
|
||||
struct driver_info *entry;
|
||||
|
||||
for (entry = dev; entry != dev + n_ents; entry++) {
|
||||
if (entry->platdata)
|
||||
entry->platdata += gd->reloc_off;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int dm_init(void)
|
||||
|
@ -137,6 +151,7 @@ int dm_init(void)
|
|||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
fix_drivers();
|
||||
fix_uclass();
|
||||
fix_devices();
|
||||
#endif
|
||||
|
||||
ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
|
||||
|
|
|
@ -148,11 +148,13 @@ static int pca953x_get_value(struct udevice *dev, unsigned offset)
|
|||
int ret;
|
||||
u8 val = 0;
|
||||
|
||||
int off = offset % BANK_SZ;
|
||||
|
||||
ret = pca953x_read_single(dev, PCA953X_INPUT, &val, offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (val >> offset) & 0x1;
|
||||
return (val >> off) & 0x1;
|
||||
}
|
||||
|
||||
static int pca953x_set_value(struct udevice *dev, unsigned offset,
|
||||
|
|
|
@ -29,10 +29,9 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define RK_I2C_FIFO_SIZE 32
|
||||
|
||||
struct rk_i2c {
|
||||
struct udevice *clk;
|
||||
struct clk clk;
|
||||
struct i2c_regs *regs;
|
||||
unsigned int speed;
|
||||
int clk_id;
|
||||
};
|
||||
|
||||
static inline void rk_i2c_get_div(int div, int *divh, int *divl)
|
||||
|
@ -55,7 +54,7 @@ static void rk_i2c_set_clk(struct rk_i2c *i2c, uint32_t scl_rate)
|
|||
int div, divl, divh;
|
||||
|
||||
/* First get i2c rate from pclk */
|
||||
i2c_rate = clk_get_periph_rate(i2c->clk, i2c->clk_id);
|
||||
i2c_rate = clk_get_rate(&i2c->clk);
|
||||
|
||||
div = DIV_ROUND_UP(i2c_rate, scl_rate * 8) - 2;
|
||||
divh = 0;
|
||||
|
@ -362,7 +361,6 @@ static int rockchip_i2c_ofdata_to_platdata(struct udevice *bus)
|
|||
bus->name, ret);
|
||||
return ret;
|
||||
}
|
||||
priv->clk_id = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,4 +17,11 @@ config SANDBOX_MBOX
|
|||
Enable support for a test mailbox implementation, which simply echos
|
||||
back a modified version of any message that is sent.
|
||||
|
||||
config TEGRA_HSP
|
||||
bool "Enable Tegra HSP controller support"
|
||||
depends on DM_MAILBOX && TEGRA
|
||||
help
|
||||
This enables support for the NVIDIA Tegra HSP Hw module, which
|
||||
implements doorbells, mailboxes, semaphores, and shared interrupts.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
obj-$(CONFIG_DM_MAILBOX) += mailbox-uclass.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o
|
||||
obj-$(CONFIG_TEGRA_HSP) += tegra-hsp.o
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <mailbox_client.h>
|
||||
#include <mailbox_uclass.h>
|
||||
#include <mailbox.h>
|
||||
#include <mailbox-uclass.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <mailbox_client.h>
|
||||
#include <mailbox.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct sandbox_mbox_test {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <mailbox_uclass.h>
|
||||
#include <mailbox-uclass.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mbox.h>
|
||||
|
||||
|
|
163
drivers/mailbox/tegra-hsp.c
Normal file
163
drivers/mailbox/tegra-hsp.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm.h>
|
||||
#include <mailbox-uclass.h>
|
||||
#include <dt-bindings/mailbox/tegra-hsp.h>
|
||||
|
||||
#define TEGRA_HSP_DB_REG_TRIGGER 0x0
|
||||
#define TEGRA_HSP_DB_REG_ENABLE 0x4
|
||||
#define TEGRA_HSP_DB_REG_RAW 0x8
|
||||
#define TEGRA_HSP_DB_REG_PENDING 0xc
|
||||
|
||||
#define TEGRA_HSP_DB_ID_CCPLEX 1
|
||||
#define TEGRA_HSP_DB_ID_BPMP 3
|
||||
#define TEGRA_HSP_DB_ID_NUM 7
|
||||
|
||||
struct tegra_hsp {
|
||||
fdt_addr_t regs;
|
||||
uint32_t db_base;
|
||||
};
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static uint32_t *tegra_hsp_reg(struct tegra_hsp *thsp, uint32_t db_id,
|
||||
uint32_t reg)
|
||||
{
|
||||
return (uint32_t *)(thsp->regs + thsp->db_base + (db_id * 0x100) + reg);
|
||||
}
|
||||
|
||||
static uint32_t tegra_hsp_readl(struct tegra_hsp *thsp, uint32_t db_id,
|
||||
uint32_t reg)
|
||||
{
|
||||
uint32_t *r = tegra_hsp_reg(thsp, db_id, reg);
|
||||
return readl(r);
|
||||
}
|
||||
|
||||
static void tegra_hsp_writel(struct tegra_hsp *thsp, uint32_t val,
|
||||
uint32_t db_id, uint32_t reg)
|
||||
{
|
||||
uint32_t *r = tegra_hsp_reg(thsp, db_id, reg);
|
||||
|
||||
writel(val, r);
|
||||
readl(r);
|
||||
}
|
||||
|
||||
static int tegra_hsp_db_id(ulong chan_id)
|
||||
{
|
||||
switch (chan_id) {
|
||||
case TEGRA_HSP_MASTER_BPMP:
|
||||
return TEGRA_HSP_DB_ID_BPMP;
|
||||
default:
|
||||
debug("Invalid channel ID\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra_hsp_request(struct mbox_chan *chan)
|
||||
{
|
||||
int db_id;
|
||||
|
||||
debug("%s(chan=%p)\n", __func__, chan);
|
||||
|
||||
db_id = tegra_hsp_db_id(chan->id);
|
||||
if (db_id < 0) {
|
||||
debug("tegra_hsp_db_id() failed: %d\n", db_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_hsp_free(struct mbox_chan *chan)
|
||||
{
|
||||
debug("%s(chan=%p)\n", __func__, chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_hsp_send(struct mbox_chan *chan, const void *data)
|
||||
{
|
||||
struct tegra_hsp *thsp = dev_get_priv(chan->dev);
|
||||
int db_id;
|
||||
|
||||
debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
|
||||
|
||||
db_id = tegra_hsp_db_id(chan->id);
|
||||
tegra_hsp_writel(thsp, 1, db_id, TEGRA_HSP_DB_REG_TRIGGER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_hsp_recv(struct mbox_chan *chan, void *data)
|
||||
{
|
||||
struct tegra_hsp *thsp = dev_get_priv(chan->dev);
|
||||
uint32_t db_id = TEGRA_HSP_DB_ID_CCPLEX;
|
||||
uint32_t val;
|
||||
|
||||
debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
|
||||
|
||||
val = tegra_hsp_readl(thsp, db_id, TEGRA_HSP_DB_REG_RAW);
|
||||
if (!(val & BIT(chan->id)))
|
||||
return -ENODATA;
|
||||
|
||||
tegra_hsp_writel(thsp, BIT(chan->id), db_id, TEGRA_HSP_DB_REG_RAW);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_hsp_bind(struct udevice *dev)
|
||||
{
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_hsp_probe(struct udevice *dev)
|
||||
{
|
||||
struct tegra_hsp *thsp = dev_get_priv(dev);
|
||||
int nr_sm, nr_ss, nr_as;
|
||||
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
thsp->regs = dev_get_addr(dev);
|
||||
if (thsp->regs == FDT_ADDR_T_NONE)
|
||||
return -ENODEV;
|
||||
|
||||
nr_sm = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SM",
|
||||
0);
|
||||
nr_ss = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SS",
|
||||
0);
|
||||
nr_as = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-AS",
|
||||
0);
|
||||
thsp->db_base = (1 + (nr_sm >> 1) + nr_ss + nr_as) << 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id tegra_hsp_ids[] = {
|
||||
{ .compatible = "nvidia,tegra186-hsp" },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct mbox_ops tegra_hsp_mbox_ops = {
|
||||
.request = tegra_hsp_request,
|
||||
.free = tegra_hsp_free,
|
||||
.send = tegra_hsp_send,
|
||||
.recv = tegra_hsp_recv,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(tegra_hsp) = {
|
||||
.name = "tegra-hsp",
|
||||
.id = UCLASS_MAILBOX,
|
||||
.of_match = tegra_hsp_ids,
|
||||
.bind = tegra_hsp_bind,
|
||||
.probe = tegra_hsp_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct tegra_hsp),
|
||||
.ops = &tegra_hsp_mbox_ops,
|
||||
};
|
|
@ -49,7 +49,8 @@ static int msm_sdc_clk_init(struct udevice *dev)
|
|||
"clock-frequency", 400000);
|
||||
uint clkd[2]; /* clk_id and clk_no */
|
||||
int clk_offset;
|
||||
struct udevice *clk;
|
||||
struct udevice *clk_dev;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd,
|
||||
|
@ -61,11 +62,17 @@ static int msm_sdc_clk_init(struct udevice *dev)
|
|||
if (clk_offset < 0)
|
||||
return clk_offset;
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk);
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_set_periph_rate(clk, clkd[1], clk_rate);
|
||||
clk.id = clkd[1];
|
||||
ret = clk_request(clk_dev, &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_set_rate(&clk, clk_rate);
|
||||
clk_free(&clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -24,8 +24,7 @@ struct rockchip_mmc_plat {
|
|||
};
|
||||
|
||||
struct rockchip_dwmmc_priv {
|
||||
struct udevice *clk;
|
||||
int periph;
|
||||
struct clk clk;
|
||||
struct dwmci_host host;
|
||||
};
|
||||
|
||||
|
@ -35,7 +34,7 @@ static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
|
|||
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_set_periph_rate(priv->clk, priv->periph, freq);
|
||||
ret = clk_set_rate(&priv->clk, freq);
|
||||
if (ret < 0) {
|
||||
debug("%s: err=%d\n", __func__, ret);
|
||||
return ret;
|
||||
|
@ -81,7 +80,6 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
|
|||
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
priv->periph = ret;
|
||||
|
||||
if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
|
||||
"clock-freq-min-max", minmax, 2))
|
||||
|
|
|
@ -651,8 +651,7 @@ int uniphier_sd_probe(struct udevice *dev)
|
|||
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||
fdt_addr_t base;
|
||||
struct udevice *clk_dev;
|
||||
int clk_id;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
priv->dev = dev;
|
||||
|
@ -665,20 +664,22 @@ int uniphier_sd_probe(struct udevice *dev)
|
|||
if (!priv->regbase)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_id = clk_get_by_index(dev, 0, &clk_dev);
|
||||
if (clk_id < 0) {
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get host clock\n");
|
||||
return clk_id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set to max rate */
|
||||
priv->mclk = clk_set_periph_rate(clk_dev, clk_id, ULONG_MAX);
|
||||
priv->mclk = clk_set_rate(&clk, ULONG_MAX);
|
||||
if (IS_ERR_VALUE(priv->mclk)) {
|
||||
dev_err(dev, "failed to set rate for host clock\n");
|
||||
clk_free(&clk);
|
||||
return priv->mclk;
|
||||
}
|
||||
|
||||
ret = clk_enable(clk_dev, clk_id);
|
||||
ret = clk_enable(&clk);
|
||||
clk_free(&clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable host clock\n");
|
||||
return ret;
|
||||
|
|
23
drivers/reset/Kconfig
Normal file
23
drivers/reset/Kconfig
Normal file
|
@ -0,0 +1,23 @@
|
|||
menu "Reset Controller Support"
|
||||
|
||||
config DM_RESET
|
||||
bool "Enable reset controllers using Driver Model"
|
||||
depends on DM && OF_CONTROL
|
||||
help
|
||||
Enable support for the reset controller driver class. Many hardware
|
||||
modules are equipped with a reset signal, typically driven by some
|
||||
reset controller hardware module within the chip. In U-Boot, reset
|
||||
controller drivers allow control over these reset signals. In some
|
||||
cases this API is applicable to chips outside the CPU as well,
|
||||
although driving such reset isgnals using GPIOs may be more
|
||||
appropriate in this case.
|
||||
|
||||
config SANDBOX_RESET
|
||||
bool "Enable the sandbox reset test driver"
|
||||
depends on DM_MAILBOX && SANDBOX
|
||||
help
|
||||
Enable support for a test reset controller implementation, which
|
||||
simply accepts requests to reset various HW modules without actually
|
||||
doing anything beyond a little error checking.
|
||||
|
||||
endmenu
|
7
drivers/reset/Makefile
Normal file
7
drivers/reset/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_DM_RESET) += reset-uclass.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o
|
||||
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
|
131
drivers/reset/reset-uclass.c
Normal file
131
drivers/reset/reset-uclass.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <reset.h>
|
||||
#include <reset-uclass.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
|
||||
{
|
||||
return (struct reset_ops *)dev->driver->ops;
|
||||
}
|
||||
|
||||
static int reset_of_xlate_default(struct reset_ctl *reset_ctl,
|
||||
struct fdtdec_phandle_args *args)
|
||||
{
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
if (args->args_count != 1) {
|
||||
debug("Invaild args_count: %d\n", args->args_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reset_ctl->id = args->args[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reset_get_by_index(struct udevice *dev, int index,
|
||||
struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct fdtdec_phandle_args args;
|
||||
int ret;
|
||||
struct udevice *dev_reset;
|
||||
struct reset_ops *ops;
|
||||
|
||||
debug("%s(dev=%p, index=%d, reset_ctl=%p)\n", __func__, dev, index,
|
||||
reset_ctl);
|
||||
|
||||
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
|
||||
"resets", "#reset-cells", 0,
|
||||
index, &args);
|
||||
if (ret) {
|
||||
debug("%s: fdtdec_parse_phandle_with_args failed: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node,
|
||||
&dev_reset);
|
||||
if (ret) {
|
||||
debug("%s: uclass_get_device_by_of_offset failed: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
ops = reset_dev_ops(dev_reset);
|
||||
|
||||
reset_ctl->dev = dev_reset;
|
||||
if (ops->of_xlate)
|
||||
ret = ops->of_xlate(reset_ctl, &args);
|
||||
else
|
||||
ret = reset_of_xlate_default(reset_ctl, &args);
|
||||
if (ret) {
|
||||
debug("of_xlate() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ops->request(reset_ctl);
|
||||
if (ret) {
|
||||
debug("ops->request() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reset_get_by_name(struct udevice *dev, const char *name,
|
||||
struct reset_ctl *reset_ctl)
|
||||
{
|
||||
int index;
|
||||
|
||||
debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name,
|
||||
reset_ctl);
|
||||
|
||||
index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reset-names",
|
||||
name);
|
||||
if (index < 0) {
|
||||
debug("fdt_find_string() failed: %d\n", index);
|
||||
return index;
|
||||
}
|
||||
|
||||
return reset_get_by_index(dev, index, reset_ctl);
|
||||
}
|
||||
|
||||
int reset_free(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
|
||||
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
return ops->free(reset_ctl);
|
||||
}
|
||||
|
||||
int reset_assert(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
|
||||
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
return ops->rst_assert(reset_ctl);
|
||||
}
|
||||
|
||||
int reset_deassert(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
|
||||
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
return ops->rst_deassert(reset_ctl);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(reset) = {
|
||||
.id = UCLASS_RESET,
|
||||
.name = "reset",
|
||||
};
|
55
drivers/reset/sandbox-reset-test.c
Normal file
55
drivers/reset/sandbox-reset-test.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <reset.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/reset.h>
|
||||
|
||||
struct sandbox_reset_test {
|
||||
struct reset_ctl ctl;
|
||||
};
|
||||
|
||||
int sandbox_reset_test_get(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
|
||||
|
||||
return reset_get_by_name(dev, "test", &sbrt->ctl);
|
||||
}
|
||||
|
||||
int sandbox_reset_test_assert(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
|
||||
|
||||
return reset_assert(&sbrt->ctl);
|
||||
}
|
||||
|
||||
int sandbox_reset_test_deassert(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
|
||||
|
||||
return reset_deassert(&sbrt->ctl);
|
||||
}
|
||||
|
||||
int sandbox_reset_test_free(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
|
||||
|
||||
return reset_free(&sbrt->ctl);
|
||||
}
|
||||
|
||||
static const struct udevice_id sandbox_reset_test_ids[] = {
|
||||
{ .compatible = "sandbox,reset-ctl-test" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_reset_test) = {
|
||||
.name = "sandbox_reset_test",
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = sandbox_reset_test_ids,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_reset_test),
|
||||
};
|
108
drivers/reset/sandbox-reset.c
Normal file
108
drivers/reset/sandbox-reset.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <reset-uclass.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/reset.h>
|
||||
|
||||
#define SANDBOX_RESET_SIGNALS 3
|
||||
|
||||
struct sandbox_reset_signal {
|
||||
bool asserted;
|
||||
};
|
||||
|
||||
struct sandbox_reset {
|
||||
struct sandbox_reset_signal signals[SANDBOX_RESET_SIGNALS];
|
||||
};
|
||||
|
||||
static int sandbox_reset_request(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
if (reset_ctl->id >= SANDBOX_RESET_SIGNALS)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_reset_free(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_reset_assert(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct sandbox_reset *sbr = dev_get_priv(reset_ctl->dev);
|
||||
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
sbr->signals[reset_ctl->id].asserted = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_reset_deassert(struct reset_ctl *reset_ctl)
|
||||
{
|
||||
struct sandbox_reset *sbr = dev_get_priv(reset_ctl->dev);
|
||||
|
||||
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
|
||||
|
||||
sbr->signals[reset_ctl->id].asserted = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_reset_bind(struct udevice *dev)
|
||||
{
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_reset_probe(struct udevice *dev)
|
||||
{
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id sandbox_reset_ids[] = {
|
||||
{ .compatible = "sandbox,reset-ctl" },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct reset_ops sandbox_reset_reset_ops = {
|
||||
.request = sandbox_reset_request,
|
||||
.free = sandbox_reset_free,
|
||||
.rst_assert = sandbox_reset_assert,
|
||||
.rst_deassert = sandbox_reset_deassert,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sandbox_reset) = {
|
||||
.name = "sandbox_reset",
|
||||
.id = UCLASS_RESET,
|
||||
.of_match = sandbox_reset_ids,
|
||||
.bind = sandbox_reset_bind,
|
||||
.probe = sandbox_reset_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_reset),
|
||||
.ops = &sandbox_reset_reset_ops,
|
||||
};
|
||||
|
||||
int sandbox_reset_query(struct udevice *dev, unsigned long id)
|
||||
{
|
||||
struct sandbox_reset *sbr = dev_get_priv(dev);
|
||||
|
||||
debug("%s(dev=%p, id=%ld)\n", __func__, dev, id);
|
||||
|
||||
if (id >= SANDBOX_RESET_SIGNALS)
|
||||
return -EINVAL;
|
||||
|
||||
return sbr->signals[id].asserted;
|
||||
}
|
|
@ -150,7 +150,8 @@ static int msm_uart_clk_init(struct udevice *dev)
|
|||
"clock-frequency", 115200);
|
||||
uint clkd[2]; /* clk_id and clk_no */
|
||||
int clk_offset;
|
||||
struct udevice *clk;
|
||||
struct udevice *clk_dev;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd,
|
||||
|
@ -162,11 +163,17 @@ static int msm_uart_clk_init(struct udevice *dev)
|
|||
if (clk_offset < 0)
|
||||
return clk_offset;
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk);
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_set_periph_rate(clk, clkd[1], clk_rate);
|
||||
clk.id = clkd[1];
|
||||
ret = clk_request(clk_dev, &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_set_rate(&clk, clk_rate);
|
||||
clk_free(&clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ static int pic32_uart_getc(struct udevice *dev)
|
|||
static int pic32_uart_probe(struct udevice *dev)
|
||||
{
|
||||
struct pic32_uart_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *clkdev;
|
||||
struct clk clk;
|
||||
fdt_addr_t addr;
|
||||
fdt_size_t size;
|
||||
int ret;
|
||||
|
@ -148,10 +148,11 @@ static int pic32_uart_probe(struct udevice *dev)
|
|||
priv->base = ioremap(addr, size);
|
||||
|
||||
/* get clock rate */
|
||||
ret = clk_get_by_index(dev, 0, &clkdev);
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
priv->uartclk = clk_get_periph_rate(clkdev, ret);
|
||||
priv->uartclk = clk_get_rate(&clk);
|
||||
clk_free(&clk);
|
||||
|
||||
/* initialize serial */
|
||||
return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
|
||||
|
|
|
@ -94,13 +94,13 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate)
|
|||
u32 uclk;
|
||||
|
||||
#ifdef CONFIG_CLK_EXYNOS
|
||||
struct udevice *clk_dev;
|
||||
struct clk clk;
|
||||
u32 ret;
|
||||
|
||||
ret = clk_get_by_index(dev, 1, &clk_dev);
|
||||
ret = clk_get_by_index(dev, 1, &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
uclk = clk_get_periph_rate(clk_dev, ret);
|
||||
uclk = clk_get_rate(&clk);
|
||||
#else
|
||||
uclk = get_uart_clk(plat->port_id);
|
||||
#endif
|
||||
|
|
|
@ -35,8 +35,7 @@ struct rockchip_spi_platdata {
|
|||
|
||||
struct rockchip_spi_priv {
|
||||
struct rockchip_spi *regs;
|
||||
struct udevice *clk;
|
||||
int clk_id;
|
||||
struct clk clk;
|
||||
unsigned int max_freq;
|
||||
unsigned int mode;
|
||||
ulong last_transaction_us; /* Time of last transaction end */
|
||||
|
@ -144,7 +143,6 @@ static int rockchip_spi_ofdata_to_platdata(struct udevice *bus)
|
|||
bus->name, ret);
|
||||
return ret;
|
||||
}
|
||||
priv->clk_id = ret;
|
||||
|
||||
plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
|
||||
50000000);
|
||||
|
@ -175,7 +173,7 @@ static int rockchip_spi_probe(struct udevice *bus)
|
|||
* Use 99 MHz as our clock since it divides nicely into 594 MHz which
|
||||
* is the assumed speed for CLK_GENERAL.
|
||||
*/
|
||||
ret = clk_set_periph_rate(priv->clk, priv->clk_id, 99000000);
|
||||
ret = clk_set_rate(&priv->clk, 99000000);
|
||||
if (ret < 0) {
|
||||
debug("%s: Failed to set clock: %d\n", __func__, ret);
|
||||
return ret;
|
||||
|
|
|
@ -26,15 +26,15 @@ static int ehci_usb_probe(struct udevice *dev)
|
|||
int i;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
struct udevice *clk_dev;
|
||||
int clk_id;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
clk_id = clk_get_by_index(dev, i, &clk_dev);
|
||||
if (clk_id < 0)
|
||||
ret = clk_get_by_index(dev, i, &clk);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (clk_enable(clk_dev, clk_id))
|
||||
printf("failed to enable clock (dev=%s, id=%d)\n",
|
||||
clk_dev->name, clk_id);
|
||||
if (clk_enable(&clk))
|
||||
printf("failed to enable clock %d\n", i);
|
||||
clk_free(&clk);
|
||||
}
|
||||
|
||||
hccr = map_physmem(dev_get_addr(dev), 0x100, MAP_NOCACHE);
|
||||
|
|
|
@ -1009,8 +1009,7 @@ int rk_edp_probe(struct udevice *dev)
|
|||
struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
|
||||
struct rk_edp_priv *priv = dev_get_priv(dev);
|
||||
struct rk3288_edp *regs = priv->regs;
|
||||
struct udevice *clk;
|
||||
int periph;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "rockchip,panel",
|
||||
|
@ -1026,8 +1025,8 @@ int rk_edp_probe(struct udevice *dev)
|
|||
|
||||
ret = clk_get_by_index(dev, 1, &clk);
|
||||
if (ret >= 0) {
|
||||
periph = ret;
|
||||
ret = clk_set_periph_rate(clk, periph, 0);
|
||||
ret = clk_set_rate(&clk, 0);
|
||||
clk_free(&clk);
|
||||
}
|
||||
if (ret) {
|
||||
debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
|
||||
|
@ -1036,8 +1035,8 @@ int rk_edp_probe(struct udevice *dev)
|
|||
|
||||
ret = clk_get_by_index(uc_plat->src_dev, 0, &clk);
|
||||
if (ret >= 0) {
|
||||
periph = ret;
|
||||
ret = clk_set_periph_rate(clk, periph, 192000000);
|
||||
ret = clk_set_rate(&clk, 192000000);
|
||||
clk_free(&clk);
|
||||
}
|
||||
if (ret < 0) {
|
||||
debug("%s: Failed to set clock in source device '%s': ret=%d\n",
|
||||
|
|
|
@ -859,15 +859,15 @@ static int rk_hdmi_probe(struct udevice *dev)
|
|||
{
|
||||
struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
|
||||
struct rk_hdmi_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *reg, *clk;
|
||||
int periph;
|
||||
struct udevice *reg;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
int vop_id = uc_plat->source_id;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret >= 0) {
|
||||
periph = ret;
|
||||
ret = clk_set_periph_rate(clk, periph, 0);
|
||||
ret = clk_set_rate(&clk, 0);
|
||||
clk_free(&clk);
|
||||
}
|
||||
if (ret) {
|
||||
debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
|
||||
|
@ -880,8 +880,8 @@ static int rk_hdmi_probe(struct udevice *dev)
|
|||
*/
|
||||
ret = clk_get_by_index(uc_plat->src_dev, 0, &clk);
|
||||
if (ret >= 0) {
|
||||
periph = ret;
|
||||
ret = clk_set_periph_rate(clk, periph, 384000000);
|
||||
ret = clk_set_rate(&clk, 384000000);
|
||||
clk_free(&clk);
|
||||
}
|
||||
if (ret < 0) {
|
||||
debug("%s: Failed to set clock in source device '%s': ret=%d\n",
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <display.h>
|
||||
#include <dm.h>
|
||||
#include <edid.h>
|
||||
|
|
|
@ -195,7 +195,8 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
|
|||
struct udevice *disp;
|
||||
int ret, remote, i, offset;
|
||||
struct display_plat *disp_uc_plat;
|
||||
struct udevice *clk;
|
||||
struct udevice *dev_clk;
|
||||
struct clk clk;
|
||||
|
||||
vop_id = fdtdec_get_int(blob, ep_node, "reg", -1);
|
||||
debug("vop_id=%d\n", vop_id);
|
||||
|
@ -237,11 +238,13 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = rkclk_get_clk(CLK_NEW, &clk);
|
||||
ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk);
|
||||
if (!ret) {
|
||||
ret = clk_set_periph_rate(clk, DCLK_VOP0 + remote_vop_id,
|
||||
timing.pixelclock.typ);
|
||||
clk.id = DCLK_VOP0 + remote_vop_id;
|
||||
ret = clk_request(dev_clk, &clk);
|
||||
}
|
||||
if (!ret)
|
||||
ret = clk_set_rate(&clk, timing.pixelclock.typ);
|
||||
if (ret) {
|
||||
debug("%s: Failed to set pixel clock: ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
|
|
95
include/clk-uclass.h
Normal file
95
include/clk-uclass.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _CLK_UCLASS_H
|
||||
#define _CLK_UCLASS_H
|
||||
|
||||
/* See clk.h for background documentation. */
|
||||
|
||||
#include <clk.h>
|
||||
#include <fdtdec.h>
|
||||
|
||||
/**
|
||||
* struct clk_ops - The functions that a clock driver must implement.
|
||||
*/
|
||||
struct clk_ops {
|
||||
/**
|
||||
* of_xlate - Translate a client's device-tree (OF) clock specifier.
|
||||
*
|
||||
* The clock core calls this function as the first step in implementing
|
||||
* a client's clk_get_by_*() call.
|
||||
*
|
||||
* If this function pointer is set to NULL, the clock core will use a
|
||||
* default implementation, which assumes #clock-cells = <1>, and that
|
||||
* the DT cell contains a simple integer clock ID.
|
||||
*
|
||||
* At present, the clock API solely supports device-tree. If this
|
||||
* changes, other xxx_xlate() functions may be added to support those
|
||||
* other mechanisms.
|
||||
*
|
||||
* @clock: The clock struct to hold the translation result.
|
||||
* @args: The clock specifier values from device tree.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*of_xlate)(struct clk *clock,
|
||||
struct fdtdec_phandle_args *args);
|
||||
/**
|
||||
* request - Request a translated clock.
|
||||
*
|
||||
* The clock core calls this function as the second step in
|
||||
* implementing a client's clk_get_by_*() call, following a successful
|
||||
* xxx_xlate() call, or as the only step in implementing a client's
|
||||
* clk_request() call.
|
||||
*
|
||||
* @clock: The clock struct to request; this has been fille in by
|
||||
* a previoux xxx_xlate() function call, or by the caller
|
||||
* of clk_request().
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*request)(struct clk *clock);
|
||||
/**
|
||||
* free - Free a previously requested clock.
|
||||
*
|
||||
* This is the implementation of the client clk_free() API.
|
||||
*
|
||||
* @clock: The clock to free.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*free)(struct clk *clock);
|
||||
/**
|
||||
* get_rate() - Get current clock rate.
|
||||
*
|
||||
* @clk: The clock to query.
|
||||
* @return clock rate in Hz, or -ve error code
|
||||
*/
|
||||
ulong (*get_rate)(struct clk *clk);
|
||||
/**
|
||||
* set_rate() - Set current clock rate.
|
||||
*
|
||||
* @clk: The clock to manipulate.
|
||||
* @rate: New clock rate in Hz.
|
||||
* @return new rate, or -ve error code.
|
||||
*/
|
||||
ulong (*set_rate)(struct clk *clk, ulong rate);
|
||||
/**
|
||||
* enable() - Enable a clock.
|
||||
*
|
||||
* @clk: The clock to manipulate.
|
||||
* @return zero on success, or -ve error code.
|
||||
*/
|
||||
int (*enable)(struct clk *clk);
|
||||
/**
|
||||
* disable() - Disable a clock.
|
||||
*
|
||||
* @clk: The clock to manipulate.
|
||||
* @return zero on success, or -ve error code.
|
||||
*/
|
||||
int (*disable)(struct clk *clk);
|
||||
};
|
||||
|
||||
#endif
|
248
include/clk.h
248
include/clk.h
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
@ -8,125 +9,166 @@
|
|||
#ifndef _CLK_H_
|
||||
#define _CLK_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* A clock is a hardware signal that oscillates autonomously at a specific
|
||||
* frequency and duty cycle. Most hardware modules require one or more clock
|
||||
* signal to drive their operation. Clock signals are typically generated
|
||||
* externally to the HW module consuming them, by an entity this API calls a
|
||||
* clock provider. This API provides a standard means for drivers to enable and
|
||||
* disable clocks, and to set the rate at which they oscillate.
|
||||
*
|
||||
* A driver that implements UCLASS_CLOCK is a clock provider. A provider will
|
||||
* often implement multiple separate clocks, since the hardware it manages
|
||||
* often has this capability. clock_uclass.h describes the interface which
|
||||
* clock providers must implement.
|
||||
*
|
||||
* Clock consumers/clients are the HW modules driven by the clock signals. This
|
||||
* header file describes the API used by drivers for those HW modules.
|
||||
*/
|
||||
|
||||
struct udevice;
|
||||
|
||||
int soc_clk_dump(void);
|
||||
|
||||
struct clk_ops {
|
||||
/**
|
||||
* get_rate() - Get current clock rate
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CLK)
|
||||
* @return clock rate in Hz, or -ve error code
|
||||
/**
|
||||
* struct clk - A handle to (allowing control of) a single clock.
|
||||
*
|
||||
* Clients provide storage for clock handles. The content of the structure is
|
||||
* managed solely by the clock API and clock drivers. A clock struct is
|
||||
* initialized by "get"ing the clock struct. The clock struct is passed to all
|
||||
* other clock APIs to identify which clock signal to operate upon.
|
||||
*
|
||||
* @dev: The device which implements the clock signal.
|
||||
* @id: The clock signal ID within the provider.
|
||||
*
|
||||
* Currently, the clock API assumes that a single integer ID is enough to
|
||||
* identify and configure any clock signal for any clock provider. If this
|
||||
* assumption becomes invalid in the future, the struct could be expanded to
|
||||
* either (a) add more fields to allow clock providers to store additional
|
||||
* information, or (b) replace the id field with an opaque pointer, which the
|
||||
* provider would dynamically allocated during its .of_xlate op, and process
|
||||
* during is .request op. This may require the addition of an extra op to clean
|
||||
* up the allocation.
|
||||
*/
|
||||
struct clk {
|
||||
struct udevice *dev;
|
||||
/*
|
||||
* Written by of_xlate. We assume a single id is enough for now. In the
|
||||
* future, we might add more fields here.
|
||||
*/
|
||||
ulong (*get_rate)(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* set_rate() - Set current clock rate
|
||||
*
|
||||
* @dev: Device to adjust
|
||||
* @rate: New clock rate in Hz
|
||||
* @return new rate, or -ve error code
|
||||
*/
|
||||
ulong (*set_rate)(struct udevice *dev, ulong rate);
|
||||
|
||||
/**
|
||||
* enable() - Enable the clock for a peripheral
|
||||
*
|
||||
* @dev: clock provider
|
||||
* @periph: Peripheral ID to enable
|
||||
* @return zero on success, or -ve error code
|
||||
*/
|
||||
int (*enable)(struct udevice *dev, int periph);
|
||||
|
||||
/**
|
||||
* get_periph_rate() - Get clock rate for a peripheral
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CLK)
|
||||
* @periph: Peripheral ID to check
|
||||
* @return clock rate in Hz, or -ve error code
|
||||
*/
|
||||
ulong (*get_periph_rate)(struct udevice *dev, int periph);
|
||||
|
||||
/**
|
||||
* set_periph_rate() - Set current clock rate for a peripheral
|
||||
*
|
||||
* @dev: Device to update (UCLASS_CLK)
|
||||
* @periph: Peripheral ID to update
|
||||
* @return new clock rate in Hz, or -ve error code
|
||||
*/
|
||||
ulong (*set_periph_rate)(struct udevice *dev, int periph, ulong rate);
|
||||
unsigned long id;
|
||||
};
|
||||
|
||||
#define clk_get_ops(dev) ((struct clk_ops *)(dev)->driver->ops)
|
||||
|
||||
/**
|
||||
* clk_get_rate() - Get current clock rate
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CLK)
|
||||
* @return clock rate in Hz, or -ve error code
|
||||
*/
|
||||
ulong clk_get_rate(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* clk_set_rate() - Set current clock rate
|
||||
*
|
||||
* @dev: Device to adjust
|
||||
* @rate: New clock rate in Hz
|
||||
* @return new rate, or -ve error code
|
||||
*/
|
||||
ulong clk_set_rate(struct udevice *dev, ulong rate);
|
||||
|
||||
/**
|
||||
* clk_enable() - Enable the clock for a peripheral
|
||||
*
|
||||
* @dev: clock provider
|
||||
* @periph: Peripheral ID to enable
|
||||
* @return zero on success, or -ve error code
|
||||
*/
|
||||
int clk_enable(struct udevice *dev, int periph);
|
||||
|
||||
/**
|
||||
* clk_get_periph_rate() - Get current clock rate for a peripheral
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CLK)
|
||||
* @return clock rate in Hz, -ve error code
|
||||
*/
|
||||
ulong clk_get_periph_rate(struct udevice *dev, int periph);
|
||||
|
||||
/**
|
||||
* clk_set_periph_rate() - Set current clock rate for a peripheral
|
||||
*
|
||||
* @dev: Device to update (UCLASS_CLK)
|
||||
* @periph: Peripheral ID to update
|
||||
* @return new clock rate in Hz, or -ve error code
|
||||
*/
|
||||
ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate);
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
/**
|
||||
* clk_get_by_index() - look up a clock referenced by a device
|
||||
* clock_get_by_index - Get/request a clock by integer index.
|
||||
*
|
||||
* Parse a device's 'clocks' list, returning information on the indexed clock,
|
||||
* ensuring that it is activated.
|
||||
* This looks up and requests a clock. The index is relative to the client
|
||||
* device; each device is assumed to have n clocks associated with it somehow,
|
||||
* and this function finds and requests one of them. The mapping of client
|
||||
* device clock indices to provider clocks may be via device-tree properties,
|
||||
* board-provided mapping tables, or some other mechanism.
|
||||
*
|
||||
* @dev: Device containing the clock reference
|
||||
* @index: Clock index to return (0 = first)
|
||||
* @clk_devp: Returns clock device
|
||||
* @return: Peripheral ID for the device to control. This is the first
|
||||
* argument after the clock node phandle. If there is no arguemnt,
|
||||
* returns 0. Return -ve error code on any error
|
||||
* @dev: The client device.
|
||||
* @index: The index of the clock to request, within the client's list of
|
||||
* clocks.
|
||||
* @clock A pointer to a clock struct to initialize.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp);
|
||||
int clk_get_by_index(struct udevice *dev, int index, struct clk *clk);
|
||||
|
||||
/**
|
||||
* clock_get_by_name - Get/request a clock by name.
|
||||
*
|
||||
* This looks up and requests a clock. The name is relative to the client
|
||||
* device; each device is assumed to have n clocks associated with it somehow,
|
||||
* and this function finds and requests one of them. The mapping of client
|
||||
* device clock names to provider clocks may be via device-tree properties,
|
||||
* board-provided mapping tables, or some other mechanism.
|
||||
*
|
||||
* @dev: The client device.
|
||||
* @name: The name of the clock to request, within the client's list of
|
||||
* clocks.
|
||||
* @clock: A pointer to a clock struct to initialize.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
|
||||
#else
|
||||
static inline int clk_get_by_index(struct udevice *dev, int index,
|
||||
struct udevice **clk_devp)
|
||||
struct clk *clk)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int clk_get_by_name(struct udevice *dev, const char *name,
|
||||
struct clk *clk)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CLK_H_ */
|
||||
/**
|
||||
* clk_request - Request a clock by provider-specific ID.
|
||||
*
|
||||
* This requests a clock using a provider-specific ID. Generally, this function
|
||||
* should not be used, since clk_get_by_index/name() provide an interface that
|
||||
* better separates clients from intimate knowledge of clock providers.
|
||||
* However, this function may be useful in core SoC-specific code.
|
||||
*
|
||||
* @dev: The clock provider device.
|
||||
* @clock: A pointer to a clock struct to initialize. The caller must
|
||||
* have already initialized any field in this struct which the
|
||||
* clock provider uses to identify the clock.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int clk_request(struct udevice *dev, struct clk *clk);
|
||||
|
||||
/**
|
||||
* clock_free - Free a previously requested clock.
|
||||
*
|
||||
* @clock: A clock struct that was previously successfully requested by
|
||||
* clk_request/get_by_*().
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int clk_free(struct clk *clk);
|
||||
|
||||
/**
|
||||
* clk_get_rate() - Get current clock rate.
|
||||
*
|
||||
* @clk: A clock struct that was previously successfully requested by
|
||||
* clk_request/get_by_*().
|
||||
* @return clock rate in Hz, or -ve error code.
|
||||
*/
|
||||
ulong clk_get_rate(struct clk *clk);
|
||||
|
||||
/**
|
||||
* clk_set_rate() - Set current clock rate.
|
||||
*
|
||||
* @clk: A clock struct that was previously successfully requested by
|
||||
* clk_request/get_by_*().
|
||||
* @rate: New clock rate in Hz.
|
||||
* @return new rate, or -ve error code.
|
||||
*/
|
||||
ulong clk_set_rate(struct clk *clk, ulong rate);
|
||||
|
||||
/**
|
||||
* clk_enable() - Enable (turn on) a clock.
|
||||
*
|
||||
* @clk: A clock struct that was previously successfully requested by
|
||||
* clk_request/get_by_*().
|
||||
* @return zero on success, or -ve error code.
|
||||
*/
|
||||
int clk_enable(struct clk *clk);
|
||||
|
||||
/**
|
||||
* clk_disable() - Disable (turn off) a clock.
|
||||
*
|
||||
* @clk: A clock struct that was previously successfully requested by
|
||||
* clk_request/get_by_*().
|
||||
* @return zero on success, or -ve error code.
|
||||
*/
|
||||
int clk_disable(struct clk *clk);
|
||||
|
||||
int soc_clk_dump(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -63,6 +63,7 @@ enum uclass_id {
|
|||
UCLASS_PWRSEQ, /* Power sequence device */
|
||||
UCLASS_REGULATOR, /* Regulator device */
|
||||
UCLASS_REMOTEPROC, /* Remote Processor device */
|
||||
UCLASS_RESET, /* Reset controller device */
|
||||
UCLASS_RTC, /* Real time clock device */
|
||||
UCLASS_SERIAL, /* Serial UART */
|
||||
UCLASS_SPI, /* SPI bus */
|
||||
|
|
14
include/dt-bindings/mailbox/tegra-hsp.h
Normal file
14
include/dt-bindings/mailbox/tegra-hsp.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* This header provides constants for binding nvidia,tegra186-hsp.
|
||||
*
|
||||
* The number with TEGRA_HSP_MASTER prefix indicates the bit that is
|
||||
* associated with a master ID in the doorbell registers.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
|
||||
#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
|
||||
|
||||
#define TEGRA_HSP_MASTER_CCPLEX 17
|
||||
#define TEGRA_HSP_MASTER_BPMP 19
|
||||
|
||||
#endif
|
|
@ -7,9 +7,9 @@
|
|||
#ifndef _MAILBOX_UCLASS_H
|
||||
#define _MAILBOX_UCLASS_H
|
||||
|
||||
/* See mailbox_client.h for background documentation. */
|
||||
/* See mailbox.h for background documentation. */
|
||||
|
||||
#include <mailbox_client.h>
|
||||
#include <mailbox.h>
|
||||
|
||||
struct udevice;
|
||||
|
|
@ -4,8 +4,8 @@
|
|||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _MAILBOX_CLIENT_H
|
||||
#define _MAILBOX_CLIENT_H
|
||||
#ifndef _MAILBOX_H
|
||||
#define _MAILBOX_H
|
||||
|
||||
/**
|
||||
* A mailbox is a hardware mechanism for transferring small fixed-size messages
|
||||
|
@ -26,7 +26,7 @@
|
|||
*
|
||||
* A driver that implements UCLASS_MAILBOX is a mailbox provider. A provider
|
||||
* will often implement multiple separate mailbox channels, since the hardware
|
||||
* it manages often has this capability. mailbox_uclass.h describes the
|
||||
* it manages often has this capability. mailbox-uclass.h describes the
|
||||
* interface which mailbox providers must implement.
|
||||
*
|
||||
* Mailbox consumers/clients generate and send, or receive and process,
|
81
include/reset-uclass.h
Normal file
81
include/reset-uclass.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _RESET_UCLASS_H
|
||||
#define _RESET_UCLASS_H
|
||||
|
||||
/* See reset.h for background documentation. */
|
||||
|
||||
#include <reset.h>
|
||||
|
||||
struct udevice;
|
||||
|
||||
/**
|
||||
* struct reset_ops - The functions that a reset controller driver must
|
||||
* implement.
|
||||
*/
|
||||
struct reset_ops {
|
||||
/**
|
||||
* of_xlate - Translate a client's device-tree (OF) reset specifier.
|
||||
*
|
||||
* The reset core calls this function as the first step in implementing
|
||||
* a client's reset_get_by_*() call.
|
||||
*
|
||||
* If this function pointer is set to NULL, the reset core will use a
|
||||
* default implementation, which assumes #reset-cells = <1>, and that
|
||||
* the DT cell contains a simple integer reset signal ID.
|
||||
*
|
||||
* At present, the reset API solely supports device-tree. If this
|
||||
* changes, other xxx_xlate() functions may be added to support those
|
||||
* other mechanisms.
|
||||
*
|
||||
* @reset_ctl: The reset control struct to hold the translation result.
|
||||
* @args: The reset specifier values from device tree.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*of_xlate)(struct reset_ctl *reset_ctl,
|
||||
struct fdtdec_phandle_args *args);
|
||||
/**
|
||||
* request - Request a translated reset control.
|
||||
*
|
||||
* The reset core calls this function as the second step in
|
||||
* implementing a client's reset_get_by_*() call, following a
|
||||
* successful xxx_xlate() call.
|
||||
*
|
||||
* @reset_ctl: The reset control struct to request; this has been
|
||||
* filled in by a previoux xxx_xlate() function call.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*request)(struct reset_ctl *reset_ctl);
|
||||
/**
|
||||
* free - Free a previously requested reset control.
|
||||
*
|
||||
* This is the implementation of the client reset_free() API.
|
||||
*
|
||||
* @reset_ctl: The reset control to free.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*free)(struct reset_ctl *reset_ctl);
|
||||
/**
|
||||
* rst_assert - Assert a reset signal.
|
||||
*
|
||||
* Note: This function is named rst_assert not assert to avoid
|
||||
* conflicting with global macro assert().
|
||||
*
|
||||
* @reset_ctl: The reset signal to assert.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*rst_assert)(struct reset_ctl *reset_ctl);
|
||||
/**
|
||||
* rst_deassert - Deassert a reset signal.
|
||||
*
|
||||
* @reset_ctl: The reset signal to deassert.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int (*rst_deassert)(struct reset_ctl *reset_ctl);
|
||||
};
|
||||
|
||||
#endif
|
135
include/reset.h
Normal file
135
include/reset.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _RESET_H
|
||||
#define _RESET_H
|
||||
|
||||
/**
|
||||
* A reset is a hardware signal indicating that a HW module (or IP block, or
|
||||
* sometimes an entire off-CPU chip) reset all of its internal state to some
|
||||
* known-good initial state. Drivers will often reset HW modules when they
|
||||
* begin execution to ensure that hardware correctly responds to all requests,
|
||||
* or in response to some error condition. Reset signals are often controlled
|
||||
* externally to the HW module being reset, by an entity this API calls a reset
|
||||
* controller. This API provides a standard means for drivers to request that
|
||||
* reset controllers set or clear reset signals.
|
||||
*
|
||||
* A driver that implements UCLASS_RESET is a reset controller or provider. A
|
||||
* controller will often implement multiple separate reset signals, since the
|
||||
* hardware it manages often has this capability. reset-uclass.h describes the
|
||||
* interface which reset controllers must implement.
|
||||
*
|
||||
* Reset consumers/clients are the HW modules affected by reset signals. This
|
||||
* header file describes the API used by drivers for those HW modules.
|
||||
*/
|
||||
|
||||
struct udevice;
|
||||
|
||||
/**
|
||||
* struct reset_ctl - A handle to (allowing control of) a single reset signal.
|
||||
*
|
||||
* Clients provide storage for reset control handles. The content of the
|
||||
* structure is managed solely by the reset API and reset drivers. A reset
|
||||
* control struct is initialized by "get"ing the reset control struct. The
|
||||
* reset control struct is passed to all other reset APIs to identify which
|
||||
* reset signal to operate upon.
|
||||
*
|
||||
* @dev: The device which implements the reset signal.
|
||||
* @id: The reset signal ID within the provider.
|
||||
*
|
||||
* Currently, the reset API assumes that a single integer ID is enough to
|
||||
* identify and configure any reset signal for any reset provider. If this
|
||||
* assumption becomes invalid in the future, the struct could be expanded to
|
||||
* either (a) add more fields to allow reset providers to store additional
|
||||
* information, or (b) replace the id field with an opaque pointer, which the
|
||||
* provider would dynamically allocated during its .of_xlate op, and process
|
||||
* during is .request op. This may require the addition of an extra op to clean
|
||||
* up the allocation.
|
||||
*/
|
||||
struct reset_ctl {
|
||||
struct udevice *dev;
|
||||
/*
|
||||
* Written by of_xlate. We assume a single id is enough for now. In the
|
||||
* future, we might add more fields here.
|
||||
*/
|
||||
unsigned long id;
|
||||
};
|
||||
|
||||
/**
|
||||
* reset_get_by_index - Get/request a reset signal by integer index.
|
||||
*
|
||||
* This looks up and requests a reset signal. The index is relative to the
|
||||
* client device; each device is assumed to have n reset signals associated
|
||||
* with it somehow, and this function finds and requests one of them. The
|
||||
* mapping of client device reset signal indices to provider reset signals may
|
||||
* be via device-tree properties, board-provided mapping tables, or some other
|
||||
* mechanism.
|
||||
*
|
||||
* @dev: The client device.
|
||||
* @index: The index of the reset signal to request, within the client's
|
||||
* list of reset signals.
|
||||
* @reset_ctl A pointer to a reset control struct to initialize.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int reset_get_by_index(struct udevice *dev, int index,
|
||||
struct reset_ctl *reset_ctl);
|
||||
|
||||
/**
|
||||
* reset_get_by_name - Get/request a reset signal by name.
|
||||
*
|
||||
* This looks up and requests a reset signal. The name is relative to the
|
||||
* client device; each device is assumed to have n reset signals associated
|
||||
* with it somehow, and this function finds and requests one of them. The
|
||||
* mapping of client device reset signal names to provider reset signal may be
|
||||
* via device-tree properties, board-provided mapping tables, or some other
|
||||
* mechanism.
|
||||
*
|
||||
* @dev: The client device.
|
||||
* @name: The name of the reset signal to request, within the client's
|
||||
* list of reset signals.
|
||||
* @reset_ctl: A pointer to a reset control struct to initialize.
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int reset_get_by_name(struct udevice *dev, const char *name,
|
||||
struct reset_ctl *reset_ctl);
|
||||
|
||||
/**
|
||||
* reset_free - Free a previously requested reset signal.
|
||||
*
|
||||
* @reset_ctl: A reset control struct that was previously successfully
|
||||
* requested by reset_get_by_*().
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int reset_free(struct reset_ctl *reset_ctl);
|
||||
|
||||
/**
|
||||
* reset_assert - Assert a reset signal.
|
||||
*
|
||||
* This function will assert the specified reset signal, thus resetting the
|
||||
* affected HW module(s). Depending on the reset controller hardware, the reset
|
||||
* signal will either stay asserted until reset_deassert() is called, or the
|
||||
* hardware may autonomously clear the reset signal itself.
|
||||
*
|
||||
* @reset_ctl: A reset control struct that was previously successfully
|
||||
* requested by reset_get_by_*().
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int reset_assert(struct reset_ctl *reset_ctl);
|
||||
|
||||
/**
|
||||
* reset_deassert - Deassert a reset signal.
|
||||
*
|
||||
* This function will deassert the specified reset signal, thus releasing the
|
||||
* affected HW modules() from reset, and allowing them to continue normal
|
||||
* operation.
|
||||
*
|
||||
* @reset_ctl: A reset control struct that was previously successfully
|
||||
* requested by reset_get_by_*().
|
||||
* @return 0 if OK, or a negative error code.
|
||||
*/
|
||||
int reset_deassert(struct reset_ctl *reset_ctl);
|
||||
|
||||
#endif
|
|
@ -5,5 +5,13 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o \
|
||||
fdt_empty_tree.o fdt_addresses.o fdt_region.o
|
||||
obj-y += \
|
||||
fdt.o \
|
||||
fdt_ro.o \
|
||||
fdt_rw.o \
|
||||
fdt_strerror.o \
|
||||
fdt_sw.o \
|
||||
fdt_wip.o \
|
||||
fdt_empty_tree.o \
|
||||
fdt_addresses.o \
|
||||
fdt_region.o
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
The libfdt functionality was written by David Gibson. The original
|
||||
source came from the git repository:
|
||||
source came from the Git repository:
|
||||
|
||||
URL: git://ozlabs.org/home/dgibson/git/libfdt.git
|
||||
|
||||
|
@ -11,13 +11,15 @@ commit 857f54e79f74429af20c2b5ecc00ee98af6a3b8b
|
|||
tree 2f648f0f88225a51ded452968d28b4402df8ade0
|
||||
parent 07a12a08005f3b5cd9337900a6551e450c07b515
|
||||
|
||||
To adapt for u-boot usage, only the applicable files were copied and
|
||||
imported into the u-boot git repository.
|
||||
Omitted:
|
||||
* GPL - u-boot comes with a copy of the GPL license
|
||||
* test subdirectory - not directly useful for u-boot
|
||||
To adapt for U-Boot usage, only the applicable files were copied and
|
||||
imported into the U-Boot Git repository.
|
||||
|
||||
After importing, other customizations were performed. See the git log
|
||||
for details.
|
||||
Omitted:
|
||||
|
||||
* GPL - U-Boot comes with a copy of the GPL license
|
||||
* test subdirectory - not directly useful for U-Boot
|
||||
|
||||
After importing, other customizations were performed. See the
|
||||
"git log" for details.
|
||||
|
||||
Jerry Van Baren
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
#include <libfdt_env.h>
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <fdt.h>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
#include <libfdt_env.h>
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <fdt.h>
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* Copyright (C) 2012 David Gibson, IBM Corporation.
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
|
||||
#include <libfdt_env.h>
|
||||
#include <fdt.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "libfdt_env.h"
|
||||
#include <libfdt_env.h>
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <fdt.h>
|
||||
|
@ -18,14 +18,13 @@
|
|||
|
||||
/**
|
||||
* fdt_add_region() - Add a new region to our list
|
||||
* @info: State information
|
||||
* @offset: Start offset of region
|
||||
* @size: Size of region
|
||||
*
|
||||
* The region is added if there is space, but in any case we increment the
|
||||
* count. If permitted, and the new region overlaps the last one, we merge
|
||||
* them.
|
||||
*
|
||||
* @info: State information
|
||||
* @offset: Start offset of region
|
||||
* @size: Size of region
|
||||
*/
|
||||
static int fdt_add_region(struct fdt_region_state *info, int offset, int size)
|
||||
{
|
||||
|
@ -119,6 +118,8 @@ int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
|
|||
|
||||
/**
|
||||
* fdt_include_supernodes() - Include supernodes required by this node
|
||||
* @info: State information
|
||||
* @depth: Current stack depth
|
||||
*
|
||||
* When we decided to include a node or property which is not at the top
|
||||
* level, this function forces the inclusion of higher level nodes. For
|
||||
|
@ -131,9 +132,6 @@ int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
|
|||
*
|
||||
* If we decide to include testing then we need the root node to have a valid
|
||||
* tree. This function adds those regions.
|
||||
*
|
||||
* @info: State information
|
||||
* @depth: Current stack depth
|
||||
*/
|
||||
static int fdt_include_supernodes(struct fdt_region_state *info, int depth)
|
||||
{
|
||||
|
@ -203,72 +201,78 @@ int fdt_first_region(const void *fdt,
|
|||
path, path_len, flags, info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Theory of operation
|
||||
/***********************************************************************
|
||||
*
|
||||
* Theory of operation
|
||||
*
|
||||
* Note: in this description 'included' means that a node (or other part
|
||||
* of the tree) should be included in the region list, i.e. it will have
|
||||
* a region which covers its part of the tree.
|
||||
*
|
||||
* This function maintains some state from the last time it is called.
|
||||
* It checks the next part of the tree that it is supposed to look at
|
||||
* (p.nextoffset) to see if that should be included or not. When it
|
||||
* finds something to include, it sets info->start to its offset. This
|
||||
* marks the start of the region we want to include.
|
||||
*
|
||||
* Once info->start is set to the start (i.e. not -1), we continue
|
||||
* scanning until we find something that we don't want included. This
|
||||
* will be the end of a region. At this point we can close off the
|
||||
* region and add it to the list. So we do so, and reset info->start
|
||||
* to -1.
|
||||
*
|
||||
* One complication here is that we want to merge regions. So when we
|
||||
* come to add another region later, we may in fact merge it with the
|
||||
* previous one if one ends where the other starts.
|
||||
*
|
||||
* The function fdt_add_region() will return -1 if it fails to add the
|
||||
* region, because we already have a region ready to be returned, and
|
||||
* the new one cannot be merged in with it. In this case, we must return
|
||||
* the region we found, and wait for another call to this function.
|
||||
* When it comes, we will repeat the processing of the tag and again
|
||||
* try to add a region. This time it will succeed.
|
||||
*
|
||||
* The current state of the pointers (stack, offset, etc.) is maintained
|
||||
* in a ptrs member. At the start of every loop iteration we make a copy
|
||||
* of it. The copy is then updated as the tag is processed. Only if we
|
||||
* get to the end of the loop iteration (and successfully call
|
||||
* fdt_add_region() if we need to) can we commit the changes we have
|
||||
* made to these pointers. For example, if we see an FDT_END_NODE tag,
|
||||
* we will decrement the depth value. But if we need to add a region
|
||||
* for this tag (let's say because the previous tag is included and this
|
||||
* FDT_END_NODE tag is not included) then we will only commit the result
|
||||
* if we were able to add the region. That allows us to retry again next
|
||||
* time.
|
||||
*
|
||||
* We keep track of a variable called 'want' which tells us what we want
|
||||
* to include when there is no specific information provided by the
|
||||
* h_include function for a particular property. This basically handles
|
||||
* the inclusion of properties which are pulled in by virtue of the node
|
||||
* they are in. So if you include a node, its properties are also
|
||||
* included. In this case 'want' will be WANT_NODES_AND_PROPS. The
|
||||
* FDT_REG_DIRECT_SUBNODES feature also makes use of 'want'. While we
|
||||
* are inside the subnode, 'want' will be set to WANT_NODES_ONLY, so
|
||||
* that only the subnode's FDT_BEGIN_NODE and FDT_END_NODE tags will be
|
||||
* included, and properties will be skipped. If WANT_NOTHING is
|
||||
* selected, then we will just rely on what the h_include() function
|
||||
* tells us.
|
||||
*
|
||||
* Using 'want' we work out 'include', which tells us whether this
|
||||
* current tag should be included or not. As you can imagine, if the
|
||||
* value of 'include' changes, that means we are on a boundary between
|
||||
* nodes to include and nodes to exclude. At this point we either close
|
||||
* off a previous region and add it to the list, or mark the start of a
|
||||
* new region.
|
||||
*
|
||||
* Apart from the nodes, we have mem_rsvmap, the FDT_END tag and the
|
||||
* string list. Each of these dealt with as a whole (i.e. we create a
|
||||
* region for each if it is to be included). For mem_rsvmap we don't
|
||||
* allow it to merge with the first struct region. For the stringlist,
|
||||
* we don't allow it to merge with the last struct region (which
|
||||
* contains at minimum the FDT_END tag).
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
Note: in this description 'included' means that a node (or other part of
|
||||
the tree) should be included in the region list, i.e. it will have a region
|
||||
which covers its part of the tree.
|
||||
|
||||
This function maintains some state from the last time it is called. It
|
||||
checks the next part of the tree that it is supposed to look at
|
||||
(p.nextoffset) to see if that should be included or not. When it finds
|
||||
something to include, it sets info->start to its offset. This marks the
|
||||
start of the region we want to include.
|
||||
|
||||
Once info->start is set to the start (i.e. not -1), we continue scanning
|
||||
until we find something that we don't want included. This will be the end
|
||||
of a region. At this point we can close off the region and add it to the
|
||||
list. So we do so, and reset info->start to -1.
|
||||
|
||||
One complication here is that we want to merge regions. So when we come to
|
||||
add another region later, we may in fact merge it with the previous one if
|
||||
one ends where the other starts.
|
||||
|
||||
The function fdt_add_region() will return -1 if it fails to add the region,
|
||||
because we already have a region ready to be returned, and the new one
|
||||
cannot be merged in with it. In this case, we must return the region we
|
||||
found, and wait for another call to this function. When it comes, we will
|
||||
repeat the processing of the tag and again try to add a region. This time it
|
||||
will succeed.
|
||||
|
||||
The current state of the pointers (stack, offset, etc.) is maintained in
|
||||
a ptrs member. At the start of every loop iteration we make a copy of it.
|
||||
The copy is then updated as the tag is processed. Only if we get to the end
|
||||
of the loop iteration (and successfully call fdt_add_region() if we need
|
||||
to) can we commit the changes we have made to these pointers. For example,
|
||||
if we see an FDT_END_NODE tag we will decrement the depth value. But if we
|
||||
need to add a region for this tag (let's say because the previous tag is
|
||||
included and this FDT_END_NODE tag is not included) then we will only commit
|
||||
the result if we were able to add the region. That allows us to retry again
|
||||
next time.
|
||||
|
||||
We keep track of a variable called 'want' which tells us what we want to
|
||||
include when there is no specific information provided by the h_include
|
||||
function for a particular property. This basically handles the inclusion of
|
||||
properties which are pulled in by virtue of the node they are in. So if you
|
||||
include a node, its properties are also included. In this case 'want' will
|
||||
be WANT_NODES_AND_PROPS. The FDT_REG_DIRECT_SUBNODES feature also makes use
|
||||
of 'want'. While we are inside the subnode, 'want' will be set to
|
||||
WANT_NODES_ONLY, so that only the subnode's FDT_BEGIN_NODE and FDT_END_NODE
|
||||
tags will be included, and properties will be skipped. If WANT_NOTHING is
|
||||
selected, then we will just rely on what the h_include() function tells us.
|
||||
|
||||
Using 'want' we work out 'include', which tells us whether this current tag
|
||||
should be included or not. As you can imagine, if the value of 'include'
|
||||
changes, that means we are on a boundary between nodes to include and nodes
|
||||
to exclude. At this point we either close off a previous region and add it
|
||||
to the list, or mark the start of a new region.
|
||||
|
||||
Apart from the nodes, we have mem_rsvmap, the FDT_END tag and the string
|
||||
list. Each of these dealt with as a whole (i.e. we create a region for each
|
||||
if it is to be included). For mem_rsvmap we don't allow it to merge with
|
||||
the first struct region. For the stringlist we don't allow it to merge with
|
||||
the last struct region (which contains at minimum the FDT_END tag).
|
||||
*/
|
||||
int fdt_next_region(const void *fdt,
|
||||
int (*h_include)(void *priv, const void *fdt, int offset,
|
||||
int type, const char *data, int size),
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
#include <libfdt_env.h>
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <fdt.h>
|
||||
|
@ -19,7 +19,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
|
|||
{
|
||||
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
|
||||
|
||||
if (! p)
|
||||
if (!p)
|
||||
/* short match */
|
||||
return 0;
|
||||
|
||||
|
@ -115,7 +115,7 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
|
|||
|
||||
/*
|
||||
* Find the next of path seperator, note we need to search for both '/' and ':'
|
||||
* and then take the first one so that we do the rigth thing for e.g.
|
||||
* and then take the first one so that we do the right thing for e.g.
|
||||
* "foo/bar:option" and "bar:option/otheroption", both of which happen, so
|
||||
* first searching for either ':' or '/' does not work.
|
||||
*/
|
||||
|
@ -163,7 +163,7 @@ int fdt_path_offset(const void *fdt, const char *path)
|
|||
if (*p == '\0' || *p == ':')
|
||||
return offset;
|
||||
q = fdt_path_next_seperator(p);
|
||||
if (! q)
|
||||
if (!q)
|
||||
q = end;
|
||||
|
||||
offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
|
||||
|
@ -273,7 +273,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|||
const struct fdt_property *prop;
|
||||
|
||||
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return NULL;
|
||||
|
||||
return prop->data;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
#include <libfdt_env.h>
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <fdt.h>
|
||||
|
@ -168,7 +168,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
|||
int err;
|
||||
|
||||
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
||||
if (! (*prop))
|
||||
if (!(*prop))
|
||||
return oldlen;
|
||||
|
||||
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
||||
|
@ -283,7 +283,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
|
|||
FDT_RW_CHECK_HEADER(fdt);
|
||||
|
||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return len;
|
||||
|
||||
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
#include <libfdt_env.h>
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <fdt.h>
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
|
||||
#include <libfdt_env.h>
|
||||
#include <fdt.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
#include <libfdt_env.h>
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <fdt.h>
|
||||
|
@ -21,7 +21,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
|||
int proplen;
|
||||
|
||||
propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
|
||||
if (! propval)
|
||||
if (!propval)
|
||||
return proplen;
|
||||
|
||||
if (proplen != len)
|
||||
|
@ -45,7 +45,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
|
|||
int len;
|
||||
|
||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return len;
|
||||
|
||||
_fdt_nop_region(prop, len + sizeof(*prop));
|
||||
|
|
|
@ -27,6 +27,7 @@ obj-$(CONFIG_DM_PCI) += pci.o
|
|||
obj-$(CONFIG_RAM) += ram.o
|
||||
obj-y += regmap.o
|
||||
obj-$(CONFIG_REMOTEPROC) += remoteproc.o
|
||||
obj-$(CONFIG_DM_RESET) += reset.o
|
||||
obj-$(CONFIG_SYSRESET) += sysreset.o
|
||||
obj-$(CONFIG_DM_RTC) += rtc.o
|
||||
obj-$(CONFIG_DM_SPI_FLASH) += sf.o
|
||||
|
|
114
test/dm/clk.c
114
test/dm/clk.c
|
@ -5,55 +5,99 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <asm/test.h>
|
||||
#include <asm/clk.h>
|
||||
#include <dm/test.h>
|
||||
#include <linux/err.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
/* Test that we can find and adjust clocks */
|
||||
static int dm_test_clk_base(struct unit_test_state *uts)
|
||||
static int dm_test_clk(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *clk;
|
||||
struct udevice *dev_fixed, *dev_clk, *dev_test;
|
||||
ulong rate;
|
||||
|
||||
ut_assertok(uclass_get_device(UCLASS_CLK, 0, &clk));
|
||||
rate = clk_get_rate(clk);
|
||||
ut_asserteq(SANDBOX_CLK_RATE, rate);
|
||||
ut_asserteq(-EINVAL, clk_set_rate(clk, 0));
|
||||
ut_assertok(clk_set_rate(clk, rate * 2));
|
||||
ut_asserteq(SANDBOX_CLK_RATE * 2, clk_get_rate(clk));
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-fixed",
|
||||
&dev_fixed));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_clk_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-sbox",
|
||||
&dev_clk));
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
ut_asserteq(0, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(0, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
|
||||
/* Test that peripheral clocks work as expected */
|
||||
static int dm_test_clk_periph(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *clk;
|
||||
ulong rate;
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test",
|
||||
&dev_test));
|
||||
ut_assertok(sandbox_clk_test_get(dev_test));
|
||||
|
||||
ut_assertok(uclass_get_device(UCLASS_CLK, 0, &clk));
|
||||
rate = clk_set_periph_rate(clk, PERIPH_ID_COUNT, 123);
|
||||
ut_asserteq(-EINVAL, rate);
|
||||
ut_asserteq(1, IS_ERR_VALUE(rate));
|
||||
ut_asserteq(1234,
|
||||
sandbox_clk_test_get_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_FIXED));
|
||||
ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_SPI));
|
||||
ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_I2C));
|
||||
|
||||
rate = clk_set_periph_rate(clk, PERIPH_ID_SPI, 123);
|
||||
ut_asserteq(0, rate);
|
||||
ut_asserteq(123, clk_get_periph_rate(clk, PERIPH_ID_SPI));
|
||||
|
||||
rate = clk_set_periph_rate(clk, PERIPH_ID_SPI, 1234);
|
||||
ut_asserteq(123, rate);
|
||||
|
||||
rate = clk_set_periph_rate(clk, PERIPH_ID_I2C, 567);
|
||||
|
||||
rate = clk_set_periph_rate(clk, PERIPH_ID_SPI, 1234);
|
||||
rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_FIXED,
|
||||
12345);
|
||||
ut_assert(IS_ERR_VALUE(rate));
|
||||
rate = sandbox_clk_test_get_rate(dev_test, SANDBOX_CLK_TEST_ID_FIXED);
|
||||
ut_asserteq(1234, rate);
|
||||
|
||||
ut_asserteq(567, clk_get_periph_rate(clk, PERIPH_ID_I2C));
|
||||
ut_asserteq(0, sandbox_clk_test_set_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_SPI,
|
||||
1000));
|
||||
ut_asserteq(0, sandbox_clk_test_set_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_I2C,
|
||||
2000));
|
||||
|
||||
ut_asserteq(1000, sandbox_clk_test_get_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_SPI));
|
||||
ut_asserteq(2000, sandbox_clk_test_get_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_I2C));
|
||||
|
||||
ut_asserteq(1000, sandbox_clk_test_set_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_SPI,
|
||||
10000));
|
||||
ut_asserteq(2000, sandbox_clk_test_set_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_I2C,
|
||||
20000));
|
||||
|
||||
rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_SPI, 0);
|
||||
ut_assert(IS_ERR_VALUE(rate));
|
||||
rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_I2C, 0);
|
||||
ut_assert(IS_ERR_VALUE(rate));
|
||||
|
||||
ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_SPI));
|
||||
ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_I2C));
|
||||
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
ut_asserteq(10000, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(20000, sandbox_clk_query_rate(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
|
||||
ut_assertok(sandbox_clk_test_enable(dev_test, SANDBOX_CLK_TEST_ID_SPI));
|
||||
ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
|
||||
ut_assertok(sandbox_clk_test_enable(dev_test, SANDBOX_CLK_TEST_ID_I2C));
|
||||
ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
|
||||
ut_assertok(sandbox_clk_test_disable(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_SPI));
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(1, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
|
||||
ut_assertok(sandbox_clk_test_disable(dev_test,
|
||||
SANDBOX_CLK_TEST_ID_I2C));
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
|
||||
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
|
||||
|
||||
ut_assertok(sandbox_clk_test_free(dev_test));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_clk_periph, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||
DM_TEST(dm_test_clk, DM_TESTF_SCAN_FDT);
|
||||
|
|
39
test/dm/reset.c
Normal file
39
test/dm/reset.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/test.h>
|
||||
#include <asm/reset.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
/* This must match the specifier for mbox-names="test" in the DT node */
|
||||
#define TEST_RESET_ID 2
|
||||
|
||||
static int dm_test_reset(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev_reset;
|
||||
struct udevice *dev_test;
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl",
|
||||
&dev_reset));
|
||||
ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
|
||||
&dev_test));
|
||||
ut_assertok(sandbox_reset_test_get(dev_test));
|
||||
|
||||
ut_assertok(sandbox_reset_test_assert(dev_test));
|
||||
ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID));
|
||||
|
||||
ut_assertok(sandbox_reset_test_deassert(dev_test));
|
||||
ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
|
||||
|
||||
ut_assertok(sandbox_reset_test_free(dev_test));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_reset, DM_TESTF_SCAN_FDT);
|
Loading…
Add table
Reference in a new issue