u-boot/drivers/clk/imx/clk-gate-93.c
Tom Rini d678a59d2d Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay
Ethernet"' I failed to notice that b4 noticed it was based on next and
so took that as the base commit and merged that part of next to master.

This reverts commit c8ffd1356d, reversing
changes made to 2ee6f3a5f7.

Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Tom Rini <trini@konsulko.com>
2024-05-19 08:16:36 -06:00

149 lines
3.1 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2022 NXP
*
* Peng Fan <peng.fan@nxp.com>
*/
#include <common.h>
#include <asm/io.h>
#include <malloc.h>
#include <clk-uclass.h>
#include <dm/device.h>
#include <dm/devres.h>
#include <linux/bug.h>
#include <linux/clk-provider.h>
#include <clk.h>
#include "clk.h"
#include <linux/err.h>
#define UBOOT_DM_CLK_IMX_GATE93 "imx_clk_gate93"
#define DIRECT_OFFSET 0x0
/*
* 0b000 - LPCG will be OFF in any CPU mode.
* 0b100 - LPCG will be ON in any CPU mode.
*/
#define LPM_SETTING_OFF 0x0
#define LPM_SETTING_ON 0x4
#define LPM_CUR_OFFSET 0x1c
#define AUTHEN_OFFSET 0x30
#define CPULPM_EN BIT(2)
#define TZ_NS_SHIFT 9
#define TZ_NS_MASK BIT(9)
#define WHITE_LIST_SHIFT 16
struct imx93_clk_gate {
struct clk clk;
void __iomem *reg;
u32 bit_idx;
u32 val;
u32 mask;
unsigned int *share_count;
};
#define to_imx93_clk_gate(_clk) container_of(_clk, struct imx93_clk_gate, clk)
static void imx93_clk_gate_do_hardware(struct clk *clk, bool enable)
{
struct imx93_clk_gate *gate = to_imx93_clk_gate(clk);
u32 val;
val = readl(gate->reg + AUTHEN_OFFSET);
if (val & CPULPM_EN) {
val = enable ? LPM_SETTING_ON : LPM_SETTING_OFF;
writel(val, gate->reg + LPM_CUR_OFFSET);
} else {
val = readl(gate->reg + DIRECT_OFFSET);
val &= ~(gate->mask << gate->bit_idx);
if (enable)
val |= (gate->val & gate->mask) << gate->bit_idx;
writel(val, gate->reg + DIRECT_OFFSET);
}
}
static int imx93_clk_gate_enable(struct clk *clk)
{
struct imx93_clk_gate *gate = to_imx93_clk_gate(clk);
if (gate->share_count && (*gate->share_count)++ > 0)
return 0;
imx93_clk_gate_do_hardware(clk, true);
return 0;
}
static int imx93_clk_gate_disable(struct clk *clk)
{
struct imx93_clk_gate *gate = to_imx93_clk_gate(clk);
if (gate->share_count) {
if (WARN_ON(*gate->share_count == 0))
return 0;
else if (--(*gate->share_count) > 0)
return 0;
}
imx93_clk_gate_do_hardware(clk, false);
return 0;
}
static ulong imx93_clk_set_rate(struct clk *clk, ulong rate)
{
struct clk *parent = clk_get_parent(clk);
if (parent)
return clk_set_rate(parent, rate);
return -ENODEV;
}
static const struct clk_ops imx93_clk_gate_ops = {
.enable = imx93_clk_gate_enable,
.disable = imx93_clk_gate_disable,
.get_rate = clk_generic_get_rate,
.set_rate = imx93_clk_set_rate,
};
struct clk *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name,
unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val,
u32 mask, u32 domain_id, unsigned int *share_count)
{
struct imx93_clk_gate *gate;
struct clk *clk;
int ret;
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
gate->reg = reg;
gate->bit_idx = bit_idx;
gate->val = val;
gate->mask = mask;
gate->share_count = share_count;
clk = &gate->clk;
ret = clk_register(clk, UBOOT_DM_CLK_IMX_GATE93, name, parent_name);
if (ret) {
kfree(gate);
return ERR_PTR(ret);
}
return clk;
}
U_BOOT_DRIVER(clk_gate93) = {
.name = UBOOT_DM_CLK_IMX_GATE93,
.id = UCLASS_CLK,
.ops = &imx93_clk_gate_ops,
.flags = DM_FLAG_PRE_RELOC,
};