Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f3bf9841 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge branch 'clk-hi3519' into clk-next

* clk-hi3519:
  clk: hisilicon: add CRG driver for hi3519 soc
  clk: hisilicon: export some hisilicon APIs to modules
  reset: hisilicon: add reset controller driver for hisilicon SOCs
parents 4087a5f2 6c9da387
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
* Hisilicon Hi3519 Clock and Reset Generator(CRG)

The Hi3519 CRG module provides clock and reset signals to various
controllers within the SoC.

This binding uses the following bindings:
    Documentation/devicetree/bindings/clock/clock-bindings.txt
    Documentation/devicetree/bindings/reset/reset.txt

Required Properties:

- compatible: should be one of the following.
  - "hisilicon,hi3519-crg" - controller compatible with Hi3519 SoC.

- reg: physical base address of the controller and length of memory mapped
  region.

- #clock-cells: should be 1.

Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.

All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.

- #reset-cells: should be 2.

A reset signal can be controlled by writing a bit register in the CRG module.
The reset specifier consists of two cells. The first cell represents the
register offset relative to the base address. The second cell represents the
bit index in the register.

Example: CRG nodes
CRG: clock-reset-controller@12010000 {
	compatible = "hisilicon,hi3519-crg";
	reg = <0x12010000 0x10000>;
	#clock-cells = <1>;
	#reset-cells = <2>;
};

Example: consumer nodes
i2c0: i2c@12110000 {
	compatible = "hisilicon,hi3519-i2c";
	reg = <0x12110000 0x1000>;
	clocks = <&CRG HI3519_I2C0_RST>;
	resets = <&CRG 0xe4 0>;
};
+15 −0
Original line number Diff line number Diff line
config COMMON_CLK_HI3519
	tristate "Hi3519 Clock Driver"
	depends on ARCH_HISI || COMPILE_TEST
	select RESET_HISI
	default ARCH_HISI
	help
	  Build the clock driver for hi3519.

config COMMON_CLK_HI6220
	bool "Hi6220 Clock Driver"
	depends on ARCH_HISI || COMPILE_TEST
@@ -5,6 +13,13 @@ config COMMON_CLK_HI6220
	help
	  Build the Hisilicon Hi6220 clock driver based on the common clock framework.

config RESET_HISI
	bool "HiSilicon Reset Controller Driver"
	depends on ARCH_HISI || COMPILE_TEST
	select RESET_CONTROLLER
	help
	  Build reset controller driver for HiSilicon device chipsets.

config STUB_CLK_HI6220
	bool "Hi6220 Stub Clock Driver"
	depends on COMMON_CLK_HI6220 && MAILBOX
+2 −0
Original line number Diff line number Diff line
@@ -7,5 +7,7 @@ obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o
obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
obj-$(CONFIG_COMMON_CLK_HI3519)	+= clk-hi3519.o
obj-$(CONFIG_COMMON_CLK_HI6220)	+= clk-hi6220.o
obj-$(CONFIG_RESET_HISI)	+= reset.o
obj-$(CONFIG_STUB_CLK_HI6220)	+= clk-hi6220-stub.o
+131 −0
Original line number Diff line number Diff line
/*
 * Hi3519 Clock Driver
 *
 * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <dt-bindings/clock/hi3519-clock.h>
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "clk.h"
#include "reset.h"

#define HI3519_INNER_CLK_OFFSET	64
#define HI3519_FIXED_24M	65
#define HI3519_FIXED_50M	66
#define HI3519_FIXED_75M	67
#define HI3519_FIXED_125M	68
#define HI3519_FIXED_150M	69
#define HI3519_FIXED_200M	70
#define HI3519_FIXED_250M	71
#define HI3519_FIXED_300M	72
#define HI3519_FIXED_400M	73
#define HI3519_FMC_MUX		74

#define HI3519_NR_CLKS		128

static const struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] = {
	{ HI3519_FIXED_24M, "24m", NULL, 0, 24000000, },
	{ HI3519_FIXED_50M, "50m", NULL, 0, 50000000, },
	{ HI3519_FIXED_75M, "75m", NULL, 0, 75000000, },
	{ HI3519_FIXED_125M, "125m", NULL, 0, 125000000, },
	{ HI3519_FIXED_150M, "150m", NULL, 0, 150000000, },
	{ HI3519_FIXED_200M, "200m", NULL, 0, 200000000, },
	{ HI3519_FIXED_250M, "250m", NULL, 0, 250000000, },
	{ HI3519_FIXED_300M, "300m", NULL, 0, 300000000, },
	{ HI3519_FIXED_400M, "400m", NULL, 0, 400000000, },
};

static const char *const fmc_mux_p[] = {
		"24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m", };
static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};

static const struct hisi_mux_clock hi3519_mux_clks[] = {
	{ HI3519_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
		CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, },
};

static const struct hisi_gate_clock hi3519_gate_clks[] = {
	{ HI3519_FMC_CLK, "clk_fmc", "fmc_mux",
		CLK_SET_RATE_PARENT, 0xc0, 1, 0, },
	{ HI3519_UART0_CLK, "clk_uart0", "24m",
		CLK_SET_RATE_PARENT, 0xe4, 20, 0, },
	{ HI3519_UART1_CLK, "clk_uart1", "24m",
		CLK_SET_RATE_PARENT, 0xe4, 21, 0, },
	{ HI3519_UART2_CLK, "clk_uart2", "24m",
		CLK_SET_RATE_PARENT, 0xe4, 22, 0, },
	{ HI3519_UART3_CLK, "clk_uart3", "24m",
		CLK_SET_RATE_PARENT, 0xe4, 23, 0, },
	{ HI3519_UART4_CLK, "clk_uart4", "24m",
		CLK_SET_RATE_PARENT, 0xe4, 24, 0, },
	{ HI3519_SPI0_CLK, "clk_spi0", "50m",
		CLK_SET_RATE_PARENT, 0xe4, 16, 0, },
	{ HI3519_SPI1_CLK, "clk_spi1", "50m",
		CLK_SET_RATE_PARENT, 0xe4, 17, 0, },
	{ HI3519_SPI2_CLK, "clk_spi2", "50m",
		CLK_SET_RATE_PARENT, 0xe4, 18, 0, },
};

static int hi3519_clk_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct hisi_clock_data *clk_data;
	struct hisi_reset_controller *rstc;

	rstc = hisi_reset_init(np);
	if (!rstc)
		return -ENOMEM;

	clk_data = hisi_clk_init(np, HI3519_NR_CLKS);
	if (!clk_data) {
		hisi_reset_exit(rstc);
		return -ENODEV;
	}

	hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks,
				     ARRAY_SIZE(hi3519_fixed_rate_clks),
				     clk_data);
	hisi_clk_register_mux(hi3519_mux_clks, ARRAY_SIZE(hi3519_mux_clks),
					clk_data);
	hisi_clk_register_gate(hi3519_gate_clks,
			ARRAY_SIZE(hi3519_gate_clks), clk_data);

	return 0;
}

static const struct of_device_id hi3519_clk_match_table[] = {
	{ .compatible = "hisilicon,hi3519-crg" },
	{ }
};
MODULE_DEVICE_TABLE(of, hi3519_clk_match_table);

static struct platform_driver hi3519_clk_driver = {
	.probe          = hi3519_clk_probe,
	.driver         = {
		.name   = "hi3519-clk",
		.of_match_table = hi3519_clk_match_table,
	},
};

static int __init hi3519_clk_init(void)
{
	return platform_driver_register(&hi3519_clk_driver);
}
core_initcall(hi3519_clk_init);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver");
+15 −8
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@

static DEFINE_SPINLOCK(hisi_clk_lock);

struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
struct hisi_clock_data *hisi_clk_init(struct device_node *np,
					     int nr_clks)
{
	struct hisi_clock_data *clk_data;
@@ -71,8 +71,9 @@ struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
err:
	return NULL;
}
EXPORT_SYMBOL_GPL(hisi_clk_init);

void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks,
void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
					 int nums, struct hisi_clock_data *data)
{
	struct clk *clk;
@@ -91,8 +92,9 @@ void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks,
		data->clk_data.clks[clks[i].id] = clk;
	}
}
EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);

void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks,
void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
					   int nums,
					   struct hisi_clock_data *data)
{
@@ -112,8 +114,9 @@ void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks,
		data->clk_data.clks[clks[i].id] = clk;
	}
}
EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);

void __init hisi_clk_register_mux(struct hisi_mux_clock *clks,
void hisi_clk_register_mux(const struct hisi_mux_clock *clks,
				  int nums, struct hisi_clock_data *data)
{
	struct clk *clk;
@@ -141,8 +144,9 @@ void __init hisi_clk_register_mux(struct hisi_mux_clock *clks,
		data->clk_data.clks[clks[i].id] = clk;
	}
}
EXPORT_SYMBOL_GPL(hisi_clk_register_mux);

void __init hisi_clk_register_divider(struct hisi_divider_clock *clks,
void hisi_clk_register_divider(const struct hisi_divider_clock *clks,
				      int nums, struct hisi_clock_data *data)
{
	struct clk *clk;
@@ -170,8 +174,9 @@ void __init hisi_clk_register_divider(struct hisi_divider_clock *clks,
		data->clk_data.clks[clks[i].id] = clk;
	}
}
EXPORT_SYMBOL_GPL(hisi_clk_register_divider);

void __init hisi_clk_register_gate(struct hisi_gate_clock *clks,
void hisi_clk_register_gate(const struct hisi_gate_clock *clks,
				       int nums, struct hisi_clock_data *data)
{
	struct clk *clk;
@@ -198,8 +203,9 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *clks,
		data->clk_data.clks[clks[i].id] = clk;
	}
}
EXPORT_SYMBOL_GPL(hisi_clk_register_gate);

void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks,
				       int nums, struct hisi_clock_data *data)
{
	struct clk *clk;
@@ -226,8 +232,9 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
		data->clk_data.clks[clks[i].id] = clk;
	}
}
EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep);

void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
					int nums, struct hisi_clock_data *data)
{
	struct clk *clk;
Loading