1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2022 Nuvoton Technology Corp. 4 */ 5 6#include <dm.h> 7#include <dt-bindings/clock/nuvoton,npcm845-clk.h> 8#include "clk_npcm.h" 9 10/* Parent clock map */ 11static const struct parent_data pll_parents[] = { 12 {NPCM8XX_CLK_PLL0, 0}, 13 {NPCM8XX_CLK_PLL1, 1}, 14 {NPCM8XX_CLK_REFCLK, 2}, 15 {NPCM8XX_CLK_PLL2DIV2, 3} 16}; 17 18static const struct parent_data cpuck_parents[] = { 19 {NPCM8XX_CLK_PLL0, 0}, 20 {NPCM8XX_CLK_PLL1, 1}, 21 {NPCM8XX_CLK_REFCLK, 2}, 22 {NPCM8XX_CLK_PLL2, 7} 23}; 24 25static const struct parent_data apb_parent[] = {{NPCM8XX_CLK_AHB, 0}}; 26 27static struct npcm_clk_pll npcm8xx_clk_plls[] = { 28 {NPCM8XX_CLK_PLL0, NPCM8XX_CLK_REFCLK, PLLCON0, 0}, 29 {NPCM8XX_CLK_PLL1, NPCM8XX_CLK_REFCLK, PLLCON1, 0}, 30 {NPCM8XX_CLK_PLL2, NPCM8XX_CLK_REFCLK, PLLCON2, 0}, 31 {NPCM8XX_CLK_PLL2DIV2, NPCM8XX_CLK_REFCLK, PLLCON2, POST_DIV2} 32}; 33 34static struct npcm_clk_select npcm8xx_clk_selectors[] = { 35 {NPCM8XX_CLK_AHB, cpuck_parents, CLKSEL, NPCM8XX_CPUCKSEL, 4, 0}, 36 {NPCM8XX_CLK_APB2, apb_parent, 0, 0, 1, FIXED_PARENT}, 37 {NPCM8XX_CLK_APB5, apb_parent, 0, 0, 1, FIXED_PARENT}, 38 {NPCM8XX_CLK_SPI0, apb_parent, 0, 0, 1, FIXED_PARENT}, 39 {NPCM8XX_CLK_SPI1, apb_parent, 0, 0, 1, FIXED_PARENT}, 40 {NPCM8XX_CLK_SPI3, apb_parent, 0, 0, 1, FIXED_PARENT}, 41 {NPCM8XX_CLK_SPIX, apb_parent, 0, 0, 1, FIXED_PARENT}, 42 {NPCM8XX_CLK_UART, pll_parents, CLKSEL, UARTCKSEL, 4, 0}, 43 {NPCM8XX_CLK_UART2, pll_parents, CLKSEL, UARTCKSEL, 4, 0}, 44 {NPCM8XX_CLK_SDHC, pll_parents, CLKSEL, SDCKSEL, 4, 0} 45}; 46 47static struct npcm_clk_div npcm8xx_clk_dividers[] = { 48 {NPCM8XX_CLK_AHB, CLKDIV1, CLK4DIV, DIV_TYPE1 | PRE_DIV2 | DIV_RO}, 49 {NPCM8XX_CLK_APB2, CLKDIV2, APB2CKDIV, DIV_TYPE2 | DIV_RO}, 50 {NPCM8XX_CLK_APB5, CLKDIV2, APB5CKDIV, DIV_TYPE2 | DIV_RO}, 51 {NPCM8XX_CLK_SPI0, CLKDIV3, SPI0CKDIV, DIV_TYPE1 | DIV_RO}, 52 {NPCM8XX_CLK_SPI1, CLKDIV3, SPI1CKDIV, DIV_TYPE1 | DIV_RO}, 53 {NPCM8XX_CLK_SPI3, CLKDIV1, SPI3CKDIV, DIV_TYPE1 | DIV_RO}, 54 {NPCM8XX_CLK_SPIX, CLKDIV3, SPIXCKDIV, DIV_TYPE1}, 55 {NPCM8XX_CLK_UART, CLKDIV1, UARTDIV1, DIV_TYPE1}, 56 {NPCM8XX_CLK_UART2, CLKDIV3, UARTDIV2, DIV_TYPE1}, 57 {NPCM8XX_CLK_SDHC, CLKDIV1, MMCCKDIV, DIV_TYPE1} 58}; 59 60static struct npcm_clk_data npcm8xx_clk_data = { 61 .clk_plls = npcm8xx_clk_plls, 62 .num_plls = ARRAY_SIZE(npcm8xx_clk_plls), 63 .clk_selectors = npcm8xx_clk_selectors, 64 .num_selectors = ARRAY_SIZE(npcm8xx_clk_selectors), 65 .clk_dividers = npcm8xx_clk_dividers, 66 .num_dividers = ARRAY_SIZE(npcm8xx_clk_dividers), 67 .refclk_id = NPCM8XX_CLK_REFCLK, 68 .pll0_id = NPCM8XX_CLK_PLL0, 69}; 70 71static int npcm8xx_clk_probe(struct udevice *dev) 72{ 73 struct npcm_clk_priv *priv = dev_get_priv(dev); 74 75 priv->base = dev_read_addr_ptr(dev); 76 if (!priv->base) 77 return -EINVAL; 78 79 priv->clk_data = &npcm8xx_clk_data; 80 priv->num_clks = NPCM8XX_NUM_CLOCKS; 81 82 return 0; 83} 84 85static const struct udevice_id npcm8xx_clk_ids[] = { 86 { .compatible = "nuvoton,npcm845-clk" }, 87 { } 88}; 89 90U_BOOT_DRIVER(clk_npcm) = { 91 .name = "clk_npcm", 92 .id = UCLASS_CLK, 93 .of_match = npcm8xx_clk_ids, 94 .ops = &npcm_clk_ops, 95 .priv_auto = sizeof(struct npcm_clk_priv), 96 .probe = npcm8xx_clk_probe, 97 .flags = DM_FLAG_PRE_RELOC, 98}; 99