#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#define SOCFPGA_L4_MP_CLK "l4_mp_clk"
#define SOCFPGA_L4_SP_CLK "l4_sp_clk"
#define SOCFPGA_NAND_CLK "nand_clk"
#define SOCFPGA_NAND_X_CLK "nand_x_clk"
#define SOCFPGA_MMC_CLK "sdmmc_clk"
#define SOCFPGA_GPIO_DB_CLK_OFFSET 0xA8
#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108
static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
if (streq(hwclk->init->name, SOCFPGA_MMC_CLK))
return perpll_src &= 0x3;
if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
streq(hwclk->init->name, SOCFPGA_NAND_X_CLK))
return (perpll_src >> 2) & 3;
return (perpll_src >> 4) & 3;
static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent)
if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
} else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
src_reg |= (parent << 1);
writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) {
} else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) {
src_reg |= (parent << 2);
src_reg |= (parent << 4);
writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC);