mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
Merge branches 'clk-socfpga', 'clk-toshiba', 'clk-st' and 'clk-bitmain' into clk-next
- Clock and reset driver for Toshiba Visconti SoCs * clk-socfpga: clk: socfpga: s10: Make use of the helper function devm_platform_ioremap_resource() clk: socfpga: agilex: Make use of the helper function devm_platform_ioremap_resource() clk: socfpga: remove redundant assignment after a mask operation clk: socfpga: remove redundant assignment on division * clk-toshiba: clk: visconti: Remove pointless NULL check in visconti_pll_add_lookup() MAINTAINERS: Add entries for Toshiba Visconti PLL and clock controller clk: visconti: Add support common clock driver and reset driver dt-bindings: clock: Add DT bindings for SMU of Toshiba Visconti TMPV770x SoC dt-bindings: clock: Add DT bindings for PLL of Toshiba Visconti TMPV770x SoC * clk-st: clk: Drop unused COMMON_CLK_STM32MP157_SCMI config clk: st: clkgen-mux: search reg within node or parent clk: st: clkgen-fsyn: search reg within node or parent * clk-bitmain: clk: bm1880: remove kfrees on static allocations
This commit is contained in:
commit
1d0bd126d9
@ -0,0 +1,57 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/toshiba,tmpv770x-pipllct.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Toshiba Visconti5 TMPV770X PLL Controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
|
||||
description:
|
||||
Toshia Visconti5 PLL controller which supports the PLLs on TMPV770X.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: toshiba,tmpv7708-pipllct
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
description: External reference clock (OSC2)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
osc2_clk: osc2-clk {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <20000000>;
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pipllct: clock-controller@24220000 {
|
||||
compatible = "toshiba,tmpv7708-pipllct";
|
||||
reg = <0 0x24220000 0 0x820>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&osc2_clk>;
|
||||
};
|
||||
};
|
||||
...
|
@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/toshiba,tmpv770x-pismu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Toshiba Visconti5 TMPV770x SMU controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
|
||||
description:
|
||||
Toshia Visconti5 SMU (System Management Unit) which supports the clock
|
||||
and resets on TMPV770x.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: toshiba,tmpv7708-pismu
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- "#reset-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pismu: syscon@24200000 {
|
||||
compatible = "toshiba,tmpv7708-pismu", "syscon";
|
||||
reg = <0 0x24200000 0 0x2140>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
@ -2782,12 +2782,15 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwamatsu/linux-visconti.git
|
||||
F: Documentation/devicetree/bindings/arm/toshiba.yaml
|
||||
F: Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pipllct.yaml
|
||||
F: Documentation/devicetree/bindings/clock/toshiba,tmpv770x-pismu.yaml
|
||||
F: Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/toshiba,gpio-visconti.yaml
|
||||
F: Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml
|
||||
F: Documentation/devicetree/bindings/pinctrl/toshiba,visconti-pinctrl.yaml
|
||||
F: Documentation/devicetree/bindings/watchdog/toshiba,visconti-wdt.yaml
|
||||
F: arch/arm64/boot/dts/toshiba/
|
||||
F: drivers/clk/visconti/
|
||||
F: drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
|
||||
F: drivers/gpio/gpio-visconti.c
|
||||
F: drivers/pci/controller/dwc/pcie-visconti.c
|
||||
|
@ -354,16 +354,6 @@ config COMMON_CLK_STM32MP157
|
||||
help
|
||||
Support for stm32mp157 SoC family clocks
|
||||
|
||||
config COMMON_CLK_STM32MP157_SCMI
|
||||
bool "stm32mp157 Clock driver with Trusted Firmware"
|
||||
depends on COMMON_CLK_STM32MP157
|
||||
select COMMON_CLK_SCMI
|
||||
select ARM_SCMI_PROTOCOL
|
||||
default y
|
||||
help
|
||||
Support for stm32mp157 SoC family clocks with Trusted Firmware using
|
||||
SCMI protocol.
|
||||
|
||||
config COMMON_CLK_STM32F
|
||||
def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746)
|
||||
help
|
||||
@ -432,6 +422,7 @@ source "drivers/clk/sunxi-ng/Kconfig"
|
||||
source "drivers/clk/tegra/Kconfig"
|
||||
source "drivers/clk/ti/Kconfig"
|
||||
source "drivers/clk/uniphier/Kconfig"
|
||||
source "drivers/clk/visconti/Kconfig"
|
||||
source "drivers/clk/x86/Kconfig"
|
||||
source "drivers/clk/xilinx/Kconfig"
|
||||
source "drivers/clk/zynqmp/Kconfig"
|
||||
|
@ -118,6 +118,7 @@ obj-y += ti/
|
||||
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_ARCH_U8500) += ux500/
|
||||
obj-y += versatile/
|
||||
obj-$(CONFIG_COMMON_CLK_VISCONTI) += visconti/
|
||||
ifeq ($(CONFIG_COMMON_CLK), y)
|
||||
obj-$(CONFIG_X86) += x86/
|
||||
endif
|
||||
|
@ -522,14 +522,6 @@ static struct clk_hw *bm1880_clk_register_pll(struct bm1880_pll_hw_clock *pll_cl
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void bm1880_clk_unregister_pll(struct clk_hw *hw)
|
||||
{
|
||||
struct bm1880_pll_hw_clock *pll_hw = to_bm1880_pll_clk(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(pll_hw);
|
||||
}
|
||||
|
||||
static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks,
|
||||
int num_clks,
|
||||
struct bm1880_clock_data *data)
|
||||
@ -555,7 +547,7 @@ static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks,
|
||||
|
||||
err_clk:
|
||||
while (i--)
|
||||
bm1880_clk_unregister_pll(data->hw_data.hws[clks[i].pll.id]);
|
||||
clk_hw_unregister(data->hw_data.hws[clks[i].pll.id]);
|
||||
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
@ -695,14 +687,6 @@ static struct clk_hw *bm1880_clk_register_div(struct bm1880_div_hw_clock *div_cl
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void bm1880_clk_unregister_div(struct clk_hw *hw)
|
||||
{
|
||||
struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);
|
||||
|
||||
clk_hw_unregister(hw);
|
||||
kfree(div_hw);
|
||||
}
|
||||
|
||||
static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks,
|
||||
int num_clks,
|
||||
struct bm1880_clock_data *data)
|
||||
@ -729,7 +713,7 @@ static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks,
|
||||
|
||||
err_clk:
|
||||
while (i--)
|
||||
bm1880_clk_unregister_div(data->hw_data.hws[clks[i].div.id]);
|
||||
clk_hw_unregister(data->hw_data.hws[clks[i].div.id]);
|
||||
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
|
@ -500,12 +500,10 @@ static int n5x_clkmgr_init(struct platform_device *pdev)
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct stratix10_clock_data *clk_data;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int i, num_clks;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@ -34,7 +34,7 @@ static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
|
||||
|
||||
if (streq(name, SOCFPGA_L4_MP_CLK)) {
|
||||
l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
|
||||
return l4_src &= 0x1;
|
||||
return l4_src & 0x1;
|
||||
}
|
||||
if (streq(name, SOCFPGA_L4_SP_CLK)) {
|
||||
l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
|
||||
@ -43,7 +43,7 @@ static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
|
||||
|
||||
perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
|
||||
if (streq(name, SOCFPGA_MMC_CLK))
|
||||
return perpll_src &= 0x3;
|
||||
return perpll_src & 0x3;
|
||||
if (streq(name, SOCFPGA_NAND_CLK) ||
|
||||
streq(name, SOCFPGA_NAND_X_CLK))
|
||||
return (perpll_src >> 2) & 3;
|
||||
|
@ -113,7 +113,7 @@ static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
|
||||
SWCTRLBTCLKSEL_MASK) >>
|
||||
SWCTRLBTCLKSEL_SHIFT);
|
||||
div += 1;
|
||||
return parent_rate /= div;
|
||||
return parent_rate / div;
|
||||
}
|
||||
|
||||
|
||||
|
@ -388,12 +388,10 @@ static int s10_clkmgr_init(struct platform_device *pdev)
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct stratix10_clock_data *clk_data;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int i, num_clks;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base)) {
|
||||
pr_err("%s: failed to map clock registers\n", __func__);
|
||||
return PTR_ERR(base);
|
||||
|
@ -988,9 +988,18 @@ static void __init st_of_quadfs_setup(struct device_node *np,
|
||||
void __iomem *reg;
|
||||
spinlock_t *lock;
|
||||
|
||||
/*
|
||||
* First check for reg property within the node to keep backward
|
||||
* compatibility, then if reg doesn't exist look at the parent node
|
||||
*/
|
||||
reg = of_iomap(np, 0);
|
||||
if (!reg)
|
||||
return;
|
||||
if (!reg) {
|
||||
reg = of_iomap(of_get_parent(np), 0);
|
||||
if (!reg) {
|
||||
pr_err("%s: Failed to get base address\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
clk_parent_name = of_clk_get_parent_name(np, 0);
|
||||
if (!clk_parent_name)
|
||||
|
@ -57,10 +57,17 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np,
|
||||
const char **parents;
|
||||
int num_parents = 0;
|
||||
|
||||
/*
|
||||
* First check for reg property within the node to keep backward
|
||||
* compatibility, then if reg doesn't exist look at the parent node
|
||||
*/
|
||||
reg = of_iomap(np, 0);
|
||||
if (!reg) {
|
||||
pr_err("%s: Failed to get base address\n", __func__);
|
||||
return;
|
||||
reg = of_iomap(of_get_parent(np), 0);
|
||||
if (!reg) {
|
||||
pr_err("%s: Failed to get base address\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
parents = clkgen_mux_get_parents(np, &num_parents);
|
||||
|
9
drivers/clk/visconti/Kconfig
Normal file
9
drivers/clk/visconti/Kconfig
Normal file
@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config COMMON_CLK_VISCONTI
|
||||
bool "Support for Toshiba Visconti5 ARM SoC clock controllers"
|
||||
depends on ARCH_VISCONTI || COMPILE_TEST
|
||||
default ARCH_VISCONTI
|
||||
help
|
||||
Support for the Toshiba Visconti5 ARM SoC clock controller.
|
||||
Say Y if you want to include clock support.
|
5
drivers/clk/visconti/Makefile
Normal file
5
drivers/clk/visconti/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Makefile for Toshiba Visconti clock
|
||||
|
||||
obj-y += clkc.o pll.o reset.o
|
||||
obj-y += pll-tmpv770x.o clkc-tmpv770x.o
|
291
drivers/clk/visconti/clkc-tmpv770x.c
Normal file
291
drivers/clk/visconti/clkc-tmpv770x.c
Normal file
@ -0,0 +1,291 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Toshiba Visconti clock controller
|
||||
*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
* Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <dt-bindings/clock/toshiba,tmpv770x.h>
|
||||
#include <dt-bindings/reset/toshiba,tmpv770x.h>
|
||||
|
||||
#include "clkc.h"
|
||||
#include "reset.h"
|
||||
|
||||
static DEFINE_SPINLOCK(tmpv770x_clk_lock);
|
||||
static DEFINE_SPINLOCK(tmpv770x_rst_lock);
|
||||
|
||||
static const struct clk_parent_data clks_parent_data[] = {
|
||||
{ .fw_name = "pipll1", .name = "pipll1", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data pietherplls_parent_data[] = {
|
||||
{ .fw_name = "pietherpll", .name = "pietherpll", },
|
||||
};
|
||||
|
||||
static const struct visconti_fixed_clk fixed_clk_tables[] = {
|
||||
/* PLL1 */
|
||||
/* PICMPT0/1, PITSC, PIUWDT, PISWDT, PISBUS, PIPMU, PIGPMU, PITMU */
|
||||
/* PIEMM, PIMISC, PIGCOMM, PIDCOMM, PIMBUS, PIGPIO, PIPGM */
|
||||
{ TMPV770X_CLK_PIPLL1_DIV4, "pipll1_div4", "pipll1", 0, 1, 4, },
|
||||
/* PISBUS */
|
||||
{ TMPV770X_CLK_PIPLL1_DIV2, "pipll1_div2", "pipll1", 0, 1, 2, },
|
||||
/* PICOBUS_CLK */
|
||||
{ TMPV770X_CLK_PIPLL1_DIV1, "pipll1_div1", "pipll1", 0, 1, 1, },
|
||||
/* PIDNNPLL */
|
||||
/* CONN_CLK, PIMBUS, PICRC0/1 */
|
||||
{ TMPV770X_CLK_PIDNNPLL_DIV1, "pidnnpll_div1", "pidnnpll", 0, 1, 1, },
|
||||
{ TMPV770X_CLK_PIREFCLK, "pirefclk", "osc2-clk", 0, 1, 1, },
|
||||
{ TMPV770X_CLK_WDTCLK, "wdtclk", "osc2-clk", 0, 1, 1, },
|
||||
};
|
||||
|
||||
static const struct visconti_clk_gate_table pietherpll_clk_gate_tables[] = {
|
||||
/* pietherpll */
|
||||
{ TMPV770X_CLK_PIETHER_2P5M, "piether_2p5m",
|
||||
pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data),
|
||||
CLK_SET_RATE_PARENT, 0x34, 0x134, 4, 200,
|
||||
TMPV770X_RESET_PIETHER_2P5M, },
|
||||
{ TMPV770X_CLK_PIETHER_25M, "piether_25m",
|
||||
pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data),
|
||||
CLK_SET_RATE_PARENT, 0x34, 0x134, 5, 20,
|
||||
TMPV770X_RESET_PIETHER_25M, },
|
||||
{ TMPV770X_CLK_PIETHER_50M, "piether_50m",
|
||||
pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data),
|
||||
CLK_SET_RATE_PARENT, 0x34, 0x134, 6, 10,
|
||||
TMPV770X_RESET_PIETHER_50M, },
|
||||
{ TMPV770X_CLK_PIETHER_125M, "piether_125m",
|
||||
pietherplls_parent_data, ARRAY_SIZE(pietherplls_parent_data),
|
||||
CLK_SET_RATE_PARENT, 0x34, 0x134, 7, 4,
|
||||
TMPV770X_RESET_PIETHER_125M, },
|
||||
};
|
||||
|
||||
static const struct visconti_clk_gate_table clk_gate_tables[] = {
|
||||
{ TMPV770X_CLK_HOX, "hox",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x4c, 0x14c, 0, 1,
|
||||
TMPV770X_RESET_HOX, },
|
||||
{ TMPV770X_CLK_PCIE_MSTR, "pcie_mstr",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x38, 0x138, 0, 1,
|
||||
TMPV770X_RESET_PCIE_MSTR, },
|
||||
{ TMPV770X_CLK_PCIE_AUX, "pcie_aux",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x38, 0x138, 1, 24,
|
||||
TMPV770X_RESET_PCIE_AUX, },
|
||||
{ TMPV770X_CLK_PIINTC, "piintc",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
CLK_IGNORE_UNUSED, 0x8, 0x108, 0, 2, //FIX!!
|
||||
TMPV770X_RESET_PIINTC,},
|
||||
{ TMPV770X_CLK_PIETHER_BUS, "piether_bus",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x34, 0x134, 0, 2,
|
||||
TMPV770X_RESET_PIETHER_BUS, }, /* BUS_CLK */
|
||||
{ TMPV770X_CLK_PISPI0, "pispi0",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x28, 0x128, 0, 2,
|
||||
TMPV770X_RESET_PISPI0, },
|
||||
{ TMPV770X_CLK_PISPI1, "pispi1",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x28, 0x128, 1, 2,
|
||||
TMPV770X_RESET_PISPI1, },
|
||||
{ TMPV770X_CLK_PISPI2, "pispi2",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x28, 0x128, 2, 2,
|
||||
TMPV770X_RESET_PISPI2, },
|
||||
{ TMPV770X_CLK_PISPI3, "pispi3",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x28, 0x128, 3, 2,
|
||||
TMPV770X_RESET_PISPI3,},
|
||||
{ TMPV770X_CLK_PISPI4, "pispi4",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x28, 0x128, 4, 2,
|
||||
TMPV770X_RESET_PISPI4, },
|
||||
{ TMPV770X_CLK_PISPI5, "pispi5",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x28, 0x128, 5, 2,
|
||||
TMPV770X_RESET_PISPI5},
|
||||
{ TMPV770X_CLK_PISPI6, "pispi6",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x28, 0x128, 6, 2,
|
||||
TMPV770X_RESET_PISPI6,},
|
||||
{ TMPV770X_CLK_PIUART0, "piuart0",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
//CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x2c, 0x12c, 0, 4,
|
||||
0, 0x2c, 0x12c, 0, 4,
|
||||
TMPV770X_RESET_PIUART0,},
|
||||
{ TMPV770X_CLK_PIUART1, "piuart1",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
//CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0x2c, 0x12c, 1, 4,
|
||||
0, 0x2c, 0x12c, 1, 4,
|
||||
TMPV770X_RESET_PIUART1, },
|
||||
{ TMPV770X_CLK_PIUART2, "piuart2",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x2c, 0x12c, 2, 4,
|
||||
TMPV770X_RESET_PIUART2, },
|
||||
{ TMPV770X_CLK_PIUART3, "piuart3",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x2c, 0x12c, 3, 4,
|
||||
TMPV770X_RESET_PIUART3, },
|
||||
{ TMPV770X_CLK_PII2C0, "pii2c0",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 0, 4,
|
||||
TMPV770X_RESET_PII2C0, },
|
||||
{ TMPV770X_CLK_PII2C1, "pii2c1",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 1, 4,
|
||||
TMPV770X_RESET_PII2C1, },
|
||||
{ TMPV770X_CLK_PII2C2, "pii2c2",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 2, 4,
|
||||
TMPV770X_RESET_PII2C2, },
|
||||
{ TMPV770X_CLK_PII2C3, "pii2c3",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 3, 4,
|
||||
TMPV770X_RESET_PII2C3,},
|
||||
{ TMPV770X_CLK_PII2C4, "pii2c4",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 4, 4,
|
||||
TMPV770X_RESET_PII2C4, },
|
||||
{ TMPV770X_CLK_PII2C5, "pii2c5",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 5, 4,
|
||||
TMPV770X_RESET_PII2C5, },
|
||||
{ TMPV770X_CLK_PII2C6, "pii2c6",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 6, 4,
|
||||
TMPV770X_RESET_PII2C6, },
|
||||
{ TMPV770X_CLK_PII2C7, "pii2c7",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 7, 4,
|
||||
TMPV770X_RESET_PII2C7, },
|
||||
{ TMPV770X_CLK_PII2C8, "pii2c8",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x30, 0x130, 8, 4,
|
||||
TMPV770X_RESET_PII2C8, },
|
||||
/* PIPCMIF */
|
||||
{ TMPV770X_CLK_PIPCMIF, "pipcmif",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x64, 0x164, 0, 4,
|
||||
TMPV770X_RESET_PIPCMIF, },
|
||||
/* PISYSTEM */
|
||||
{ TMPV770X_CLK_WRCK, "wrck",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x68, 0x168, 9, 32,
|
||||
-1, }, /* No reset */
|
||||
{ TMPV770X_CLK_PICKMON, "pickmon",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x10, 0x110, 8, 4,
|
||||
TMPV770X_RESET_PICKMON, },
|
||||
{ TMPV770X_CLK_SBUSCLK, "sbusclk",
|
||||
clks_parent_data, ARRAY_SIZE(clks_parent_data),
|
||||
0, 0x14, 0x114, 0, 4,
|
||||
TMPV770X_RESET_SBUSCLK, },
|
||||
};
|
||||
|
||||
static const struct visconti_reset_data clk_reset_data[] = {
|
||||
[TMPV770X_RESET_PIETHER_2P5M] = { 0x434, 0x534, 4, },
|
||||
[TMPV770X_RESET_PIETHER_25M] = { 0x434, 0x534, 5, },
|
||||
[TMPV770X_RESET_PIETHER_50M] = { 0x434, 0x534, 6, },
|
||||
[TMPV770X_RESET_PIETHER_125M] = { 0x434, 0x534, 7, },
|
||||
[TMPV770X_RESET_HOX] = { 0x44c, 0x54c, 0, },
|
||||
[TMPV770X_RESET_PCIE_MSTR] = { 0x438, 0x538, 0, },
|
||||
[TMPV770X_RESET_PCIE_AUX] = { 0x438, 0x538, 1, },
|
||||
[TMPV770X_RESET_PIINTC] = { 0x408, 0x508, 0, },
|
||||
[TMPV770X_RESET_PIETHER_BUS] = { 0x434, 0x534, 0, },
|
||||
[TMPV770X_RESET_PISPI0] = { 0x428, 0x528, 0, },
|
||||
[TMPV770X_RESET_PISPI1] = { 0x428, 0x528, 1, },
|
||||
[TMPV770X_RESET_PISPI2] = { 0x428, 0x528, 2, },
|
||||
[TMPV770X_RESET_PISPI3] = { 0x428, 0x528, 3, },
|
||||
[TMPV770X_RESET_PISPI4] = { 0x428, 0x528, 4, },
|
||||
[TMPV770X_RESET_PISPI5] = { 0x428, 0x528, 5, },
|
||||
[TMPV770X_RESET_PISPI6] = { 0x428, 0x528, 6, },
|
||||
[TMPV770X_RESET_PIUART0] = { 0x42c, 0x52c, 0, },
|
||||
[TMPV770X_RESET_PIUART1] = { 0x42c, 0x52c, 1, },
|
||||
[TMPV770X_RESET_PIUART2] = { 0x42c, 0x52c, 2, },
|
||||
[TMPV770X_RESET_PIUART3] = { 0x42c, 0x52c, 3, },
|
||||
[TMPV770X_RESET_PII2C0] = { 0x430, 0x530, 0, },
|
||||
[TMPV770X_RESET_PII2C1] = { 0x430, 0x530, 1, },
|
||||
[TMPV770X_RESET_PII2C2] = { 0x430, 0x530, 2, },
|
||||
[TMPV770X_RESET_PII2C3] = { 0x430, 0x530, 3, },
|
||||
[TMPV770X_RESET_PII2C4] = { 0x430, 0x530, 4, },
|
||||
[TMPV770X_RESET_PII2C5] = { 0x430, 0x530, 5, },
|
||||
[TMPV770X_RESET_PII2C6] = { 0x430, 0x530, 6, },
|
||||
[TMPV770X_RESET_PII2C7] = { 0x430, 0x530, 7, },
|
||||
[TMPV770X_RESET_PII2C8] = { 0x430, 0x530, 8, },
|
||||
[TMPV770X_RESET_PIPCMIF] = { 0x464, 0x564, 0, },
|
||||
[TMPV770X_RESET_PICKMON] = { 0x410, 0x510, 8, },
|
||||
[TMPV770X_RESET_SBUSCLK] = { 0x414, 0x514, 0, },
|
||||
};
|
||||
|
||||
static int visconti_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct visconti_clk_provider *ctx;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct regmap *regmap;
|
||||
int ret, i;
|
||||
|
||||
regmap = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
ctx = visconti_init_clk(dev, regmap, TMPV770X_NR_CLK);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
ret = visconti_register_reset_controller(dev, regmap, clk_reset_data,
|
||||
TMPV770X_NR_RESET,
|
||||
&visconti_reset_ops,
|
||||
&tmpv770x_rst_lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register reset controller: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < (ARRAY_SIZE(fixed_clk_tables)); i++)
|
||||
ctx->clk_data.hws[fixed_clk_tables[i].id] =
|
||||
clk_hw_register_fixed_factor(NULL,
|
||||
fixed_clk_tables[i].name,
|
||||
fixed_clk_tables[i].parent,
|
||||
fixed_clk_tables[i].flag,
|
||||
fixed_clk_tables[i].mult,
|
||||
fixed_clk_tables[i].div);
|
||||
|
||||
ret = visconti_clk_register_gates(ctx, clk_gate_tables,
|
||||
ARRAY_SIZE(clk_gate_tables), clk_reset_data,
|
||||
&tmpv770x_clk_lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register main clock gate: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = visconti_clk_register_gates(ctx, pietherpll_clk_gate_tables,
|
||||
ARRAY_SIZE(pietherpll_clk_gate_tables),
|
||||
clk_reset_data, &tmpv770x_clk_lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register pietherpll clock gate: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &ctx->clk_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id visconti_clk_ids[] = {
|
||||
{ .compatible = "toshiba,tmpv7708-pismu", },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver visconti_clk_driver = {
|
||||
.probe = visconti_clk_probe,
|
||||
.driver = {
|
||||
.name = "visconti-clk",
|
||||
.of_match_table = visconti_clk_ids,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(visconti_clk_driver);
|
206
drivers/clk/visconti/clkc.c
Normal file
206
drivers/clk/visconti/clkc.c
Normal file
@ -0,0 +1,206 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Toshiba Visconti clock controller
|
||||
*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
* Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "clkc.h"
|
||||
|
||||
static inline struct visconti_clk_gate *to_visconti_clk_gate(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct visconti_clk_gate, hw);
|
||||
}
|
||||
|
||||
static int visconti_gate_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct visconti_clk_gate *gate = to_visconti_clk_gate(hw);
|
||||
u32 clk = BIT(gate->ck_idx);
|
||||
u32 val;
|
||||
|
||||
regmap_read(gate->regmap, gate->ckon_offset, &val);
|
||||
return (val & clk) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void visconti_gate_clk_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct visconti_clk_gate *gate = to_visconti_clk_gate(hw);
|
||||
u32 clk = BIT(gate->ck_idx);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (!visconti_gate_clk_is_enabled(hw)) {
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
regmap_update_bits(gate->regmap, gate->ckoff_offset, clk, clk);
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
}
|
||||
|
||||
static int visconti_gate_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct visconti_clk_gate *gate = to_visconti_clk_gate(hw);
|
||||
u32 clk = BIT(gate->ck_idx);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
regmap_update_bits(gate->regmap, gate->ckon_offset, clk, clk);
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops visconti_clk_gate_ops = {
|
||||
.enable = visconti_gate_clk_enable,
|
||||
.disable = visconti_gate_clk_disable,
|
||||
.is_enabled = visconti_gate_clk_is_enabled,
|
||||
};
|
||||
|
||||
static struct clk_hw *visconti_clk_register_gate(struct device *dev,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
struct regmap *regmap,
|
||||
const struct visconti_clk_gate_table *clks,
|
||||
u32 rson_offset,
|
||||
u32 rsoff_offset,
|
||||
u8 rs_idx,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct visconti_clk_gate *gate;
|
||||
struct clk_parent_data *pdata;
|
||||
struct clk_init_data init;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pdata->name = pdata->fw_name = parent_name;
|
||||
|
||||
gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &visconti_clk_gate_ops;
|
||||
init.flags = clks->flags;
|
||||
init.parent_data = pdata;
|
||||
init.num_parents = 1;
|
||||
|
||||
gate->regmap = regmap;
|
||||
gate->ckon_offset = clks->ckon_offset;
|
||||
gate->ckoff_offset = clks->ckoff_offset;
|
||||
gate->ck_idx = clks->ck_idx;
|
||||
gate->rson_offset = rson_offset;
|
||||
gate->rsoff_offset = rsoff_offset;
|
||||
gate->rs_idx = rs_idx;
|
||||
gate->lock = lock;
|
||||
gate->hw.init = &init;
|
||||
|
||||
hw = &gate->hw;
|
||||
ret = devm_clk_hw_register(dev, hw);
|
||||
if (ret)
|
||||
hw = ERR_PTR(ret);
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
int visconti_clk_register_gates(struct visconti_clk_provider *ctx,
|
||||
const struct visconti_clk_gate_table *clks,
|
||||
int num_gate,
|
||||
const struct visconti_reset_data *reset,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct device *dev = ctx->dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_gate; i++) {
|
||||
const char *parent_div_name = clks[i].parent_data[0].name;
|
||||
struct clk_parent_data *pdata;
|
||||
u32 rson_offset, rsoff_offset;
|
||||
struct clk_hw *gate_clk;
|
||||
struct clk_hw *div_clk;
|
||||
char *dev_name;
|
||||
u8 rs_idx;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s_div", clks[i].name);
|
||||
if (!dev_name)
|
||||
return -ENOMEM;
|
||||
|
||||
if (clks[i].rs_id >= 0) {
|
||||
rson_offset = reset[clks[i].rs_id].rson_offset;
|
||||
rsoff_offset = reset[clks[i].rs_id].rsoff_offset;
|
||||
rs_idx = reset[clks[i].rs_id].rs_idx;
|
||||
} else {
|
||||
rson_offset = rsoff_offset = rs_idx = -1;
|
||||
}
|
||||
|
||||
div_clk = devm_clk_hw_register_fixed_factor(dev,
|
||||
dev_name,
|
||||
parent_div_name,
|
||||
0, 1,
|
||||
clks[i].div);
|
||||
if (IS_ERR(div_clk))
|
||||
return PTR_ERR(div_clk);
|
||||
|
||||
gate_clk = visconti_clk_register_gate(dev,
|
||||
clks[i].name,
|
||||
dev_name,
|
||||
ctx->regmap,
|
||||
&clks[i],
|
||||
rson_offset,
|
||||
rsoff_offset,
|
||||
rs_idx,
|
||||
lock);
|
||||
if (IS_ERR(gate_clk)) {
|
||||
dev_err(dev, "%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
return PTR_ERR(gate_clk);
|
||||
}
|
||||
|
||||
ctx->clk_data.hws[clks[i].id] = gate_clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct visconti_clk_provider *visconti_init_clk(struct device *dev,
|
||||
struct regmap *regmap,
|
||||
unsigned long nr_clks)
|
||||
{
|
||||
struct visconti_clk_provider *ctx;
|
||||
int i;
|
||||
|
||||
ctx = devm_kzalloc(dev, struct_size(ctx, clk_data.hws, nr_clks), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; i < nr_clks; ++i)
|
||||
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
|
||||
ctx->clk_data.num = nr_clks;
|
||||
|
||||
ctx->dev = dev;
|
||||
ctx->regmap = regmap;
|
||||
|
||||
return ctx;
|
||||
}
|
76
drivers/clk/visconti/clkc.h
Normal file
76
drivers/clk/visconti/clkc.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Toshiba Visconti clock controller
|
||||
*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
* Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
|
||||
#ifndef _VISCONTI_CLKC_H_
|
||||
#define _VISCONTI_CLKC_H_
|
||||
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "reset.h"
|
||||
|
||||
struct visconti_clk_provider {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct clk_hw_onecell_data clk_data;
|
||||
};
|
||||
|
||||
struct visconti_clk_gate_table {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const struct clk_parent_data *parent_data;
|
||||
u8 num_parents;
|
||||
u8 flags;
|
||||
u32 ckon_offset;
|
||||
u32 ckoff_offset;
|
||||
u8 ck_idx;
|
||||
unsigned int div;
|
||||
u8 rs_id;
|
||||
};
|
||||
|
||||
struct visconti_fixed_clk {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *parent;
|
||||
unsigned long flag;
|
||||
unsigned int mult;
|
||||
unsigned int div;
|
||||
};
|
||||
|
||||
struct visconti_clk_gate {
|
||||
struct clk_hw hw;
|
||||
struct regmap *regmap;
|
||||
u32 ckon_offset;
|
||||
u32 ckoff_offset;
|
||||
u8 ck_idx;
|
||||
u8 flags;
|
||||
u32 rson_offset;
|
||||
u32 rsoff_offset;
|
||||
u8 rs_idx;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
struct visconti_clk_provider *visconti_init_clk(struct device *dev,
|
||||
struct regmap *regmap,
|
||||
unsigned long nr_clks);
|
||||
int visconti_clk_register_gates(struct visconti_clk_provider *data,
|
||||
const struct visconti_clk_gate_table *clks,
|
||||
int num_gate,
|
||||
const struct visconti_reset_data *reset,
|
||||
spinlock_t *lock);
|
||||
#endif /* _VISCONTI_CLKC_H_ */
|
85
drivers/clk/visconti/pll-tmpv770x.c
Normal file
85
drivers/clk/visconti/pll-tmpv770x.c
Normal file
@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Toshiba Visconti PLL controller
|
||||
*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
* Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/toshiba,tmpv770x.h>
|
||||
|
||||
#include "pll.h"
|
||||
|
||||
static DEFINE_SPINLOCK(tmpv770x_pll_lock);
|
||||
|
||||
static const struct visconti_pll_rate_table pipll0_rates[] __initconst = {
|
||||
VISCONTI_PLL_RATE(840000000, 0x1, 0x0, 0x1, 0x54, 0x000000, 0x2, 0x1),
|
||||
VISCONTI_PLL_RATE(780000000, 0x1, 0x0, 0x1, 0x4e, 0x000000, 0x2, 0x1),
|
||||
VISCONTI_PLL_RATE(600000000, 0x1, 0x0, 0x1, 0x3c, 0x000000, 0x2, 0x1),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct visconti_pll_rate_table piddrcpll_rates[] __initconst = {
|
||||
VISCONTI_PLL_RATE(780000000, 0x1, 0x0, 0x1, 0x4e, 0x000000, 0x2, 0x1),
|
||||
VISCONTI_PLL_RATE(760000000, 0x1, 0x0, 0x1, 0x4c, 0x000000, 0x2, 0x1),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct visconti_pll_rate_table pivoifpll_rates[] __initconst = {
|
||||
VISCONTI_PLL_RATE(165000000, 0x1, 0x0, 0x1, 0x42, 0x000000, 0x4, 0x2),
|
||||
VISCONTI_PLL_RATE(148500000, 0x1, 0x1, 0x1, 0x3b, 0x666666, 0x4, 0x2),
|
||||
VISCONTI_PLL_RATE(96000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x2),
|
||||
VISCONTI_PLL_RATE(74250000, 0x1, 0x1, 0x1, 0x3b, 0x666666, 0x4, 0x4),
|
||||
VISCONTI_PLL_RATE(54000000, 0x1, 0x0, 0x1, 0x36, 0x000000, 0x5, 0x4),
|
||||
VISCONTI_PLL_RATE(48000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x4),
|
||||
VISCONTI_PLL_RATE(35750000, 0x1, 0x1, 0x1, 0x32, 0x0ccccc, 0x7, 0x4),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct visconti_pll_rate_table piimgerpll_rates[] __initconst = {
|
||||
VISCONTI_PLL_RATE(165000000, 0x1, 0x0, 0x1, 0x42, 0x000000, 0x4, 0x2),
|
||||
VISCONTI_PLL_RATE(96000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x2),
|
||||
VISCONTI_PLL_RATE(54000000, 0x1, 0x0, 0x1, 0x36, 0x000000, 0x5, 0x4),
|
||||
VISCONTI_PLL_RATE(48000000, 0x1, 0x0, 0x1, 0x30, 0x000000, 0x5, 0x4),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct visconti_pll_info pll_info[] __initconst = {
|
||||
{ TMPV770X_PLL_PIPLL0, "pipll0", "osc2-clk", 0x0, pipll0_rates },
|
||||
{ TMPV770X_PLL_PIDDRCPLL, "piddrcpll", "osc2-clk", 0x500, piddrcpll_rates },
|
||||
{ TMPV770X_PLL_PIVOIFPLL, "pivoifpll", "osc2-clk", 0x600, pivoifpll_rates },
|
||||
{ TMPV770X_PLL_PIIMGERPLL, "piimgerpll", "osc2-clk", 0x700, piimgerpll_rates },
|
||||
};
|
||||
|
||||
static void __init tmpv770x_setup_plls(struct device_node *np)
|
||||
{
|
||||
struct visconti_pll_provider *ctx;
|
||||
void __iomem *reg_base;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
return;
|
||||
|
||||
ctx = visconti_init_pll(np, reg_base, TMPV770X_NR_PLL);
|
||||
if (IS_ERR(ctx)) {
|
||||
iounmap(reg_base);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->clk_data.hws[TMPV770X_PLL_PIPLL1] =
|
||||
clk_hw_register_fixed_rate(NULL, "pipll1", NULL, 0, 600000000);
|
||||
ctx->clk_data.hws[TMPV770X_PLL_PIDNNPLL] =
|
||||
clk_hw_register_fixed_rate(NULL, "pidnnpll", NULL, 0, 500000000);
|
||||
ctx->clk_data.hws[TMPV770X_PLL_PIETHERPLL] =
|
||||
clk_hw_register_fixed_rate(NULL, "pietherpll", NULL, 0, 500000000);
|
||||
|
||||
visconti_register_plls(ctx, pll_info, ARRAY_SIZE(pll_info), &tmpv770x_pll_lock);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(tmpv770x_plls, "toshiba,tmpv7708-pipllct", tmpv770x_setup_plls);
|
340
drivers/clk/visconti/pll.c
Normal file
340
drivers/clk/visconti/pll.c
Normal file
@ -0,0 +1,340 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Toshiba Visconti PLL driver
|
||||
*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
* Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "pll.h"
|
||||
|
||||
struct visconti_pll {
|
||||
struct clk_hw hw;
|
||||
void __iomem *pll_base;
|
||||
spinlock_t *lock;
|
||||
unsigned long flags;
|
||||
const struct visconti_pll_rate_table *rate_table;
|
||||
size_t rate_count;
|
||||
struct visconti_pll_provider *ctx;
|
||||
};
|
||||
|
||||
#define PLL_CONF_REG 0x0000
|
||||
#define PLL_CTRL_REG 0x0004
|
||||
#define PLL_FRACMODE_REG 0x0010
|
||||
#define PLL_INTIN_REG 0x0014
|
||||
#define PLL_FRACIN_REG 0x0018
|
||||
#define PLL_REFDIV_REG 0x001c
|
||||
#define PLL_POSTDIV_REG 0x0020
|
||||
|
||||
#define PLL_CONFIG_SEL BIT(0)
|
||||
#define PLL_PLLEN BIT(4)
|
||||
#define PLL_BYPASS BIT(16)
|
||||
#define PLL_INTIN_MASK GENMASK(11, 0)
|
||||
#define PLL_FRACIN_MASK GENMASK(23, 0)
|
||||
#define PLL_REFDIV_MASK GENMASK(5, 0)
|
||||
#define PLL_POSTDIV_MASK GENMASK(2, 0)
|
||||
|
||||
#define PLL0_FRACMODE_DACEN BIT(4)
|
||||
#define PLL0_FRACMODE_DSMEN BIT(0)
|
||||
|
||||
#define PLL_CREATE_FRACMODE(table) (table->dacen << 4 | table->dsmen)
|
||||
#define PLL_CREATE_OSTDIV(table) (table->postdiv2 << 4 | table->postdiv1)
|
||||
|
||||
static inline struct visconti_pll *to_visconti_pll(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct visconti_pll, hw);
|
||||
}
|
||||
|
||||
static void visconti_pll_get_params(struct visconti_pll *pll,
|
||||
struct visconti_pll_rate_table *rate_table)
|
||||
{
|
||||
u32 postdiv, val;
|
||||
|
||||
val = readl(pll->pll_base + PLL_FRACMODE_REG);
|
||||
|
||||
rate_table->dacen = FIELD_GET(PLL0_FRACMODE_DACEN, val);
|
||||
rate_table->dsmen = FIELD_GET(PLL0_FRACMODE_DSMEN, val);
|
||||
|
||||
rate_table->fracin = readl(pll->pll_base + PLL_FRACIN_REG) & PLL_FRACIN_MASK;
|
||||
rate_table->intin = readl(pll->pll_base + PLL_INTIN_REG) & PLL_INTIN_MASK;
|
||||
rate_table->refdiv = readl(pll->pll_base + PLL_REFDIV_REG) & PLL_REFDIV_MASK;
|
||||
|
||||
postdiv = readl(pll->pll_base + PLL_POSTDIV_REG);
|
||||
rate_table->postdiv1 = postdiv & PLL_POSTDIV_MASK;
|
||||
rate_table->postdiv2 = (postdiv >> 4) & PLL_POSTDIV_MASK;
|
||||
}
|
||||
|
||||
static const struct visconti_pll_rate_table *visconti_get_pll_settings(struct visconti_pll *pll,
|
||||
unsigned long rate)
|
||||
{
|
||||
const struct visconti_pll_rate_table *rate_table = pll->rate_table;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pll->rate_count; i++)
|
||||
if (rate == rate_table[i].rate)
|
||||
return &rate_table[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned long visconti_get_pll_rate_from_data(struct visconti_pll *pll,
|
||||
const struct visconti_pll_rate_table *rate)
|
||||
{
|
||||
const struct visconti_pll_rate_table *rate_table = pll->rate_table;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pll->rate_count; i++)
|
||||
if (memcmp(&rate_table[i].dacen, &rate->dacen,
|
||||
sizeof(*rate) - sizeof(unsigned long)) == 0)
|
||||
return rate_table[i].rate;
|
||||
|
||||
/* set default */
|
||||
return rate_table[0].rate;
|
||||
}
|
||||
|
||||
static long visconti_pll_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *prate)
|
||||
{
|
||||
struct visconti_pll *pll = to_visconti_pll(hw);
|
||||
const struct visconti_pll_rate_table *rate_table = pll->rate_table;
|
||||
int i;
|
||||
|
||||
/* Assumming rate_table is in descending order */
|
||||
for (i = 0; i < pll->rate_count; i++)
|
||||
if (rate >= rate_table[i].rate)
|
||||
return rate_table[i].rate;
|
||||
|
||||
/* return minimum supported value */
|
||||
return rate_table[i - 1].rate;
|
||||
}
|
||||
|
||||
static unsigned long visconti_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct visconti_pll *pll = to_visconti_pll(hw);
|
||||
struct visconti_pll_rate_table rate_table;
|
||||
|
||||
memset(&rate_table, 0, sizeof(rate_table));
|
||||
visconti_pll_get_params(pll, &rate_table);
|
||||
|
||||
return visconti_get_pll_rate_from_data(pll, &rate_table);
|
||||
}
|
||||
|
||||
static int visconti_pll_set_params(struct visconti_pll *pll,
|
||||
const struct visconti_pll_rate_table *rate_table)
|
||||
{
|
||||
writel(PLL_CREATE_FRACMODE(rate_table), pll->pll_base + PLL_FRACMODE_REG);
|
||||
writel(PLL_CREATE_OSTDIV(rate_table), pll->pll_base + PLL_POSTDIV_REG);
|
||||
writel(rate_table->intin, pll->pll_base + PLL_INTIN_REG);
|
||||
writel(rate_table->fracin, pll->pll_base + PLL_FRACIN_REG);
|
||||
writel(rate_table->refdiv, pll->pll_base + PLL_REFDIV_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visconti_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct visconti_pll *pll = to_visconti_pll(hw);
|
||||
const struct visconti_pll_rate_table *rate_table;
|
||||
|
||||
rate_table = visconti_get_pll_settings(pll, rate);
|
||||
if (!rate_table)
|
||||
return -EINVAL;
|
||||
|
||||
return visconti_pll_set_params(pll, rate_table);
|
||||
}
|
||||
|
||||
static int visconti_pll_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct visconti_pll *pll = to_visconti_pll(hw);
|
||||
u32 reg;
|
||||
|
||||
reg = readl(pll->pll_base + PLL_CTRL_REG);
|
||||
|
||||
return (reg & PLL_PLLEN);
|
||||
}
|
||||
|
||||
static int visconti_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct visconti_pll *pll = to_visconti_pll(hw);
|
||||
const struct visconti_pll_rate_table *rate_table = pll->rate_table;
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
if (visconti_pll_is_enabled(hw))
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(pll->lock, flags);
|
||||
|
||||
writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
|
||||
|
||||
reg = readl(pll->pll_base + PLL_CTRL_REG);
|
||||
reg |= PLL_BYPASS;
|
||||
writel(reg, pll->pll_base + PLL_CTRL_REG);
|
||||
|
||||
visconti_pll_set_params(pll, &rate_table[0]);
|
||||
|
||||
reg = readl(pll->pll_base + PLL_CTRL_REG);
|
||||
reg &= ~PLL_PLLEN;
|
||||
writel(reg, pll->pll_base + PLL_CTRL_REG);
|
||||
|
||||
udelay(1);
|
||||
|
||||
reg = readl(pll->pll_base + PLL_CTRL_REG);
|
||||
reg |= PLL_PLLEN;
|
||||
writel(reg, pll->pll_base + PLL_CTRL_REG);
|
||||
|
||||
udelay(40);
|
||||
|
||||
reg = readl(pll->pll_base + PLL_CTRL_REG);
|
||||
reg &= ~PLL_BYPASS;
|
||||
writel(reg, pll->pll_base + PLL_CTRL_REG);
|
||||
|
||||
spin_unlock_irqrestore(pll->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void visconti_pll_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct visconti_pll *pll = to_visconti_pll(hw);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
if (!visconti_pll_is_enabled(hw))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(pll->lock, flags);
|
||||
|
||||
writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
|
||||
|
||||
reg = readl(pll->pll_base + PLL_CTRL_REG);
|
||||
reg |= PLL_BYPASS;
|
||||
writel(reg, pll->pll_base + PLL_CTRL_REG);
|
||||
|
||||
reg = readl(pll->pll_base + PLL_CTRL_REG);
|
||||
reg &= ~PLL_PLLEN;
|
||||
writel(reg, pll->pll_base + PLL_CTRL_REG);
|
||||
|
||||
spin_unlock_irqrestore(pll->lock, flags);
|
||||
}
|
||||
|
||||
static const struct clk_ops visconti_pll_ops = {
|
||||
.enable = visconti_pll_enable,
|
||||
.disable = visconti_pll_disable,
|
||||
.is_enabled = visconti_pll_is_enabled,
|
||||
.round_rate = visconti_pll_round_rate,
|
||||
.recalc_rate = visconti_pll_recalc_rate,
|
||||
.set_rate = visconti_pll_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw *visconti_register_pll(struct visconti_pll_provider *ctx,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
int offset,
|
||||
const struct visconti_pll_rate_table *rate_table,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct visconti_pll *pll;
|
||||
struct clk *pll_clk;
|
||||
struct clk_hw *pll_hw_clk;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
|
||||
if (!pll)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.flags = CLK_IGNORE_UNUSED;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
for (len = 0; rate_table[len].rate != 0; )
|
||||
len++;
|
||||
pll->rate_count = len;
|
||||
pll->rate_table = kmemdup(rate_table,
|
||||
pll->rate_count * sizeof(struct visconti_pll_rate_table),
|
||||
GFP_KERNEL);
|
||||
WARN(!pll->rate_table, "%s: could not allocate rate table for %s\n", __func__, name);
|
||||
|
||||
init.ops = &visconti_pll_ops;
|
||||
pll->hw.init = &init;
|
||||
pll->pll_base = ctx->reg_base + offset;
|
||||
pll->lock = lock;
|
||||
pll->ctx = ctx;
|
||||
|
||||
pll_hw_clk = &pll->hw;
|
||||
ret = clk_hw_register(NULL, &pll->hw);
|
||||
if (ret) {
|
||||
pr_err("failed to register pll clock %s : %ld\n", name, PTR_ERR(pll_clk));
|
||||
kfree(pll);
|
||||
pll_hw_clk = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return pll_hw_clk;
|
||||
}
|
||||
|
||||
static void visconti_pll_add_lookup(struct visconti_pll_provider *ctx,
|
||||
struct clk_hw *hw_clk,
|
||||
unsigned int id)
|
||||
{
|
||||
if (id)
|
||||
ctx->clk_data.hws[id] = hw_clk;
|
||||
}
|
||||
|
||||
void __init visconti_register_plls(struct visconti_pll_provider *ctx,
|
||||
const struct visconti_pll_info *list,
|
||||
unsigned int nr_plls,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < nr_plls; idx++, list++) {
|
||||
struct clk_hw *clk;
|
||||
|
||||
clk = visconti_register_pll(ctx,
|
||||
list->name,
|
||||
list->parent,
|
||||
list->base_reg,
|
||||
list->rate_table,
|
||||
lock);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("failed to register clock %s\n", list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
visconti_pll_add_lookup(ctx, clk, list->id);
|
||||
}
|
||||
}
|
||||
|
||||
struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
|
||||
void __iomem *base,
|
||||
unsigned long nr_plls)
|
||||
{
|
||||
struct visconti_pll_provider *ctx;
|
||||
int i;
|
||||
|
||||
ctx = kzalloc(struct_size(ctx, clk_data.hws, nr_plls), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; i < nr_plls; ++i)
|
||||
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
ctx->node = np;
|
||||
ctx->reg_base = base;
|
||||
ctx->clk_data.num = nr_plls;
|
||||
|
||||
return ctx;
|
||||
}
|
62
drivers/clk/visconti/pll.h
Normal file
62
drivers/clk/visconti/pll.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
* Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
|
||||
#ifndef _VISCONTI_PLL_H_
|
||||
#define _VISCONTI_PLL_H_
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
struct visconti_pll_provider {
|
||||
void __iomem *reg_base;
|
||||
struct regmap *regmap;
|
||||
struct clk_hw_onecell_data clk_data;
|
||||
struct device_node *node;
|
||||
};
|
||||
|
||||
#define VISCONTI_PLL_RATE(_rate, _dacen, _dsmen, \
|
||||
_refdiv, _intin, _fracin, _postdiv1, _postdiv2) \
|
||||
{ \
|
||||
.rate = _rate, \
|
||||
.dacen = _dacen, \
|
||||
.dsmen = _dsmen, \
|
||||
.refdiv = _refdiv, \
|
||||
.intin = _intin, \
|
||||
.fracin = _fracin, \
|
||||
.postdiv1 = _postdiv1, \
|
||||
.postdiv2 = _postdiv2 \
|
||||
}
|
||||
|
||||
struct visconti_pll_rate_table {
|
||||
unsigned long rate;
|
||||
unsigned int dacen;
|
||||
unsigned int dsmen;
|
||||
unsigned int refdiv;
|
||||
unsigned long intin;
|
||||
unsigned long fracin;
|
||||
unsigned int postdiv1;
|
||||
unsigned int postdiv2;
|
||||
};
|
||||
|
||||
struct visconti_pll_info {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *parent;
|
||||
unsigned long base_reg;
|
||||
const struct visconti_pll_rate_table *rate_table;
|
||||
};
|
||||
|
||||
struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
|
||||
void __iomem *base,
|
||||
unsigned long nr_plls);
|
||||
void visconti_register_plls(struct visconti_pll_provider *ctx,
|
||||
const struct visconti_pll_info *list,
|
||||
unsigned int nr_plls, spinlock_t *lock);
|
||||
|
||||
#endif /* _VISCONTI_PLL_H_ */
|
107
drivers/clk/visconti/reset.c
Normal file
107
drivers/clk/visconti/reset.c
Normal file
@ -0,0 +1,107 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Toshiba Visconti ARM SoC reset controller
|
||||
*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
* Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "reset.h"
|
||||
|
||||
static inline struct visconti_reset *to_visconti_reset(struct reset_controller_dev *rcdev)
|
||||
{
|
||||
return container_of(rcdev, struct visconti_reset, rcdev);
|
||||
}
|
||||
|
||||
static int visconti_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
|
||||
{
|
||||
struct visconti_reset *reset = to_visconti_reset(rcdev);
|
||||
const struct visconti_reset_data *data = &reset->resets[id];
|
||||
u32 rst = BIT(data->rs_idx);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(reset->lock, flags);
|
||||
ret = regmap_update_bits(reset->regmap, data->rson_offset, rst, rst);
|
||||
spin_unlock_irqrestore(reset->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int visconti_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
|
||||
{
|
||||
struct visconti_reset *reset = to_visconti_reset(rcdev);
|
||||
const struct visconti_reset_data *data = &reset->resets[id];
|
||||
u32 rst = BIT(data->rs_idx);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(reset->lock, flags);
|
||||
ret = regmap_update_bits(reset->regmap, data->rsoff_offset, rst, rst);
|
||||
spin_unlock_irqrestore(reset->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int visconti_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
|
||||
{
|
||||
visconti_reset_assert(rcdev, id);
|
||||
udelay(1);
|
||||
visconti_reset_deassert(rcdev, id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visconti_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
|
||||
{
|
||||
struct visconti_reset *reset = to_visconti_reset(rcdev);
|
||||
const struct visconti_reset_data *data = &reset->resets[id];
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(reset->lock, flags);
|
||||
ret = regmap_read(reset->regmap, data->rson_offset, ®);
|
||||
spin_unlock_irqrestore(reset->lock, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return !(reg & data->rs_idx);
|
||||
}
|
||||
|
||||
const struct reset_control_ops visconti_reset_ops = {
|
||||
.assert = visconti_reset_assert,
|
||||
.deassert = visconti_reset_deassert,
|
||||
.reset = visconti_reset_reset,
|
||||
.status = visconti_reset_status,
|
||||
};
|
||||
|
||||
int visconti_register_reset_controller(struct device *dev,
|
||||
struct regmap *regmap,
|
||||
const struct visconti_reset_data *resets,
|
||||
unsigned int num_resets,
|
||||
const struct reset_control_ops *reset_ops,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct visconti_reset *reset;
|
||||
|
||||
reset = devm_kzalloc(dev, sizeof(*reset), GFP_KERNEL);
|
||||
if (!reset)
|
||||
return -ENOMEM;
|
||||
|
||||
reset->regmap = regmap;
|
||||
reset->resets = resets;
|
||||
reset->rcdev.ops = reset_ops;
|
||||
reset->rcdev.nr_resets = num_resets;
|
||||
reset->rcdev.of_node = dev->of_node;
|
||||
reset->lock = lock;
|
||||
|
||||
return devm_reset_controller_register(dev, &reset->rcdev);
|
||||
}
|
36
drivers/clk/visconti/reset.h
Normal file
36
drivers/clk/visconti/reset.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Toshiba ARM SoC reset controller driver
|
||||
*
|
||||
* Copyright (c) 2021 TOSHIBA CORPORATION
|
||||
*
|
||||
* Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
|
||||
*/
|
||||
|
||||
#ifndef _VISCONTI_RESET_H_
|
||||
#define _VISCONTI_RESET_H_
|
||||
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
struct visconti_reset_data {
|
||||
u32 rson_offset;
|
||||
u32 rsoff_offset;
|
||||
u8 rs_idx;
|
||||
};
|
||||
|
||||
struct visconti_reset {
|
||||
struct reset_controller_dev rcdev;
|
||||
struct regmap *regmap;
|
||||
const struct visconti_reset_data *resets;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
extern const struct reset_control_ops visconti_reset_ops;
|
||||
|
||||
int visconti_register_reset_controller(struct device *dev,
|
||||
struct regmap *regmap,
|
||||
const struct visconti_reset_data *resets,
|
||||
unsigned int num_resets,
|
||||
const struct reset_control_ops *reset_ops,
|
||||
spinlock_t *lock);
|
||||
#endif /* _VISCONTI_RESET_H_ */
|
181
include/dt-bindings/clock/toshiba,tmpv770x.h
Normal file
181
include/dt-bindings/clock/toshiba,tmpv770x.h
Normal file
@ -0,0 +1,181 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
|
||||
#ifndef _DT_BINDINGS_CLOCK_TOSHIBA_TMPV770X_H_
|
||||
#define _DT_BINDINGS_CLOCK_TOSHIBA_TMPV770X_H_
|
||||
|
||||
/* PLL */
|
||||
#define TMPV770X_PLL_PIPLL0 0
|
||||
#define TMPV770X_PLL_PIPLL1 1
|
||||
#define TMPV770X_PLL_PIDNNPLL 2
|
||||
#define TMPV770X_PLL_PIETHERPLL 3
|
||||
#define TMPV770X_PLL_PIDDRCPLL 4
|
||||
#define TMPV770X_PLL_PIVOIFPLL 5
|
||||
#define TMPV770X_PLL_PIIMGERPLL 6
|
||||
#define TMPV770X_NR_PLL 7
|
||||
|
||||
/* Clocks */
|
||||
#define TMPV770X_CLK_PIPLL1_DIV1 0
|
||||
#define TMPV770X_CLK_PIPLL1_DIV2 1
|
||||
#define TMPV770X_CLK_PIPLL1_DIV4 2
|
||||
#define TMPV770X_CLK_PIDNNPLL_DIV1 3
|
||||
#define TMPV770X_CLK_DDRC_PHY_PLL0 4
|
||||
#define TMPV770X_CLK_DDRC_PHY_PLL1 5
|
||||
#define TMPV770X_CLK_D_PHYPLL 6
|
||||
#define TMPV770X_CLK_PHY_PCIEPLL 7
|
||||
#define TMPV770X_CLK_CA53CL0 8
|
||||
#define TMPV770X_CLK_CA53CL1 9
|
||||
#define TMPV770X_CLK_PISDMAC 10
|
||||
#define TMPV770X_CLK_PIPDMAC0 11
|
||||
#define TMPV770X_CLK_PIPDMAC1 12
|
||||
#define TMPV770X_CLK_PIWRAM 13
|
||||
#define TMPV770X_CLK_DDRC0 14
|
||||
#define TMPV770X_CLK_DDRC0_SCLK 15
|
||||
#define TMPV770X_CLK_DDRC0_NCLK 16
|
||||
#define TMPV770X_CLK_DDRC0_MCLK 17
|
||||
#define TMPV770X_CLK_DDRC0_APBCLK 18
|
||||
#define TMPV770X_CLK_DDRC1 19
|
||||
#define TMPV770X_CLK_DDRC1_SCLK 20
|
||||
#define TMPV770X_CLK_DDRC1_NCLK 21
|
||||
#define TMPV770X_CLK_DDRC1_MCLK 22
|
||||
#define TMPV770X_CLK_DDRC1_APBCLK 23
|
||||
#define TMPV770X_CLK_HOX 24
|
||||
#define TMPV770X_CLK_PCIE_MSTR 25
|
||||
#define TMPV770X_CLK_PCIE_AUX 26
|
||||
#define TMPV770X_CLK_PIINTC 27
|
||||
#define TMPV770X_CLK_PIETHER_BUS 28
|
||||
#define TMPV770X_CLK_PISPI0 29
|
||||
#define TMPV770X_CLK_PISPI1 30
|
||||
#define TMPV770X_CLK_PISPI2 31
|
||||
#define TMPV770X_CLK_PISPI3 32
|
||||
#define TMPV770X_CLK_PISPI4 33
|
||||
#define TMPV770X_CLK_PISPI5 34
|
||||
#define TMPV770X_CLK_PISPI6 35
|
||||
#define TMPV770X_CLK_PIUART0 36
|
||||
#define TMPV770X_CLK_PIUART1 37
|
||||
#define TMPV770X_CLK_PIUART2 38
|
||||
#define TMPV770X_CLK_PIUART3 39
|
||||
#define TMPV770X_CLK_PII2C0 40
|
||||
#define TMPV770X_CLK_PII2C1 41
|
||||
#define TMPV770X_CLK_PII2C2 42
|
||||
#define TMPV770X_CLK_PII2C3 43
|
||||
#define TMPV770X_CLK_PII2C4 44
|
||||
#define TMPV770X_CLK_PII2C5 45
|
||||
#define TMPV770X_CLK_PII2C6 46
|
||||
#define TMPV770X_CLK_PII2C7 47
|
||||
#define TMPV770X_CLK_PII2C8 48
|
||||
#define TMPV770X_CLK_PIGPIO 49
|
||||
#define TMPV770X_CLK_PIPGM 50
|
||||
#define TMPV770X_CLK_PIPCMIF 51
|
||||
#define TMPV770X_CLK_PIPCMIF_AUDIO_O 52
|
||||
#define TMPV770X_CLK_PIPCMIF_AUDIO_I 53
|
||||
#define TMPV770X_CLK_PICMPT0 54
|
||||
#define TMPV770X_CLK_PICMPT1 55
|
||||
#define TMPV770X_CLK_PITSC 56
|
||||
#define TMPV770X_CLK_PIUWDT 57
|
||||
#define TMPV770X_CLK_PISWDT 58
|
||||
#define TMPV770X_CLK_WDTCLK 59
|
||||
#define TMPV770X_CLK_PISUBUS_150M 60
|
||||
#define TMPV770X_CLK_PISUBUS_300M 61
|
||||
#define TMPV770X_CLK_PIPMU 62
|
||||
#define TMPV770X_CLK_PIGPMU 63
|
||||
#define TMPV770X_CLK_PITMU 64
|
||||
#define TMPV770X_CLK_WRCK 65
|
||||
#define TMPV770X_CLK_PIEMM 66
|
||||
#define TMPV770X_CLK_PIMISC 67
|
||||
#define TMPV770X_CLK_PIGCOMM 68
|
||||
#define TMPV770X_CLK_PIDCOMM 69
|
||||
#define TMPV770X_CLK_PICKMON 70
|
||||
#define TMPV770X_CLK_PIMBUS 71
|
||||
#define TMPV770X_CLK_SBUSCLK 72
|
||||
#define TMPV770X_CLK_DDR0_APBCLKCLK 73
|
||||
#define TMPV770X_CLK_DDR1_APBCLKCLK 74
|
||||
#define TMPV770X_CLK_DSP0_PBCLK 75
|
||||
#define TMPV770X_CLK_DSP1_PBCLK 76
|
||||
#define TMPV770X_CLK_DSP2_PBCLK 77
|
||||
#define TMPV770X_CLK_DSP3_PBCLK 78
|
||||
#define TMPV770X_CLK_DSVIIF0_APBCLK 79
|
||||
#define TMPV770X_CLK_VIIF0_APBCLK 80
|
||||
#define TMPV770X_CLK_VIIF0_CFGCLK 81
|
||||
#define TMPV770X_CLK_VIIF1_APBCLK 82
|
||||
#define TMPV770X_CLK_VIIF1_CFGCLK 83
|
||||
#define TMPV770X_CLK_VIIF2_APBCLK 84
|
||||
#define TMPV770X_CLK_VIIF2_CFGCLK 85
|
||||
#define TMPV770X_CLK_VIIF3_APBCLK 86
|
||||
#define TMPV770X_CLK_VIIF3_CFGCLK 87
|
||||
#define TMPV770X_CLK_VIIF4_APBCLK 88
|
||||
#define TMPV770X_CLK_VIIF4_CFGCLK 89
|
||||
#define TMPV770X_CLK_VIIF5_APBCLK 90
|
||||
#define TMPV770X_CLK_VIIF5_CFGCLK 91
|
||||
#define TMPV770X_CLK_VOIF_SBUSCLK 92
|
||||
#define TMPV770X_CLK_VOIF_PROCCLK 93
|
||||
#define TMPV770X_CLK_VOIF_DPHYCFGCLK 94
|
||||
#define TMPV770X_CLK_DNN0 95
|
||||
#define TMPV770X_CLK_STMAT 96
|
||||
#define TMPV770X_CLK_HWA0 97
|
||||
#define TMPV770X_CLK_AFFINE0 98
|
||||
#define TMPV770X_CLK_HAMAT 99
|
||||
#define TMPV770X_CLK_SMLDB 100
|
||||
#define TMPV770X_CLK_HWA0_ASYNC 101
|
||||
#define TMPV770X_CLK_HWA2 102
|
||||
#define TMPV770X_CLK_FLMAT 103
|
||||
#define TMPV770X_CLK_PYRAMID 104
|
||||
#define TMPV770X_CLK_HWA2_ASYNC 105
|
||||
#define TMPV770X_CLK_DSP0 106
|
||||
#define TMPV770X_CLK_VIIFBS0 107
|
||||
#define TMPV770X_CLK_VIIFBS0_L2ISP 108
|
||||
#define TMPV770X_CLK_VIIFBS0_L1ISP 109
|
||||
#define TMPV770X_CLK_VIIFBS0_PROC 110
|
||||
#define TMPV770X_CLK_VIIFBS1 111
|
||||
#define TMPV770X_CLK_VIIFBS2 112
|
||||
#define TMPV770X_CLK_VIIFOP_MBUS 113
|
||||
#define TMPV770X_CLK_VIIFOP0_PROC 114
|
||||
#define TMPV770X_CLK_PIETHER_2P5M 115
|
||||
#define TMPV770X_CLK_PIETHER_25M 116
|
||||
#define TMPV770X_CLK_PIETHER_50M 117
|
||||
#define TMPV770X_CLK_PIETHER_125M 118
|
||||
#define TMPV770X_CLK_VOIF0_DPHYCFG 119
|
||||
#define TMPV770X_CLK_VOIF0_PROC 120
|
||||
#define TMPV770X_CLK_VOIF0_SBUS 121
|
||||
#define TMPV770X_CLK_VOIF0_DSIREF 122
|
||||
#define TMPV770X_CLK_VOIF0_PIXEL 123
|
||||
#define TMPV770X_CLK_PIREFCLK 124
|
||||
#define TMPV770X_CLK_SBUS 125
|
||||
#define TMPV770X_CLK_BUSLCK 126
|
||||
#define TMPV770X_NR_CLK 127
|
||||
|
||||
/* Reset */
|
||||
#define TMPV770X_RESET_PIETHER_2P5M 0
|
||||
#define TMPV770X_RESET_PIETHER_25M 1
|
||||
#define TMPV770X_RESET_PIETHER_50M 2
|
||||
#define TMPV770X_RESET_PIETHER_125M 3
|
||||
#define TMPV770X_RESET_HOX 4
|
||||
#define TMPV770X_RESET_PCIE_MSTR 5
|
||||
#define TMPV770X_RESET_PCIE_AUX 6
|
||||
#define TMPV770X_RESET_PIINTC 7
|
||||
#define TMPV770X_RESET_PIETHER_BUS 8
|
||||
#define TMPV770X_RESET_PISPI0 9
|
||||
#define TMPV770X_RESET_PISPI1 10
|
||||
#define TMPV770X_RESET_PISPI2 11
|
||||
#define TMPV770X_RESET_PISPI3 12
|
||||
#define TMPV770X_RESET_PISPI4 13
|
||||
#define TMPV770X_RESET_PISPI5 14
|
||||
#define TMPV770X_RESET_PISPI6 15
|
||||
#define TMPV770X_RESET_PIUART0 16
|
||||
#define TMPV770X_RESET_PIUART1 17
|
||||
#define TMPV770X_RESET_PIUART2 18
|
||||
#define TMPV770X_RESET_PIUART3 19
|
||||
#define TMPV770X_RESET_PII2C0 20
|
||||
#define TMPV770X_RESET_PII2C1 21
|
||||
#define TMPV770X_RESET_PII2C2 22
|
||||
#define TMPV770X_RESET_PII2C3 23
|
||||
#define TMPV770X_RESET_PII2C4 24
|
||||
#define TMPV770X_RESET_PII2C5 25
|
||||
#define TMPV770X_RESET_PII2C6 26
|
||||
#define TMPV770X_RESET_PII2C7 27
|
||||
#define TMPV770X_RESET_PII2C8 28
|
||||
#define TMPV770X_RESET_PIPCMIF 29
|
||||
#define TMPV770X_RESET_PICKMON 30
|
||||
#define TMPV770X_RESET_SBUSCLK 31
|
||||
#define TMPV770X_NR_RESET 32
|
||||
|
||||
#endif /*_DT_BINDINGS_CLOCK_TOSHIBA_TMPV770X_H_ */
|
41
include/dt-bindings/reset/toshiba,tmpv770x.h
Normal file
41
include/dt-bindings/reset/toshiba,tmpv770x.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_TOSHIBA_TMPV770X_H_
|
||||
#define _DT_BINDINGS_RESET_TOSHIBA_TMPV770X_H_
|
||||
|
||||
/* Reset */
|
||||
#define TMPV770X_RESET_PIETHER_2P5M 0
|
||||
#define TMPV770X_RESET_PIETHER_25M 1
|
||||
#define TMPV770X_RESET_PIETHER_50M 2
|
||||
#define TMPV770X_RESET_PIETHER_125M 3
|
||||
#define TMPV770X_RESET_HOX 4
|
||||
#define TMPV770X_RESET_PCIE_MSTR 5
|
||||
#define TMPV770X_RESET_PCIE_AUX 6
|
||||
#define TMPV770X_RESET_PIINTC 7
|
||||
#define TMPV770X_RESET_PIETHER_BUS 8
|
||||
#define TMPV770X_RESET_PISPI0 9
|
||||
#define TMPV770X_RESET_PISPI1 10
|
||||
#define TMPV770X_RESET_PISPI2 11
|
||||
#define TMPV770X_RESET_PISPI3 12
|
||||
#define TMPV770X_RESET_PISPI4 13
|
||||
#define TMPV770X_RESET_PISPI5 14
|
||||
#define TMPV770X_RESET_PISPI6 15
|
||||
#define TMPV770X_RESET_PIUART0 16
|
||||
#define TMPV770X_RESET_PIUART1 17
|
||||
#define TMPV770X_RESET_PIUART2 18
|
||||
#define TMPV770X_RESET_PIUART3 19
|
||||
#define TMPV770X_RESET_PII2C0 20
|
||||
#define TMPV770X_RESET_PII2C1 21
|
||||
#define TMPV770X_RESET_PII2C2 22
|
||||
#define TMPV770X_RESET_PII2C3 23
|
||||
#define TMPV770X_RESET_PII2C4 24
|
||||
#define TMPV770X_RESET_PII2C5 25
|
||||
#define TMPV770X_RESET_PII2C6 26
|
||||
#define TMPV770X_RESET_PII2C7 27
|
||||
#define TMPV770X_RESET_PII2C8 28
|
||||
#define TMPV770X_RESET_PIPCMIF 29
|
||||
#define TMPV770X_RESET_PICKMON 30
|
||||
#define TMPV770X_RESET_SBUSCLK 31
|
||||
#define TMPV770X_NR_RESET 32
|
||||
|
||||
#endif /*_DT_BINDINGS_RESET_TOSHIBA_TMPV770X_H_ */
|
Loading…
Reference in New Issue
Block a user