Merge branches 'clk-aspeed', 'clk-lock-UP', 'clk-mediatek' and 'clk-allwinner' into clk-next
* clk-aspeed: clk: aspeed: Handle inverse polarity of USB port 1 clock gate clk: aspeed: Fix return value check in aspeed_cc_init() clk: aspeed: Add reset controller clk: aspeed: Register gated clocks clk: aspeed: Add platform driver and register PLLs clk: aspeed: Register core clocks clk: Add clock driver for ASPEED BMC SoCs dt-bindings: clock: Add ASPEED constants * clk-lock-UP: clk: fix reentrancy of clk_enable() on UP systems * clk-mediatek: clk: mediatek: adjust dependency of reset.c to avoid unexpectedly being built clk: mediatek: Fix all warnings for missing struct clk_onecell_data clk: mediatek: fixup test-building of MediaTek clock drivers clk: mediatek: group drivers under indpendent menu * clk-allwinner: clk: sunxi-ng: a83t: Add M divider to TCON1 clock clk: sunxi-ng: fix the A64/H5 clock description of DE2 CCU clk: sunxi-ng: add support for Allwinner H3 DE2 CCU dt-bindings: fix the binding of Allwinner DE2 CCU of A83T and H3 clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for audio PLL clk: sunxi-ng: sun8i: a83t: Add /2 fixed post divider to audio PLL clk: sunxi-ng: Support fixed post-dividers on NM style clocks clk: sunxi-ng: sun50i: a64: Add 2x fixed post-divider to MMC module clocks clk: sunxi-ng: Support fixed post-dividers on MP style clocks clk: sunxi: Use PTR_ERR_OR_ZERO()
This commit is contained in:
commit
c43a52cfd2
|
@ -4,13 +4,14 @@ Allwinner Display Engine 2.0 Clock Control Binding
|
|||
Required properties :
|
||||
- compatible: must contain one of the following compatibles:
|
||||
- "allwinner,sun8i-a83t-de2-clk"
|
||||
- "allwinner,sun8i-h3-de2-clk"
|
||||
- "allwinner,sun8i-v3s-de2-clk"
|
||||
- "allwinner,sun50i-h5-de2-clk"
|
||||
|
||||
- reg: Must contain the registers base address and length
|
||||
- clocks: phandle to the clocks feeding the display engine subsystem.
|
||||
Three are needed:
|
||||
- "mod": the display engine module clock
|
||||
- "mod": the display engine module clock (on A83T it's the DE PLL)
|
||||
- "bus": the bus clock for the whole display engine subsystem
|
||||
- clock-names: Must contain the clock names described just above
|
||||
- resets: phandle to the reset control for the display engine subsystem.
|
||||
|
@ -19,7 +20,7 @@ Required properties :
|
|||
|
||||
Example:
|
||||
de2_clocks: clock@1000000 {
|
||||
compatible = "allwinner,sun8i-a83t-de2-clk";
|
||||
compatible = "allwinner,sun8i-h3-de2-clk";
|
||||
reg = <0x01000000 0x100000>;
|
||||
clocks = <&ccu CLK_BUS_DE>,
|
||||
<&ccu CLK_DE>;
|
||||
|
|
|
@ -142,6 +142,18 @@ config COMMON_CLK_GEMINI
|
|||
This driver supports the SoC clocks on the Cortina Systems Gemini
|
||||
platform, also known as SL3516 or CS3516.
|
||||
|
||||
config COMMON_CLK_ASPEED
|
||||
bool "Clock driver for Aspeed BMC SoCs"
|
||||
depends on ARCH_ASPEED || COMPILE_TEST
|
||||
default ARCH_ASPEED
|
||||
select MFD_SYSCON
|
||||
select RESET_CONTROLLER
|
||||
---help---
|
||||
This driver supports the SoC clocks on the Aspeed BMC platforms.
|
||||
|
||||
The G4 and G5 series, including the ast2400 and ast2500, are supported
|
||||
by this driver.
|
||||
|
||||
config COMMON_CLK_S2MPS11
|
||||
tristate "Clock driver for S2MPS1X/S5M8767 MFD"
|
||||
depends on MFD_SEC_CORE || COMPILE_TEST
|
||||
|
|
|
@ -27,6 +27,7 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
|
|||
obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
|
||||
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
|
||||
obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o
|
||||
obj-$(CONFIG_COMMON_CLK_ASPEED) += clk-aspeed.o
|
||||
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
||||
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
|
||||
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
|
||||
|
@ -67,7 +68,7 @@ obj-$(CONFIG_ARCH_MXC) += imx/
|
|||
obj-$(CONFIG_MACH_INGENIC) += ingenic/
|
||||
obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
|
||||
obj-$(CONFIG_MACH_LOONGSON32) += loongson1/
|
||||
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
|
||||
obj-y += mediatek/
|
||||
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/
|
||||
obj-$(CONFIG_MACH_PIC32) += microchip/
|
||||
ifeq ($(CONFIG_COMMON_CLK), y)
|
||||
|
|
|
@ -0,0 +1,667 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#define pr_fmt(fmt) "clk-aspeed: " fmt
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <dt-bindings/clock/aspeed-clock.h>
|
||||
|
||||
#define ASPEED_NUM_CLKS 35
|
||||
|
||||
#define ASPEED_RESET_CTRL 0x04
|
||||
#define ASPEED_CLK_SELECTION 0x08
|
||||
#define ASPEED_CLK_STOP_CTRL 0x0c
|
||||
#define ASPEED_MPLL_PARAM 0x20
|
||||
#define ASPEED_HPLL_PARAM 0x24
|
||||
#define AST2500_HPLL_BYPASS_EN BIT(20)
|
||||
#define AST2400_HPLL_STRAPPED BIT(18)
|
||||
#define AST2400_HPLL_BYPASS_EN BIT(17)
|
||||
#define ASPEED_MISC_CTRL 0x2c
|
||||
#define UART_DIV13_EN BIT(12)
|
||||
#define ASPEED_STRAP 0x70
|
||||
#define CLKIN_25MHZ_EN BIT(23)
|
||||
#define AST2400_CLK_SOURCE_SEL BIT(18)
|
||||
#define ASPEED_CLK_SELECTION_2 0xd8
|
||||
|
||||
/* Globally visible clocks */
|
||||
static DEFINE_SPINLOCK(aspeed_clk_lock);
|
||||
|
||||
/* Keeps track of all clocks */
|
||||
static struct clk_hw_onecell_data *aspeed_clk_data;
|
||||
|
||||
static void __iomem *scu_base;
|
||||
|
||||
/**
|
||||
* struct aspeed_gate_data - Aspeed gated clocks
|
||||
* @clock_idx: bit used to gate this clock in the clock register
|
||||
* @reset_idx: bit used to reset this IP in the reset register. -1 if no
|
||||
* reset is required when enabling the clock
|
||||
* @name: the clock name
|
||||
* @parent_name: the name of the parent clock
|
||||
* @flags: standard clock framework flags
|
||||
*/
|
||||
struct aspeed_gate_data {
|
||||
u8 clock_idx;
|
||||
s8 reset_idx;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct aspeed_clk_gate - Aspeed specific clk_gate structure
|
||||
* @hw: handle between common and hardware-specific interfaces
|
||||
* @reg: register controlling gate
|
||||
* @clock_idx: bit used to gate this clock in the clock register
|
||||
* @reset_idx: bit used to reset this IP in the reset register. -1 if no
|
||||
* reset is required when enabling the clock
|
||||
* @flags: hardware-specific flags
|
||||
* @lock: register lock
|
||||
*
|
||||
* Some of the clocks in the Aspeed SoC must be put in reset before enabling.
|
||||
* This modified version of clk_gate allows an optional reset bit to be
|
||||
* specified.
|
||||
*/
|
||||
struct aspeed_clk_gate {
|
||||
struct clk_hw hw;
|
||||
struct regmap *map;
|
||||
u8 clock_idx;
|
||||
s8 reset_idx;
|
||||
u8 flags;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
#define to_aspeed_clk_gate(_hw) container_of(_hw, struct aspeed_clk_gate, hw)
|
||||
|
||||
/* TODO: ask Aspeed about the actual parent data */
|
||||
static const struct aspeed_gate_data aspeed_gates[] = {
|
||||
/* clk rst name parent flags */
|
||||
[ASPEED_CLK_GATE_ECLK] = { 0, -1, "eclk-gate", "eclk", 0 }, /* Video Engine */
|
||||
[ASPEED_CLK_GATE_GCLK] = { 1, 7, "gclk-gate", NULL, 0 }, /* 2D engine */
|
||||
[ASPEED_CLK_GATE_MCLK] = { 2, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */
|
||||
[ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */
|
||||
[ASPEED_CLK_GATE_BCLK] = { 4, 10, "bclk-gate", "bclk", 0 }, /* PCIe/PCI */
|
||||
[ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, 0 }, /* DAC */
|
||||
[ASPEED_CLK_GATE_REFCLK] = { 6, -1, "refclk-gate", "clkin", CLK_IS_CRITICAL },
|
||||
[ASPEED_CLK_GATE_USBPORT2CLK] = { 7, 3, "usb-port2-gate", NULL, 0 }, /* USB2.0 Host port 2 */
|
||||
[ASPEED_CLK_GATE_LCLK] = { 8, 5, "lclk-gate", NULL, 0 }, /* LPC */
|
||||
[ASPEED_CLK_GATE_USBUHCICLK] = { 9, 15, "usb-uhci-gate", NULL, 0 }, /* USB1.1 (requires port 2 enabled) */
|
||||
[ASPEED_CLK_GATE_D1CLK] = { 10, 13, "d1clk-gate", NULL, 0 }, /* GFX CRT */
|
||||
[ASPEED_CLK_GATE_YCLK] = { 13, 4, "yclk-gate", NULL, 0 }, /* HAC */
|
||||
[ASPEED_CLK_GATE_USBPORT1CLK] = { 14, 14, "usb-port1-gate", NULL, 0 }, /* USB2 hub/USB2 host port 1/USB1.1 dev */
|
||||
[ASPEED_CLK_GATE_UART1CLK] = { 15, -1, "uart1clk-gate", "uart", 0 }, /* UART1 */
|
||||
[ASPEED_CLK_GATE_UART2CLK] = { 16, -1, "uart2clk-gate", "uart", 0 }, /* UART2 */
|
||||
[ASPEED_CLK_GATE_UART5CLK] = { 17, -1, "uart5clk-gate", "uart", 0 }, /* UART5 */
|
||||
[ASPEED_CLK_GATE_ESPICLK] = { 19, -1, "espiclk-gate", NULL, 0 }, /* eSPI */
|
||||
[ASPEED_CLK_GATE_MAC1CLK] = { 20, 11, "mac1clk-gate", "mac", 0 }, /* MAC1 */
|
||||
[ASPEED_CLK_GATE_MAC2CLK] = { 21, 12, "mac2clk-gate", "mac", 0 }, /* MAC2 */
|
||||
[ASPEED_CLK_GATE_RSACLK] = { 24, -1, "rsaclk-gate", NULL, 0 }, /* RSA */
|
||||
[ASPEED_CLK_GATE_UART3CLK] = { 25, -1, "uart3clk-gate", "uart", 0 }, /* UART3 */
|
||||
[ASPEED_CLK_GATE_UART4CLK] = { 26, -1, "uart4clk-gate", "uart", 0 }, /* UART4 */
|
||||
[ASPEED_CLK_GATE_SDCLKCLK] = { 27, 16, "sdclk-gate", NULL, 0 }, /* SDIO/SD */
|
||||
[ASPEED_CLK_GATE_LHCCLK] = { 28, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */
|
||||
};
|
||||
|
||||
static const struct clk_div_table ast2500_mac_div_table[] = {
|
||||
{ 0x0, 4 }, /* Yep, really. Aspeed confirmed this is correct */
|
||||
{ 0x1, 4 },
|
||||
{ 0x2, 6 },
|
||||
{ 0x3, 8 },
|
||||
{ 0x4, 10 },
|
||||
{ 0x5, 12 },
|
||||
{ 0x6, 14 },
|
||||
{ 0x7, 16 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct clk_div_table ast2400_div_table[] = {
|
||||
{ 0x0, 2 },
|
||||
{ 0x1, 4 },
|
||||
{ 0x2, 6 },
|
||||
{ 0x3, 8 },
|
||||
{ 0x4, 10 },
|
||||
{ 0x5, 12 },
|
||||
{ 0x6, 14 },
|
||||
{ 0x7, 16 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct clk_div_table ast2500_div_table[] = {
|
||||
{ 0x0, 4 },
|
||||
{ 0x1, 8 },
|
||||
{ 0x2, 12 },
|
||||
{ 0x3, 16 },
|
||||
{ 0x4, 20 },
|
||||
{ 0x5, 24 },
|
||||
{ 0x6, 28 },
|
||||
{ 0x7, 32 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static struct clk_hw *aspeed_ast2400_calc_pll(const char *name, u32 val)
|
||||
{
|
||||
unsigned int mult, div;
|
||||
|
||||
if (val & AST2400_HPLL_BYPASS_EN) {
|
||||
/* Pass through mode */
|
||||
mult = div = 1;
|
||||
} else {
|
||||
/* F = 24Mhz * (2-OD) * [(N + 2) / (D + 1)] */
|
||||
u32 n = (val >> 5) & 0x3f;
|
||||
u32 od = (val >> 4) & 0x1;
|
||||
u32 d = val & 0xf;
|
||||
|
||||
mult = (2 - od) * (n + 2);
|
||||
div = d + 1;
|
||||
}
|
||||
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
|
||||
mult, div);
|
||||
};
|
||||
|
||||
static struct clk_hw *aspeed_ast2500_calc_pll(const char *name, u32 val)
|
||||
{
|
||||
unsigned int mult, div;
|
||||
|
||||
if (val & AST2500_HPLL_BYPASS_EN) {
|
||||
/* Pass through mode */
|
||||
mult = div = 1;
|
||||
} else {
|
||||
/* F = clkin * [(M+1) / (N+1)] / (P + 1) */
|
||||
u32 p = (val >> 13) & 0x3f;
|
||||
u32 m = (val >> 5) & 0xff;
|
||||
u32 n = val & 0x1f;
|
||||
|
||||
mult = (m + 1) / (n + 1);
|
||||
div = p + 1;
|
||||
}
|
||||
|
||||
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
|
||||
mult, div);
|
||||
}
|
||||
|
||||
struct aspeed_clk_soc_data {
|
||||
const struct clk_div_table *div_table;
|
||||
const struct clk_div_table *mac_div_table;
|
||||
struct clk_hw *(*calc_pll)(const char *name, u32 val);
|
||||
};
|
||||
|
||||
static const struct aspeed_clk_soc_data ast2500_data = {
|
||||
.div_table = ast2500_div_table,
|
||||
.mac_div_table = ast2500_mac_div_table,
|
||||
.calc_pll = aspeed_ast2500_calc_pll,
|
||||
};
|
||||
|
||||
static const struct aspeed_clk_soc_data ast2400_data = {
|
||||
.div_table = ast2400_div_table,
|
||||
.mac_div_table = ast2400_div_table,
|
||||
.calc_pll = aspeed_ast2400_calc_pll,
|
||||
};
|
||||
|
||||
static int aspeed_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
unsigned long flags;
|
||||
u32 clk = BIT(gate->clock_idx);
|
||||
u32 rst = BIT(gate->reset_idx);
|
||||
u32 enval;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (gate->reset_idx >= 0) {
|
||||
/* Put IP in reset */
|
||||
regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, rst);
|
||||
|
||||
/* Delay 100us */
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
/* Enable clock */
|
||||
enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
|
||||
regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
|
||||
|
||||
if (gate->reset_idx >= 0) {
|
||||
/* A delay of 10ms is specified by the ASPEED docs */
|
||||
mdelay(10);
|
||||
|
||||
/* Take IP out of reset */
|
||||
regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, 0);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aspeed_clk_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
unsigned long flags;
|
||||
u32 clk = BIT(gate->clock_idx);
|
||||
u32 enval;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? clk : 0;
|
||||
regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, enval);
|
||||
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
}
|
||||
|
||||
static int aspeed_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
u32 clk = BIT(gate->clock_idx);
|
||||
u32 reg;
|
||||
|
||||
regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, ®);
|
||||
|
||||
return (reg & clk) ? 0 : 1;
|
||||
}
|
||||
|
||||
static const struct clk_ops aspeed_clk_gate_ops = {
|
||||
.enable = aspeed_clk_enable,
|
||||
.disable = aspeed_clk_disable,
|
||||
.is_enabled = aspeed_clk_is_enabled,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct aspeed_reset - Aspeed reset controller
|
||||
* @map: regmap to access the containing system controller
|
||||
* @rcdev: reset controller device
|
||||
*/
|
||||
struct aspeed_reset {
|
||||
struct regmap *map;
|
||||
struct reset_controller_dev rcdev;
|
||||
};
|
||||
|
||||
#define to_aspeed_reset(p) container_of((p), struct aspeed_reset, rcdev)
|
||||
|
||||
static const u8 aspeed_resets[] = {
|
||||
[ASPEED_RESET_XDMA] = 25,
|
||||
[ASPEED_RESET_MCTP] = 24,
|
||||
[ASPEED_RESET_ADC] = 23,
|
||||
[ASPEED_RESET_JTAG_MASTER] = 22,
|
||||
[ASPEED_RESET_MIC] = 18,
|
||||
[ASPEED_RESET_PWM] = 9,
|
||||
[ASPEED_RESET_PCIVGA] = 8,
|
||||
[ASPEED_RESET_I2C] = 2,
|
||||
[ASPEED_RESET_AHB] = 1,
|
||||
};
|
||||
|
||||
static int aspeed_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
|
||||
u32 rst = BIT(aspeed_resets[id]);
|
||||
|
||||
return regmap_update_bits(ar->map, ASPEED_RESET_CTRL, rst, 0);
|
||||
}
|
||||
|
||||
static int aspeed_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
|
||||
u32 rst = BIT(aspeed_resets[id]);
|
||||
|
||||
return regmap_update_bits(ar->map, ASPEED_RESET_CTRL, rst, rst);
|
||||
}
|
||||
|
||||
static int aspeed_reset_status(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
|
||||
u32 val, rst = BIT(aspeed_resets[id]);
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(ar->map, ASPEED_RESET_CTRL, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return !!(val & rst);
|
||||
}
|
||||
|
||||
static const struct reset_control_ops aspeed_reset_ops = {
|
||||
.assert = aspeed_reset_assert,
|
||||
.deassert = aspeed_reset_deassert,
|
||||
.status = aspeed_reset_status,
|
||||
};
|
||||
|
||||
static struct clk_hw *aspeed_clk_hw_register_gate(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
struct regmap *map, u8 clock_idx, u8 reset_idx,
|
||||
u8 clk_gate_flags, spinlock_t *lock)
|
||||
{
|
||||
struct aspeed_clk_gate *gate;
|
||||
struct clk_init_data init;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &aspeed_clk_gate_ops;
|
||||
init.flags = flags;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
|
||||
gate->map = map;
|
||||
gate->clock_idx = clock_idx;
|
||||
gate->reset_idx = reset_idx;
|
||||
gate->flags = clk_gate_flags;
|
||||
gate->lock = lock;
|
||||
gate->hw.init = &init;
|
||||
|
||||
hw = &gate->hw;
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(gate);
|
||||
hw = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static int aspeed_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct aspeed_clk_soc_data *soc_data;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct aspeed_reset *ar;
|
||||
struct regmap *map;
|
||||
struct clk_hw *hw;
|
||||
u32 val, rate;
|
||||
int i, ret;
|
||||
|
||||
map = syscon_node_to_regmap(dev->of_node);
|
||||
if (IS_ERR(map)) {
|
||||
dev_err(dev, "no syscon regmap\n");
|
||||
return PTR_ERR(map);
|
||||
}
|
||||
|
||||
ar = devm_kzalloc(dev, sizeof(*ar), GFP_KERNEL);
|
||||
if (!ar)
|
||||
return -ENOMEM;
|
||||
|
||||
ar->map = map;
|
||||
ar->rcdev.owner = THIS_MODULE;
|
||||
ar->rcdev.nr_resets = ARRAY_SIZE(aspeed_resets);
|
||||
ar->rcdev.ops = &aspeed_reset_ops;
|
||||
ar->rcdev.of_node = dev->of_node;
|
||||
|
||||
ret = devm_reset_controller_register(dev, &ar->rcdev);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not register reset controller\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* SoC generations share common layouts but have different divisors */
|
||||
soc_data = of_device_get_match_data(dev);
|
||||
if (!soc_data) {
|
||||
dev_err(dev, "no match data for platform\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* UART clock div13 setting */
|
||||
regmap_read(map, ASPEED_MISC_CTRL, &val);
|
||||
if (val & UART_DIV13_EN)
|
||||
rate = 24000000 / 13;
|
||||
else
|
||||
rate = 24000000;
|
||||
/* TODO: Find the parent data for the uart clock */
|
||||
hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_UART] = hw;
|
||||
|
||||
/*
|
||||
* Memory controller (M-PLL) PLL. This clock is configured by the
|
||||
* bootloader, and is exposed to Linux as a read-only clock rate.
|
||||
*/
|
||||
regmap_read(map, ASPEED_MPLL_PARAM, &val);
|
||||
hw = soc_data->calc_pll("mpll", val);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_MPLL] = hw;
|
||||
|
||||
/* SD/SDIO clock divider (TODO: There's a gate too) */
|
||||
hw = clk_hw_register_divider_table(dev, "sdio", "hpll", 0,
|
||||
scu_base + ASPEED_CLK_SELECTION, 12, 3, 0,
|
||||
soc_data->div_table,
|
||||
&aspeed_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_SDIO] = hw;
|
||||
|
||||
/* MAC AHB bus clock divider */
|
||||
hw = clk_hw_register_divider_table(dev, "mac", "hpll", 0,
|
||||
scu_base + ASPEED_CLK_SELECTION, 16, 3, 0,
|
||||
soc_data->mac_div_table,
|
||||
&aspeed_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_MAC] = hw;
|
||||
|
||||
/* LPC Host (LHCLK) clock divider */
|
||||
hw = clk_hw_register_divider_table(dev, "lhclk", "hpll", 0,
|
||||
scu_base + ASPEED_CLK_SELECTION, 20, 3, 0,
|
||||
soc_data->div_table,
|
||||
&aspeed_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_LHCLK] = hw;
|
||||
|
||||
/* P-Bus (BCLK) clock divider */
|
||||
hw = clk_hw_register_divider_table(dev, "bclk", "hpll", 0,
|
||||
scu_base + ASPEED_CLK_SELECTION_2, 0, 2, 0,
|
||||
soc_data->div_table,
|
||||
&aspeed_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_BCLK] = hw;
|
||||
|
||||
/*
|
||||
* TODO: There are a number of clocks that not included in this driver
|
||||
* as more information is required:
|
||||
* D2-PLL
|
||||
* D-PLL
|
||||
* YCLK
|
||||
* RGMII
|
||||
* RMII
|
||||
* UART[1..5] clock source mux
|
||||
* Video Engine (ECLK) mux and clock divider
|
||||
*/
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) {
|
||||
const struct aspeed_gate_data *gd = &aspeed_gates[i];
|
||||
u32 gate_flags;
|
||||
|
||||
/* Special case: the USB port 1 clock (bit 14) is always
|
||||
* working the opposite way from the other ones.
|
||||
*/
|
||||
gate_flags = (gd->clock_idx == 14) ? 0 : CLK_GATE_SET_TO_DISABLE;
|
||||
hw = aspeed_clk_hw_register_gate(dev,
|
||||
gd->name,
|
||||
gd->parent_name,
|
||||
gd->flags,
|
||||
map,
|
||||
gd->clock_idx,
|
||||
gd->reset_idx,
|
||||
gate_flags,
|
||||
&aspeed_clk_lock);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
aspeed_clk_data->hws[i] = hw;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static const struct of_device_id aspeed_clk_dt_ids[] = {
|
||||
{ .compatible = "aspeed,ast2400-scu", .data = &ast2400_data },
|
||||
{ .compatible = "aspeed,ast2500-scu", .data = &ast2500_data },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver aspeed_clk_driver = {
|
||||
.probe = aspeed_clk_probe,
|
||||
.driver = {
|
||||
.name = "aspeed-clk",
|
||||
.of_match_table = aspeed_clk_dt_ids,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(aspeed_clk_driver);
|
||||
|
||||
static void __init aspeed_ast2400_cc(struct regmap *map)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
u32 val, freq, div;
|
||||
|
||||
/*
|
||||
* CLKIN is the crystal oscillator, 24, 48 or 25MHz selected by
|
||||
* strapping
|
||||
*/
|
||||
regmap_read(map, ASPEED_STRAP, &val);
|
||||
if (val & CLKIN_25MHZ_EN)
|
||||
freq = 25000000;
|
||||
else if (val & AST2400_CLK_SOURCE_SEL)
|
||||
freq = 48000000;
|
||||
else
|
||||
freq = 24000000;
|
||||
hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, freq);
|
||||
pr_debug("clkin @%u MHz\n", freq / 1000000);
|
||||
|
||||
/*
|
||||
* High-speed PLL clock derived from the crystal. This the CPU clock,
|
||||
* and we assume that it is enabled
|
||||
*/
|
||||
regmap_read(map, ASPEED_HPLL_PARAM, &val);
|
||||
WARN(val & AST2400_HPLL_STRAPPED, "hpll is strapped not configured");
|
||||
aspeed_clk_data->hws[ASPEED_CLK_HPLL] = aspeed_ast2400_calc_pll("hpll", val);
|
||||
|
||||
/*
|
||||
* Strap bits 11:10 define the CPU/AHB clock frequency ratio (aka HCLK)
|
||||
* 00: Select CPU:AHB = 1:1
|
||||
* 01: Select CPU:AHB = 2:1
|
||||
* 10: Select CPU:AHB = 4:1
|
||||
* 11: Select CPU:AHB = 3:1
|
||||
*/
|
||||
regmap_read(map, ASPEED_STRAP, &val);
|
||||
val = (val >> 10) & 0x3;
|
||||
div = val + 1;
|
||||
if (div == 3)
|
||||
div = 4;
|
||||
else if (div == 4)
|
||||
div = 3;
|
||||
hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, div);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_AHB] = hw;
|
||||
|
||||
/* APB clock clock selection register SCU08 (aka PCLK) */
|
||||
hw = clk_hw_register_divider_table(NULL, "apb", "hpll", 0,
|
||||
scu_base + ASPEED_CLK_SELECTION, 23, 3, 0,
|
||||
ast2400_div_table,
|
||||
&aspeed_clk_lock);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_APB] = hw;
|
||||
}
|
||||
|
||||
static void __init aspeed_ast2500_cc(struct regmap *map)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
u32 val, freq, div;
|
||||
|
||||
/* CLKIN is the crystal oscillator, 24 or 25MHz selected by strapping */
|
||||
regmap_read(map, ASPEED_STRAP, &val);
|
||||
if (val & CLKIN_25MHZ_EN)
|
||||
freq = 25000000;
|
||||
else
|
||||
freq = 24000000;
|
||||
hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, freq);
|
||||
pr_debug("clkin @%u MHz\n", freq / 1000000);
|
||||
|
||||
/*
|
||||
* High-speed PLL clock derived from the crystal. This the CPU clock,
|
||||
* and we assume that it is enabled
|
||||
*/
|
||||
regmap_read(map, ASPEED_HPLL_PARAM, &val);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_HPLL] = aspeed_ast2500_calc_pll("hpll", val);
|
||||
|
||||
/* Strap bits 11:9 define the AXI/AHB clock frequency ratio (aka HCLK)*/
|
||||
regmap_read(map, ASPEED_STRAP, &val);
|
||||
val = (val >> 9) & 0x7;
|
||||
WARN(val == 0, "strapping is zero: cannot determine ahb clock");
|
||||
div = 2 * (val + 1);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, div);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_AHB] = hw;
|
||||
|
||||
/* APB clock clock selection register SCU08 (aka PCLK) */
|
||||
regmap_read(map, ASPEED_CLK_SELECTION, &val);
|
||||
val = (val >> 23) & 0x7;
|
||||
div = 4 * (val + 1);
|
||||
hw = clk_hw_register_fixed_factor(NULL, "apb", "hpll", 0, 1, div);
|
||||
aspeed_clk_data->hws[ASPEED_CLK_APB] = hw;
|
||||
};
|
||||
|
||||
static void __init aspeed_cc_init(struct device_node *np)
|
||||
{
|
||||
struct regmap *map;
|
||||
u32 val;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
scu_base = of_iomap(np, 0);
|
||||
if (!scu_base)
|
||||
return;
|
||||
|
||||
aspeed_clk_data = kzalloc(sizeof(*aspeed_clk_data) +
|
||||
sizeof(*aspeed_clk_data->hws) * ASPEED_NUM_CLKS,
|
||||
GFP_KERNEL);
|
||||
if (!aspeed_clk_data)
|
||||
return;
|
||||
|
||||
/*
|
||||
* This way all clocks fetched before the platform device probes,
|
||||
* except those we assign here for early use, will be deferred.
|
||||
*/
|
||||
for (i = 0; i < ASPEED_NUM_CLKS; i++)
|
||||
aspeed_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
map = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(map)) {
|
||||
pr_err("no syscon regmap\n");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* We check that the regmap works on this very first access,
|
||||
* but as this is an MMIO-backed regmap, subsequent regmap
|
||||
* access is not going to fail and we skip error checks from
|
||||
* this point.
|
||||
*/
|
||||
ret = regmap_read(map, ASPEED_STRAP, &val);
|
||||
if (ret) {
|
||||
pr_err("failed to read strapping register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "aspeed,ast2400-scu"))
|
||||
aspeed_ast2400_cc(map);
|
||||
else if (of_device_is_compatible(np, "aspeed,ast2500-scu"))
|
||||
aspeed_ast2500_cc(map);
|
||||
else
|
||||
pr_err("unknown platform, failed to add clocks\n");
|
||||
|
||||
aspeed_clk_data->num = ASPEED_NUM_CLKS;
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, aspeed_clk_data);
|
||||
if (ret)
|
||||
pr_err("failed to add DT provider: %d\n", ret);
|
||||
};
|
||||
CLK_OF_DECLARE_DRIVER(aspeed_cc_g5, "aspeed,ast2500-scu", aspeed_cc_init);
|
||||
CLK_OF_DECLARE_DRIVER(aspeed_cc_g4, "aspeed,ast2400-scu", aspeed_cc_init);
|
|
@ -144,10 +144,18 @@ static unsigned long clk_enable_lock(void)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!spin_trylock_irqsave(&enable_lock, flags)) {
|
||||
/*
|
||||
* On UP systems, spin_trylock_irqsave() always returns true, even if
|
||||
* we already hold the lock. So, in that case, we rely only on
|
||||
* reference counting.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_SMP) ||
|
||||
!spin_trylock_irqsave(&enable_lock, flags)) {
|
||||
if (enable_owner == current) {
|
||||
enable_refcnt++;
|
||||
__acquire(enable_lock);
|
||||
if (!IS_ENABLED(CONFIG_SMP))
|
||||
local_save_flags(flags);
|
||||
return flags;
|
||||
}
|
||||
spin_lock_irqsave(&enable_lock, flags);
|
||||
|
|
|
@ -1,136 +1,140 @@
|
|||
#
|
||||
# MediaTek SoC drivers
|
||||
# MediaTek Clock Drivers
|
||||
#
|
||||
menu "Clock driver for MediaTek SoC"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
|
||||
config COMMON_CLK_MEDIATEK
|
||||
bool
|
||||
select RESET_CONTROLLER
|
||||
---help---
|
||||
Mediatek SoCs' clock support.
|
||||
MediaTek SoCs' clock support.
|
||||
|
||||
config COMMON_CLK_MT2701
|
||||
bool "Clock driver for Mediatek MT2701"
|
||||
bool "Clock driver for MediaTek MT2701"
|
||||
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK && ARM
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 basic clocks.
|
||||
This driver supports MediaTek MT2701 basic clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_MMSYS
|
||||
bool "Clock driver for Mediatek MT2701 mmsys"
|
||||
bool "Clock driver for MediaTek MT2701 mmsys"
|
||||
depends on COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 mmsys clocks.
|
||||
This driver supports MediaTek MT2701 mmsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_IMGSYS
|
||||
bool "Clock driver for Mediatek MT2701 imgsys"
|
||||
bool "Clock driver for MediaTek MT2701 imgsys"
|
||||
depends on COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 imgsys clocks.
|
||||
This driver supports MediaTek MT2701 imgsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_VDECSYS
|
||||
bool "Clock driver for Mediatek MT2701 vdecsys"
|
||||
bool "Clock driver for MediaTek MT2701 vdecsys"
|
||||
depends on COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 vdecsys clocks.
|
||||
This driver supports MediaTek MT2701 vdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_HIFSYS
|
||||
bool "Clock driver for Mediatek MT2701 hifsys"
|
||||
bool "Clock driver for MediaTek MT2701 hifsys"
|
||||
depends on COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 hifsys clocks.
|
||||
This driver supports MediaTek MT2701 hifsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_ETHSYS
|
||||
bool "Clock driver for Mediatek MT2701 ethsys"
|
||||
bool "Clock driver for MediaTek MT2701 ethsys"
|
||||
depends on COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 ethsys clocks.
|
||||
This driver supports MediaTek MT2701 ethsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_BDPSYS
|
||||
bool "Clock driver for Mediatek MT2701 bdpsys"
|
||||
bool "Clock driver for MediaTek MT2701 bdpsys"
|
||||
depends on COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 bdpsys clocks.
|
||||
This driver supports MediaTek MT2701 bdpsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712
|
||||
bool "Clock driver for Mediatek MT2712"
|
||||
bool "Clock driver for MediaTek MT2712"
|
||||
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK && ARM64
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 basic clocks.
|
||||
This driver supports MediaTek MT2712 basic clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_BDPSYS
|
||||
bool "Clock driver for Mediatek MT2712 bdpsys"
|
||||
bool "Clock driver for MediaTek MT2712 bdpsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 bdpsys clocks.
|
||||
This driver supports MediaTek MT2712 bdpsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_IMGSYS
|
||||
bool "Clock driver for Mediatek MT2712 imgsys"
|
||||
bool "Clock driver for MediaTek MT2712 imgsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 imgsys clocks.
|
||||
This driver supports MediaTek MT2712 imgsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_JPGDECSYS
|
||||
bool "Clock driver for Mediatek MT2712 jpgdecsys"
|
||||
bool "Clock driver for MediaTek MT2712 jpgdecsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 jpgdecsys clocks.
|
||||
This driver supports MediaTek MT2712 jpgdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_MFGCFG
|
||||
bool "Clock driver for Mediatek MT2712 mfgcfg"
|
||||
bool "Clock driver for MediaTek MT2712 mfgcfg"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 mfgcfg clocks.
|
||||
This driver supports MediaTek MT2712 mfgcfg clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_MMSYS
|
||||
bool "Clock driver for Mediatek MT2712 mmsys"
|
||||
bool "Clock driver for MediaTek MT2712 mmsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 mmsys clocks.
|
||||
This driver supports MediaTek MT2712 mmsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_VDECSYS
|
||||
bool "Clock driver for Mediatek MT2712 vdecsys"
|
||||
bool "Clock driver for MediaTek MT2712 vdecsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 vdecsys clocks.
|
||||
This driver supports MediaTek MT2712 vdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2712_VENCSYS
|
||||
bool "Clock driver for Mediatek MT2712 vencsys"
|
||||
bool "Clock driver for MediaTek MT2712 vencsys"
|
||||
depends on COMMON_CLK_MT2712
|
||||
---help---
|
||||
This driver supports Mediatek MT2712 vencsys clocks.
|
||||
This driver supports MediaTek MT2712 vencsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797
|
||||
bool "Clock driver for Mediatek MT6797"
|
||||
bool "Clock driver for MediaTek MT6797"
|
||||
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK && ARM64
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 basic clocks.
|
||||
This driver supports MediaTek MT6797 basic clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_MMSYS
|
||||
bool "Clock driver for Mediatek MT6797 mmsys"
|
||||
bool "Clock driver for MediaTek MT6797 mmsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 mmsys clocks.
|
||||
This driver supports MediaTek MT6797 mmsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_IMGSYS
|
||||
bool "Clock driver for Mediatek MT6797 imgsys"
|
||||
bool "Clock driver for MediaTek MT6797 imgsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 imgsys clocks.
|
||||
This driver supports MediaTek MT6797 imgsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_VDECSYS
|
||||
bool "Clock driver for Mediatek MT6797 vdecsys"
|
||||
bool "Clock driver for MediaTek MT6797 vdecsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 vdecsys clocks.
|
||||
This driver supports MediaTek MT6797 vdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT6797_VENCSYS
|
||||
bool "Clock driver for Mediatek MT6797 vencsys"
|
||||
bool "Clock driver for MediaTek MT6797 vencsys"
|
||||
depends on COMMON_CLK_MT6797
|
||||
---help---
|
||||
This driver supports Mediatek MT6797 vencsys clocks.
|
||||
This driver supports MediaTek MT6797 vencsys clocks.
|
||||
|
||||
config COMMON_CLK_MT7622
|
||||
bool "Clock driver for MediaTek MT7622"
|
||||
|
@ -163,17 +167,18 @@ config COMMON_CLK_MT7622_AUDSYS
|
|||
to audio consumers such as I2S and TDM.
|
||||
|
||||
config COMMON_CLK_MT8135
|
||||
bool "Clock driver for Mediatek MT8135"
|
||||
bool "Clock driver for MediaTek MT8135"
|
||||
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK && ARM
|
||||
---help---
|
||||
This driver supports Mediatek MT8135 clocks.
|
||||
This driver supports MediaTek MT8135 clocks.
|
||||
|
||||
config COMMON_CLK_MT8173
|
||||
bool "Clock driver for Mediatek MT8173"
|
||||
bool "Clock driver for MediaTek MT8173"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK
|
||||
---help---
|
||||
This driver supports Mediatek MT8173 clocks.
|
||||
This driver supports MediaTek MT8173 clocks.
|
||||
endmenu
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o
|
||||
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
|
||||
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/clk-provider.h>
|
||||
|
||||
struct clk;
|
||||
struct clk_onecell_data;
|
||||
|
||||
#define MAX_MUX_GATE_BIT 31
|
||||
#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
|
||||
|
@ -228,14 +229,7 @@ void mtk_clk_register_plls(struct device_node *node,
|
|||
struct clk *mtk_clk_register_ref2usb_tx(const char *name,
|
||||
const char *parent_name, void __iomem *reg);
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
void mtk_register_reset_controller(struct device_node *np,
|
||||
unsigned int num_regs, int regofs);
|
||||
#else
|
||||
static inline void mtk_register_reset_controller(struct device_node *np,
|
||||
unsigned int num_regs, int regofs)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DRV_CLK_MTK_H */
|
||||
|
|
|
@ -400,28 +400,45 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080,
|
|||
BIT(31), /* gate */
|
||||
0);
|
||||
|
||||
/*
|
||||
* MMC clocks are the new timing mode (see A83T & H3) variety, but without
|
||||
* the mode switch. This means they have a 2x post divider between the clock
|
||||
* and the MMC module. This is not documented in the manual, but is taken
|
||||
* into consideration when setting the mmc module clocks in the BSP kernel.
|
||||
* Without it, MMC performance is degraded.
|
||||
*
|
||||
* We model it here to be consistent with other SoCs supporting this mode.
|
||||
* The alternative would be to add the 2x multiplier when setting the MMC
|
||||
* module clock in the MMC driver, just for the A64.
|
||||
*/
|
||||
static const char * const mmc_default_parents[] = { "osc24M", "pll-periph0-2x",
|
||||
"pll-periph1-2x" };
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_default_parents, 0x088,
|
||||
0, 4, /* M */
|
||||
16, 2, /* P */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0",
|
||||
mmc_default_parents, 0x088,
|
||||
0, 4, /* M */
|
||||
16, 2, /* P */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
2, /* post-div */
|
||||
0);
|
||||
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_default_parents, 0x08c,
|
||||
0, 4, /* M */
|
||||
16, 2, /* P */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1",
|
||||
mmc_default_parents, 0x08c,
|
||||
0, 4, /* M */
|
||||
16, 2, /* P */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
2, /* post-div */
|
||||
0);
|
||||
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_default_parents, 0x090,
|
||||
0, 4, /* M */
|
||||
16, 2, /* P */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
0);
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2",
|
||||
mmc_default_parents, 0x090,
|
||||
0, 4, /* M */
|
||||
16, 2, /* P */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
2, /* post-div */
|
||||
0);
|
||||
|
||||
static const char * const ts_parents[] = { "osc24M", "pll-periph0", };
|
||||
static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098,
|
||||
|
|
|
@ -76,15 +76,26 @@ static struct ccu_mult pll_c1cpux_clk = {
|
|||
*/
|
||||
#define SUN8I_A83T_PLL_AUDIO_REG 0x008
|
||||
|
||||
/* clock rates doubled for post divider */
|
||||
static struct ccu_sdm_setting pll_audio_sdm_table[] = {
|
||||
{ .rate = 45158400, .pattern = 0xc00121ff, .m = 29, .n = 54 },
|
||||
{ .rate = 49152000, .pattern = 0xc000e147, .m = 30, .n = 61 },
|
||||
};
|
||||
|
||||
static struct ccu_nm pll_audio_clk = {
|
||||
.enable = BIT(31),
|
||||
.lock = BIT(2),
|
||||
.n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
|
||||
.m = _SUNXI_CCU_DIV(0, 6),
|
||||
.fixed_post_div = 2,
|
||||
.sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24),
|
||||
0x284, BIT(31)),
|
||||
.common = {
|
||||
.reg = SUN8I_A83T_PLL_AUDIO_REG,
|
||||
.lock_reg = CCU_SUN8I_A83T_LOCK_REG,
|
||||
.features = CCU_FEATURE_LOCK_REG,
|
||||
.features = CCU_FEATURE_LOCK_REG |
|
||||
CCU_FEATURE_FIXED_POSTDIV |
|
||||
CCU_FEATURE_SIGMA_DELTA_MOD,
|
||||
.hw.init = CLK_HW_INIT("pll-audio", "osc24M",
|
||||
&ccu_nm_ops, CLK_SET_RATE_UNGATE),
|
||||
},
|
||||
|
@ -493,8 +504,8 @@ static SUNXI_CCU_MUX_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
|
|||
0x118, 24, 3, BIT(31), CLK_SET_RATE_PARENT);
|
||||
|
||||
static const char * const tcon1_parents[] = { "pll-video1" };
|
||||
static SUNXI_CCU_MUX_WITH_GATE(tcon1_clk, "tcon1", tcon1_parents,
|
||||
0x11c, 24, 3, BIT(31), CLK_SET_RATE_PARENT);
|
||||
static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_clk, "tcon1", tcon1_parents,
|
||||
0x11c, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
|
||||
|
||||
static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x130, BIT(16), 0);
|
||||
|
||||
|
@ -889,9 +900,10 @@ static int sun8i_a83t_ccu_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(reg))
|
||||
return PTR_ERR(reg);
|
||||
|
||||
/* Enforce d1 = 0, d2 = 0 for Audio PLL */
|
||||
/* Enforce d1 = 0, d2 = 1 for Audio PLL */
|
||||
val = readl(reg + SUN8I_A83T_PLL_AUDIO_REG);
|
||||
val &= ~(BIT(16) | BIT(18));
|
||||
val &= ~BIT(16);
|
||||
val |= BIT(18);
|
||||
writel(val, reg + SUN8I_A83T_PLL_AUDIO_REG);
|
||||
|
||||
/* Enforce P = 1 for both CPU cluster PLLs */
|
||||
|
|
|
@ -41,6 +41,8 @@ static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div",
|
|||
|
||||
static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
|
||||
CLK_SET_RATE_PARENT);
|
||||
static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
|
||||
CLK_SET_RATE_PARENT);
|
||||
static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
|
@ -65,6 +67,20 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = {
|
|||
&wb_div_a83_clk.common,
|
||||
};
|
||||
|
||||
static struct ccu_common *sun8i_h3_de2_clks[] = {
|
||||
&mixer0_clk.common,
|
||||
&mixer1_clk.common,
|
||||
&wb_clk.common,
|
||||
|
||||
&bus_mixer0_clk.common,
|
||||
&bus_mixer1_clk.common,
|
||||
&bus_wb_clk.common,
|
||||
|
||||
&mixer0_div_clk.common,
|
||||
&mixer1_div_clk.common,
|
||||
&wb_div_clk.common,
|
||||
};
|
||||
|
||||
static struct ccu_common *sun8i_v3s_de2_clks[] = {
|
||||
&mixer0_clk.common,
|
||||
&wb_clk.common,
|
||||
|
@ -93,6 +109,23 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
|
|||
.num = CLK_NUMBER,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = {
|
||||
.hws = {
|
||||
[CLK_MIXER0] = &mixer0_clk.common.hw,
|
||||
[CLK_MIXER1] = &mixer1_clk.common.hw,
|
||||
[CLK_WB] = &wb_clk.common.hw,
|
||||
|
||||
[CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw,
|
||||
[CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw,
|
||||
[CLK_BUS_WB] = &bus_wb_clk.common.hw,
|
||||
|
||||
[CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw,
|
||||
[CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw,
|
||||
[CLK_WB_DIV] = &wb_div_clk.common.hw,
|
||||
},
|
||||
.num = CLK_NUMBER,
|
||||
};
|
||||
|
||||
static struct clk_hw_onecell_data sun8i_v3s_de2_hw_clks = {
|
||||
.hws = {
|
||||
[CLK_MIXER0] = &mixer0_clk.common.hw,
|
||||
|
@ -133,11 +166,21 @@ static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
|
|||
.num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets),
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
|
||||
.ccu_clks = sun8i_a83t_de2_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun8i_a83t_de2_clks),
|
||||
static const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = {
|
||||
.ccu_clks = sun8i_h3_de2_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks),
|
||||
|
||||
.hw_clks = &sun8i_a83t_de2_hw_clks,
|
||||
.hw_clks = &sun8i_h3_de2_hw_clks,
|
||||
|
||||
.resets = sun8i_a83t_de2_resets,
|
||||
.num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets),
|
||||
};
|
||||
|
||||
static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
|
||||
.ccu_clks = sun8i_h3_de2_clks,
|
||||
.num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks),
|
||||
|
||||
.hw_clks = &sun8i_h3_de2_hw_clks,
|
||||
|
||||
.resets = sun50i_a64_de2_resets,
|
||||
.num_resets = ARRAY_SIZE(sun50i_a64_de2_resets),
|
||||
|
@ -237,6 +280,10 @@ static const struct of_device_id sunxi_de2_clk_ids[] = {
|
|||
.compatible = "allwinner,sun8i-a83t-de2-clk",
|
||||
.data = &sun8i_a83t_de2_clk_desc,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun8i-h3-de2-clk",
|
||||
.data = &sun8i_h3_de2_clk_desc,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun8i-v3s-de2-clk",
|
||||
.data = &sun8i_v3s_de2_clk_desc,
|
||||
|
|
|
@ -50,12 +50,19 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
|
|||
unsigned int max_m, max_p;
|
||||
unsigned int m, p;
|
||||
|
||||
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate *= cmp->fixed_post_div;
|
||||
|
||||
max_m = cmp->m.max ?: 1 << cmp->m.width;
|
||||
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
|
||||
|
||||
ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
|
||||
rate = *parent_rate / p / m;
|
||||
|
||||
return *parent_rate / p / m;
|
||||
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate /= cmp->fixed_post_div;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static void ccu_mp_disable(struct clk_hw *hw)
|
||||
|
@ -83,6 +90,7 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
|
|||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_mp *cmp = hw_to_ccu_mp(hw);
|
||||
unsigned long rate;
|
||||
unsigned int m, p;
|
||||
u32 reg;
|
||||
|
||||
|
@ -101,7 +109,11 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
|
|||
p = reg >> cmp->p.shift;
|
||||
p &= (1 << cmp->p.width) - 1;
|
||||
|
||||
return (parent_rate >> p) / m;
|
||||
rate = (parent_rate >> p) / m;
|
||||
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate /= cmp->fixed_post_div;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int ccu_mp_determine_rate(struct clk_hw *hw,
|
||||
|
@ -129,6 +141,10 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
max_m = cmp->m.max ?: 1 << cmp->m.width;
|
||||
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
|
||||
|
||||
/* Adjust target rate according to post-dividers */
|
||||
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate = rate * cmp->fixed_post_div;
|
||||
|
||||
ccu_mp_find_best(parent_rate, rate, max_m, max_p, &m, &p);
|
||||
|
||||
spin_lock_irqsave(cmp->common.lock, flags);
|
||||
|
|
|
@ -33,9 +33,33 @@ struct ccu_mp {
|
|||
struct ccu_div_internal m;
|
||||
struct ccu_div_internal p;
|
||||
struct ccu_mux_internal mux;
|
||||
|
||||
unsigned int fixed_post_div;
|
||||
|
||||
struct ccu_common common;
|
||||
};
|
||||
|
||||
#define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \
|
||||
_mshift, _mwidth, \
|
||||
_pshift, _pwidth, \
|
||||
_muxshift, _muxwidth, \
|
||||
_gate, _postdiv, _flags) \
|
||||
struct ccu_mp _struct = { \
|
||||
.enable = _gate, \
|
||||
.m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
|
||||
.p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
|
||||
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
|
||||
.fixed_post_div = _postdiv, \
|
||||
.common = { \
|
||||
.reg = _reg, \
|
||||
.features = CCU_FEATURE_FIXED_POSTDIV, \
|
||||
.hw.init = CLK_HW_INIT_PARENTS(_name, \
|
||||
_parents, \
|
||||
&ccu_mp_ops, \
|
||||
_flags), \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
|
||||
_mshift, _mwidth, \
|
||||
_pshift, _pwidth, \
|
||||
|
|
|
@ -70,11 +70,18 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw,
|
|||
unsigned long parent_rate)
|
||||
{
|
||||
struct ccu_nm *nm = hw_to_ccu_nm(hw);
|
||||
unsigned long rate;
|
||||
unsigned long n, m;
|
||||
u32 reg;
|
||||
|
||||
if (ccu_frac_helper_is_enabled(&nm->common, &nm->frac))
|
||||
return ccu_frac_helper_read_rate(&nm->common, &nm->frac);
|
||||
if (ccu_frac_helper_is_enabled(&nm->common, &nm->frac)) {
|
||||
rate = ccu_frac_helper_read_rate(&nm->common, &nm->frac);
|
||||
|
||||
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate /= nm->fixed_post_div;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
reg = readl(nm->common.base + nm->common.reg);
|
||||
|
||||
|
@ -90,15 +97,15 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw,
|
|||
if (!m)
|
||||
m++;
|
||||
|
||||
if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm)) {
|
||||
unsigned long rate =
|
||||
ccu_sdm_helper_read_rate(&nm->common, &nm->sdm,
|
||||
m, n);
|
||||
if (rate)
|
||||
return rate;
|
||||
}
|
||||
if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm))
|
||||
rate = ccu_sdm_helper_read_rate(&nm->common, &nm->sdm, m, n);
|
||||
else
|
||||
rate = parent_rate * n / m;
|
||||
|
||||
return parent_rate * n / m;
|
||||
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate /= nm->fixed_post_div;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
@ -107,11 +114,20 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||
struct ccu_nm *nm = hw_to_ccu_nm(hw);
|
||||
struct _ccu_nm _nm;
|
||||
|
||||
if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
|
||||
return rate;
|
||||
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate *= nm->fixed_post_div;
|
||||
|
||||
if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate))
|
||||
if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
|
||||
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate /= nm->fixed_post_div;
|
||||
return rate;
|
||||
}
|
||||
|
||||
if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) {
|
||||
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate /= nm->fixed_post_div;
|
||||
return rate;
|
||||
}
|
||||
|
||||
_nm.min_n = nm->n.min ?: 1;
|
||||
_nm.max_n = nm->n.max ?: 1 << nm->n.width;
|
||||
|
@ -119,8 +135,12 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||
_nm.max_m = nm->m.max ?: 1 << nm->m.width;
|
||||
|
||||
ccu_nm_find_best(*parent_rate, rate, &_nm);
|
||||
rate = *parent_rate * _nm.n / _nm.m;
|
||||
|
||||
return *parent_rate * _nm.n / _nm.m;
|
||||
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate /= nm->fixed_post_div;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
@ -131,6 +151,10 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
/* Adjust target rate according to post-dividers */
|
||||
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
rate = rate * nm->fixed_post_div;
|
||||
|
||||
if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
|
||||
spin_lock_irqsave(nm->common.lock, flags);
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ struct ccu_nm {
|
|||
struct ccu_frac_internal frac;
|
||||
struct ccu_sdm_internal sdm;
|
||||
|
||||
unsigned int fixed_post_div;
|
||||
|
||||
struct ccu_common common;
|
||||
};
|
||||
|
||||
|
|
|
@ -98,10 +98,7 @@ static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(reg);
|
||||
|
||||
clk = sun8i_a23_apb0_register(np, reg);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
||||
|
||||
#ifndef DT_BINDINGS_ASPEED_CLOCK_H
|
||||
#define DT_BINDINGS_ASPEED_CLOCK_H
|
||||
|
||||
#define ASPEED_CLK_GATE_ECLK 0
|
||||
#define ASPEED_CLK_GATE_GCLK 1
|
||||
#define ASPEED_CLK_GATE_MCLK 2
|
||||
#define ASPEED_CLK_GATE_VCLK 3
|
||||
#define ASPEED_CLK_GATE_BCLK 4
|
||||
#define ASPEED_CLK_GATE_DCLK 5
|
||||
#define ASPEED_CLK_GATE_REFCLK 6
|
||||
#define ASPEED_CLK_GATE_USBPORT2CLK 7
|
||||
#define ASPEED_CLK_GATE_LCLK 8
|
||||
#define ASPEED_CLK_GATE_USBUHCICLK 9
|
||||
#define ASPEED_CLK_GATE_D1CLK 10
|
||||
#define ASPEED_CLK_GATE_YCLK 11
|
||||
#define ASPEED_CLK_GATE_USBPORT1CLK 12
|
||||
#define ASPEED_CLK_GATE_UART1CLK 13
|
||||
#define ASPEED_CLK_GATE_UART2CLK 14
|
||||
#define ASPEED_CLK_GATE_UART5CLK 15
|
||||
#define ASPEED_CLK_GATE_ESPICLK 16
|
||||
#define ASPEED_CLK_GATE_MAC1CLK 17
|
||||
#define ASPEED_CLK_GATE_MAC2CLK 18
|
||||
#define ASPEED_CLK_GATE_RSACLK 19
|
||||
#define ASPEED_CLK_GATE_UART3CLK 20
|
||||
#define ASPEED_CLK_GATE_UART4CLK 21
|
||||
#define ASPEED_CLK_GATE_SDCLKCLK 22
|
||||
#define ASPEED_CLK_GATE_LHCCLK 23
|
||||
#define ASPEED_CLK_HPLL 24
|
||||
#define ASPEED_CLK_AHB 25
|
||||
#define ASPEED_CLK_APB 26
|
||||
#define ASPEED_CLK_UART 27
|
||||
#define ASPEED_CLK_SDIO 28
|
||||
#define ASPEED_CLK_ECLK 29
|
||||
#define ASPEED_CLK_ECLK_MUX 30
|
||||
#define ASPEED_CLK_LHCLK 31
|
||||
#define ASPEED_CLK_MAC 32
|
||||
#define ASPEED_CLK_BCLK 33
|
||||
#define ASPEED_CLK_MPLL 34
|
||||
|
||||
#define ASPEED_RESET_XDMA 0
|
||||
#define ASPEED_RESET_MCTP 1
|
||||
#define ASPEED_RESET_ADC 2
|
||||
#define ASPEED_RESET_JTAG_MASTER 3
|
||||
#define ASPEED_RESET_MIC 4
|
||||
#define ASPEED_RESET_PWM 5
|
||||
#define ASPEED_RESET_PCIVGA 6
|
||||
#define ASPEED_RESET_I2C 7
|
||||
#define ASPEED_RESET_AHB 8
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue