u-boot/drivers/clk/imx/clk-pfd.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

115 lines
2.4 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019 DENX Software Engineering
* Lukasz Majewski, DENX Software Engineering, lukma@denx.de
*
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <common.h>
#include <asm/io.h>
#include <malloc.h>
#include <clk-uclass.h>
#include <dm/device.h>
#include <dm/devres.h>
#include <linux/clk-provider.h>
#include <div64.h>
#include <clk.h>
#include "clk.h"
#include <linux/err.h>
#define UBOOT_DM_CLK_IMX_PFD "imx_clk_pfd"
struct clk_pfd {
struct clk clk;
void __iomem *reg;
u8 idx;
};
#define to_clk_pfd(_clk) container_of(_clk, struct clk_pfd, clk)
#define SET 0x4
#define CLR 0x8
#define OTG 0xc
static unsigned long clk_pfd_recalc_rate(struct clk *clk)
{
struct clk_pfd *pfd =
to_clk_pfd(dev_get_clk_ptr(clk->dev));
unsigned long parent_rate = clk_get_parent_rate(clk);
u64 tmp = parent_rate;
u8 frac = (readl(pfd->reg) >> (pfd->idx * 8)) & 0x3f;
tmp *= 18;
do_div(tmp, frac);
return tmp;
}
static unsigned long clk_pfd_set_rate(struct clk *clk, unsigned long rate)
{
struct clk_pfd *pfd = to_clk_pfd(clk);
unsigned long parent_rate = clk_get_parent_rate(clk);
u64 tmp = parent_rate;
u8 frac;
tmp = tmp * 18 + rate / 2;
do_div(tmp, rate);
frac = tmp;
if (frac < 12)
frac = 12;
else if (frac > 35)
frac = 35;
writel(0x3f << (pfd->idx * 8), pfd->reg + CLR);
writel(frac << (pfd->idx * 8), pfd->reg + SET);
return 0;
}
static const struct clk_ops clk_pfd_ops = {
.get_rate = clk_pfd_recalc_rate,
.set_rate = clk_pfd_set_rate,
};
struct clk *imx_clk_pfd(const char *name, const char *parent_name,
void __iomem *reg, u8 idx)
{
struct clk_pfd *pfd;
struct clk *clk;
int ret;
pfd = kzalloc(sizeof(*pfd), GFP_KERNEL);
if (!pfd)
return ERR_PTR(-ENOMEM);
pfd->reg = reg;
pfd->idx = idx;
/* register the clock */
clk = &pfd->clk;
ret = clk_register(clk, UBOOT_DM_CLK_IMX_PFD, name, parent_name);
if (ret) {
kfree(pfd);
return ERR_PTR(ret);
}
return clk;
}
U_BOOT_DRIVER(clk_pfd) = {
.name = UBOOT_DM_CLK_IMX_PFD,
.id = UCLASS_CLK,
.ops = &clk_pfd_ops,
.flags = DM_FLAG_PRE_RELOC,
};