diff options
author | Tom Rini <trini@konsulko.com> | 2016-06-20 05:14:01 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-06-20 05:14:01 -0400 |
commit | 09849f4a7779a247be8af5cfae44f7aad30e1222 (patch) | |
tree | 50891a9305714eff354702443555f52f1a65463c | |
parent | 7c8ef0feb97586d35b0296b48903daef8c06ab21 (diff) | |
parent | 135aa95002646c46e89de93fa36adad1b010548f (diff) | |
download | talos-obmc-uboot-09849f4a7779a247be8af5cfae44f7aad30e1222.tar.gz talos-obmc-uboot-09849f4a7779a247be8af5cfae44f7aad30e1222.zip |
Merge git://git.denx.de/u-boot-dm
77 files changed, 2028 insertions, 687 deletions
diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi index 18b6a26643..fce34fa650 100644 --- a/arch/arm/dts/tegra186.dtsi +++ b/arch/arm/dts/tegra186.dtsi @@ -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"; diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h index d66b26f18e..317e5128ed 100644 --- a/arch/arm/include/asm/arch-rockchip/clock.h +++ b/arch/arm/include/asm/arch-rockchip/clock.h @@ -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; diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index 133d66341b..816540e582 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -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; diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c index 2e21282335..55ac73e9d2 100644 --- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c +++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c @@ -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; diff --git a/arch/arm/mach-snapdragon/clock-apq8016.c b/arch/arm/mach-snapdragon/clock-apq8016.c index d548d757d3..c2cf92494a 100644 --- a/arch/arm/mach-snapdragon/clock-apq8016.c +++ b/arch/arm/mach-snapdragon/clock-apq8016.c @@ -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[] = { diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index b18a12e342..f4affa5512 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -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 diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c index 6444be8f03..40383c11c9 100644 --- a/arch/arm/mach-zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c @@ -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> diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c index f2ee911df4..ac33391921 100644 --- a/arch/mips/mach-pic32/cpu.c +++ b/arch/mips/mach-pic32/cpu.c @@ -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 diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 686c215aea..9e46f9e815 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -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"; diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h new file mode 100644 index 0000000000..9dc6c8184b --- /dev/null +++ b/arch/sandbox/include/asm/clk.h @@ -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 diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h index 427af2c970..73b42f0f08 100644 --- a/arch/sandbox/include/asm/gpio.h +++ b/arch/sandbox/include/asm/gpio.h @@ -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, diff --git a/arch/sandbox/include/asm/reset.h b/arch/sandbox/include/asm/reset.h new file mode 100644 index 0000000000..7146aa5ab2 --- /dev/null +++ b/arch/sandbox/include/asm/reset.h @@ -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 diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 224b0ebaf9..451a78e590 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -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, diff --git a/board/microchip/pic32mzda/pic32mzda.c b/board/microchip/pic32mzda/pic32mzda.c index afe2ab8b71..3d31d3d062 100644 --- a/board/microchip/pic32mzda/pic32mzda.c +++ b/board/microchip/pic32mzda/pic32mzda.c @@ -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; } diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 4eb3c224fd..94253a65e4 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -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 diff --git a/doc/device-tree-bindings/reset/reset.txt b/doc/device-tree-bindings/reset/reset.txt new file mode 100644 index 0000000000..31db6ff849 --- /dev/null +++ b/doc/device-tree-bindings/reset/reset.txt @@ -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. diff --git a/drivers/Kconfig b/drivers/Kconfig index f2a137ad87..f6003a0a59 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -56,6 +56,8 @@ source "drivers/ram/Kconfig" source "drivers/remoteproc/Kconfig" +source "drivers/reset/Kconfig" + source "drivers/rtc/Kconfig" source "drivers/serial/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index db5317c9c7..1723958857 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -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/ diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 81fe600188..f7a88912e0 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -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/ diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index b483c1ef33..6e4d67220a 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -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); + return (struct clk_ops *)dev->driver->ops; } -ulong clk_set_rate(struct udevice *dev, ulong rate) +#if CONFIG_IS_ENABLED(OF_CONTROL) +#ifdef CONFIG_SPL_BUILD +int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) { - struct clk_ops *ops = clk_get_ops(dev); + int ret; + u32 cell[2]; - if (!ops->set_rate) + if (index != 0) return -ENOSYS; - - return ops->set_rate(dev, rate); + 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; + clk->id = cell[1]; + return 0; } -int clk_enable(struct udevice *dev, int periph) +int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk) { - struct clk_ops *ops = clk_get_ops(dev); - - if (!ops->enable) - return -ENOSYS; - - return ops->enable(dev, periph); + return -ENOSYS; } - -ulong clk_get_periph_rate(struct udevice *dev, int periph) +#else +static int clk_of_xlate_default(struct clk *clk, + struct fdtdec_phandle_args *args) { - struct clk_ops *ops = clk_get_ops(dev); + debug("%s(clk=%p)\n", __func__, clk); - 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 (args->args_count > 1) { + debug("Invaild args_count: %d\n", args->args_count); + return -EINVAL; + } - if (!ops->set_periph_rate) - return -ENOSYS; + if (args->args_count) + clk->id = args->args[0]; + else + clk->id = 0; - return ops->set_periph_rate(dev, periph, rate); + return 0; } -#if CONFIG_IS_ENABLED(OF_CONTROL) -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) { 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); - 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; + struct udevice *dev_clk; + struct clk_ops *ops; + + debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk); - assert(*clk_devp); + 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, diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index 8beda9cb55..797e537907 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -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) diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c index 5d883544d5..70ec3543cf 100644 --- a/drivers/clk/clk_pic32.c +++ b/drivers/clk/clk_pic32.c @@ -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) diff --git a/drivers/clk/clk_rk3036.c b/drivers/clk/clk_rk3036.c index 7ec65bdff0..6202c9da5d 100644 --- a/drivers/clk/clk_rk3036.c +++ b/drivers/clk/clk_rk3036.c @@ -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) -{ - struct rk3036_clk_plat *plat = dev_get_platdata(dev); - struct rk3036_clk_priv *priv = dev_get_priv(dev); - - debug("%s\n", dev->name); - return rkclk_pll_get_rate(priv->cru, plat->clk_id); -} - -static ulong rk3036_clk_set_rate(struct udevice *dev, ulong rate) +static ulong rk3036_clk_get_rate(struct clk *clk) { - debug("%s\n", dev->name); + struct rk3036_clk_priv *priv = dev_get_priv(clk->dev); - return 0; + switch (clk->id) { + case 0 ... 63: + return rkclk_pll_get_rate(priv->cru, clk->id); + default: + return -ENOENT; + } } -static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate) +static ulong rk3036_clk_set_rate(struct clk *clk, ulong rate) { - struct rk3036_clk_priv *priv = dev_get_priv(dev); - ulong new_rate; + struct rk3036_clk_priv *priv = dev_get_priv(clk->dev); + ulong new_rate, gclk_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, diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c index d88893c8ea..2285453e8d 100644 --- a/drivers/clk/clk_rk3288.c +++ b/drivers/clk/clk_rk3288.c @@ -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, diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c index 367130f8b7..c6bd7c64e2 100644 --- a/drivers/clk/clk_sandbox.c +++ b/drivers/clk/clk_sandbox.c @@ -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); + + if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT) + return -EINVAL; - return priv->rate; + 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); + old_rate = priv->rate[clk->id]; + priv->rate[clk->id] = rate; - if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT) - return -EINVAL; - return priv->periph_rate[periph]; + return old_rate; } -static ulong sandbox_set_periph_rate(struct udevice *dev, int periph, - ulong rate) +static int sandbox_clk_enable(struct clk *clk) { - struct sandbox_clk_priv *priv = dev_get_priv(dev); - ulong old_rate; + struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); - if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT) + if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT) return -EINVAL; - old_rate = priv->periph_rate[periph]; - priv->periph_rate[periph] = rate; - return old_rate; + priv->enabled[clk->id] = true; + + return 0; } -static int sandbox_clk_probe(struct udevice *dev) +static int sandbox_clk_disable(struct clk *clk) { - struct sandbox_clk_priv *priv = dev_get_priv(dev); + struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); + + if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT) + return -EINVAL; - priv->rate = SANDBOX_CLK_RATE; + 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]; +} diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c new file mode 100644 index 0000000000..999100de9d --- /dev/null +++ b/drivers/clk/clk_sandbox_test.c @@ -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), +}; diff --git a/drivers/clk/exynos/clk-exynos7420.c b/drivers/clk/exynos/clk-exynos7420.c index bf5d0e6e60..1f017a307f 100644 --- a/drivers/clk/exynos/clk-exynos7420.c +++ b/drivers/clk/exynos/clk-exynos7420.c @@ -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[] = { diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c index 25c163b395..2f5d4d8391 100644 --- a/drivers/clk/uniphier/clk-uniphier-core.c +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -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) diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c index c6ecd119bd..2dd3fc074a 100644 --- a/drivers/clk/uniphier/clk-uniphier-mio.c +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include <clk.h> #include <dm/device.h> #include "clk-uniphier.h" diff --git a/drivers/core/root.c b/drivers/core/root.c index 13c2713e61..95886add23 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -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); diff --git a/drivers/gpio/pca953x_gpio.c b/drivers/gpio/pca953x_gpio.c index 065b181bd2..0410add518 100644 --- a/drivers/gpio/pca953x_gpio.c +++ b/drivers/gpio/pca953x_gpio.c @@ -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, diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c index 3fceade61e..63b141838b 100644 --- a/drivers/i2c/rk_i2c.c +++ b/drivers/i2c/rk_i2c.c @@ -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; } diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 9087512390..9649b70589 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -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 diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index bbae4def6d..155dbeb099 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -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 diff --git a/drivers/mailbox/mailbox-uclass.c b/drivers/mailbox/mailbox-uclass.c index 73fa32874a..40f851d915 100644 --- a/drivers/mailbox/mailbox-uclass.c +++ b/drivers/mailbox/mailbox-uclass.c @@ -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; diff --git a/drivers/mailbox/sandbox-mbox-test.c b/drivers/mailbox/sandbox-mbox-test.c index 02d161aada..8351522bd4 100644 --- a/drivers/mailbox/sandbox-mbox-test.c +++ b/drivers/mailbox/sandbox-mbox-test.c @@ -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 { diff --git a/drivers/mailbox/sandbox-mbox.c b/drivers/mailbox/sandbox-mbox.c index 1b7ac231cb..530c62c029 100644 --- a/drivers/mailbox/sandbox-mbox.c +++ b/drivers/mailbox/sandbox-mbox.c @@ -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> diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c new file mode 100644 index 0000000000..5c781a50b6 --- /dev/null +++ b/drivers/mailbox/tegra-hsp.c @@ -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, +}; diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index 1e2a29b825..64bbf0cd25 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -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; diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index 750ab9f8c5..d41d60ce35 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -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)) diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 4978cca76d..152e987397 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -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; diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig new file mode 100644 index 0000000000..0fe8cc3827 --- /dev/null +++ b/drivers/reset/Kconfig @@ -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 diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile new file mode 100644 index 0000000000..71f3b21961 --- /dev/null +++ b/drivers/reset/Makefile @@ -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 diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c new file mode 100644 index 0000000000..edaecfbc99 --- /dev/null +++ b/drivers/reset/reset-uclass.c @@ -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", +}; diff --git a/drivers/reset/sandbox-reset-test.c b/drivers/reset/sandbox-reset-test.c new file mode 100644 index 0000000000..e37d6c91ef --- /dev/null +++ b/drivers/reset/sandbox-reset-test.c @@ -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), +}; diff --git a/drivers/reset/sandbox-reset.c b/drivers/reset/sandbox-reset.c new file mode 100644 index 0000000000..4258af521b --- /dev/null +++ b/drivers/reset/sandbox-reset.c @@ -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; +} diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index 80fb89ea8b..a7cab1346f 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -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; diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c index af9fbbf655..c2141f0a08 100644 --- a/drivers/serial/serial_pic32.c +++ b/drivers/serial/serial_pic32.c @@ -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); diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index cb55c5ab71..622547951e 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -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 diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c index 9eff423acd..bc6dfd8862 100644 --- a/drivers/spi/rk_spi.c +++ b/drivers/spi/rk_spi.c @@ -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; diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 4444988e36..e0377ca1c9 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -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); diff --git a/drivers/video/rockchip/rk_edp.c b/drivers/video/rockchip/rk_edp.c index 124ddf684b..7ece038c8f 100644 --- a/drivers/video/rockchip/rk_edp.c +++ b/drivers/video/rockchip/rk_edp.c @@ -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", diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c index 5fcb61ac2a..8dd2c87090 100644 --- a/drivers/video/rockchip/rk_hdmi.c +++ b/drivers/video/rockchip/rk_hdmi.c @@ -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", diff --git a/drivers/video/rockchip/rk_lvds.c b/drivers/video/rockchip/rk_lvds.c index dc10b866c9..fcbb4d63d2 100644 --- a/drivers/video/rockchip/rk_lvds.c +++ b/drivers/video/rockchip/rk_lvds.c @@ -5,7 +5,6 @@ */ #include <common.h> -#include <clk.h> #include <display.h> #include <dm.h> #include <edid.h> diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c index db09d9a41d..cc26f1956d 100644 --- a/drivers/video/rockchip/rk_vop.c +++ b/drivers/video/rockchip/rk_vop.c @@ -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; diff --git a/include/clk-uclass.h b/include/clk-uclass.h new file mode 100644 index 0000000000..07c1065495 --- /dev/null +++ b/include/clk-uclass.h @@ -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 diff --git a/include/clk.h b/include/clk.h index ca20c3dd27..2f31cf70e3 100644 --- a/include/clk.h +++ b/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> -struct udevice; +/** + * 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. + */ -int soc_clk_dump(void); +struct udevice; -struct clk_ops { - /** - * get_rate() - Get current clock rate - * - * @dev: Device to check (UCLASS_CLK) - * @return clock rate in Hz, or -ve error code - */ - 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 +/** + * 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 (*set_periph_rate)(struct udevice *dev, int periph, ulong rate); + unsigned long id; }; -#define clk_get_ops(dev) ((struct clk_ops *)(dev)->driver->ops) +#if CONFIG_IS_ENABLED(OF_CONTROL) +/** + * clock_get_by_index - Get/request a clock by integer index. + * + * 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: 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 clk *clk); /** - * clk_get_rate() - Get current clock rate + * clock_get_by_name - Get/request a clock by name. * - * @dev: Device to check (UCLASS_CLK) - * @return clock rate in Hz, or -ve error code + * 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. */ -ulong clk_get_rate(struct udevice *dev); +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 clk *clk) +{ + return -ENOSYS; +} + +static int clk_get_by_name(struct udevice *dev, const char *name, + struct clk *clk) +{ + return -ENOSYS; +} +#endif /** - * clk_set_rate() - Set current clock rate + * clk_request - Request a clock by provider-specific ID. * - * @dev: Device to adjust - * @rate: New clock rate in Hz - * @return new rate, or -ve error code + * 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. */ -ulong clk_set_rate(struct udevice *dev, ulong rate); +int clk_request(struct udevice *dev, struct clk *clk); /** - * clk_enable() - Enable the clock for a peripheral + * clock_free - Free a previously requested clock. * - * @dev: clock provider - * @periph: Peripheral ID to enable - * @return zero on success, or -ve error code + * @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_enable(struct udevice *dev, int periph); +int clk_free(struct clk *clk); /** - * clk_get_periph_rate() - Get current clock rate for a peripheral + * clk_get_rate() - Get current clock rate. * - * @dev: Device to check (UCLASS_CLK) - * @return clock rate in Hz, -ve error code + * @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_periph_rate(struct udevice *dev, int periph); +ulong clk_get_rate(struct clk *clk); /** - * clk_set_periph_rate() - Set current clock rate for a peripheral + * clk_set_rate() - Set current clock rate. * - * @dev: Device to update (UCLASS_CLK) - * @periph: Peripheral ID to update - * @return new clock rate in Hz, or -ve error code + * @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_periph_rate(struct udevice *dev, int periph, ulong rate); +ulong clk_set_rate(struct clk *clk, ulong rate); -#if CONFIG_IS_ENABLED(OF_CONTROL) /** - * clk_get_by_index() - look up a clock referenced by a device + * clk_enable() - Enable (turn on) a clock. * - * Parse a device's 'clocks' list, returning information on the indexed clock, - * ensuring that it is activated. + * @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. * - * @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 + * @clk: A clock struct that was previously successfully requested by + * clk_request/get_by_*(). + * @return zero on success, or -ve error code. */ -int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp); -#else -static inline int clk_get_by_index(struct udevice *dev, int index, - struct udevice **clk_devp) -{ - return -ENOSYS; -} -#endif +int clk_disable(struct clk *clk); -#endif /* _CLK_H_ */ +int soc_clk_dump(void); + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 0777cbe27e..b768660e85 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -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 */ diff --git a/include/dt-bindings/mailbox/tegra-hsp.h b/include/dt-bindings/mailbox/tegra-hsp.h new file mode 100644 index 0000000000..e8c23fa91d --- /dev/null +++ b/include/dt-bindings/mailbox/tegra-hsp.h @@ -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 diff --git a/include/mailbox_uclass.h b/include/mailbox-uclass.h index 6a2994c34c..6ec62e5a0e 100644 --- a/include/mailbox_uclass.h +++ b/include/mailbox-uclass.h @@ -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; diff --git a/include/mailbox_client.h b/include/mailbox.h index 8345ea0bf1..a92a1a590d 100644 --- a/include/mailbox_client.h +++ b/include/mailbox.h @@ -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, diff --git a/include/reset-uclass.h b/include/reset-uclass.h new file mode 100644 index 0000000000..50adeca757 --- /dev/null +++ b/include/reset-uclass.h @@ -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 diff --git a/include/reset.h b/include/reset.h new file mode 100644 index 0000000000..dc0900f96a --- /dev/null +++ b/include/reset.h @@ -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 diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile index 934d6142c3..8b86c15904 100644 --- a/lib/libfdt/Makefile +++ b/lib/libfdt/Makefile @@ -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 diff --git a/lib/libfdt/README b/lib/libfdt/README index e0598761f9..db40ab25e8 100644 --- a/lib/libfdt/README +++ b/lib/libfdt/README @@ -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. +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 -After importing, other customizations were performed. See the git log -for details. + * 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 diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c index e146aba6eb..96017a15a2 100644 --- a/lib/libfdt/fdt.c +++ b/lib/libfdt/fdt.c @@ -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> diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c index 76054d98e5..b6bc66ea32 100644 --- a/lib/libfdt/fdt_addresses.c +++ b/lib/libfdt/fdt_addresses.c @@ -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> diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c index 34f1c84431..6fde1eb9ed 100644 --- a/lib/libfdt/fdt_empty_tree.c +++ b/lib/libfdt/fdt_empty_tree.c @@ -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> diff --git a/lib/libfdt/fdt_region.c b/lib/libfdt/fdt_region.c index 747d8bb86a..d2ce4c1c53 100644 --- a/lib/libfdt/fdt_region.c +++ b/lib/libfdt/fdt_region.c @@ -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), diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index 7b0777b67e..12214c2dc2 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -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; diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c index 1a358a8ca0..e7321ccae4 100644 --- a/lib/libfdt/fdt_rw.c +++ b/lib/libfdt/fdt_rw.c @@ -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); diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c index 2f3cc243db..3b7e1683d0 100644 --- a/lib/libfdt/fdt_strerror.c +++ b/lib/libfdt/fdt_strerror.c @@ -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> diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c index 345a3acbf8..70fd026550 100644 --- a/lib/libfdt/fdt_sw.c +++ b/lib/libfdt/fdt_sw.c @@ -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> diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c index 3f2dfa573b..9fe988655f 100644 --- a/lib/libfdt/fdt_wip.c +++ b/lib/libfdt/fdt_wip.c @@ -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)); diff --git a/test/dm/Makefile b/test/dm/Makefile index 9eaf04b9ba..cad3374e43 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -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 diff --git a/test/dm/clk.c b/test/dm/clk.c index 9ff6d95103..712a1e674a 100644 --- a/test/dm/clk.c +++ b/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 = 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); - rate = clk_set_periph_rate(clk, PERIPH_ID_SPI, 1234); - ut_asserteq(123, rate); + 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)); - rate = clk_set_periph_rate(clk, PERIPH_ID_I2C, 567); + 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)); - rate = clk_set_periph_rate(clk, PERIPH_ID_SPI, 1234); - ut_asserteq(1234, rate); + 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_asserteq(567, clk_get_periph_rate(clk, PERIPH_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); diff --git a/test/dm/reset.c b/test/dm/reset.c new file mode 100644 index 0000000000..0ae8031540 --- /dev/null +++ b/test/dm/reset.c @@ -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); |