1085 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * Copyright (c) 2014 MundoReader S.L.4 * Author: Heiko Stuebner <heiko@sntech.de>5 *6 * Copyright (c) 2015 Rockchip Electronics Co. Ltd.7 * Author: Xing Zheng <zhengxing@rock-chips.com>8 *9 * based on10 *11 * samsung/clk.h12 * Copyright (c) 2013 Samsung Electronics Co., Ltd.13 * Copyright (c) 2013 Linaro Ltd.14 * Author: Thomas Abraham <thomas.ab@samsung.com>15 */16 17#ifndef CLK_ROCKCHIP_CLK_H18#define CLK_ROCKCHIP_CLK_H19 20#include <linux/io.h>21#include <linux/clk-provider.h>22 23struct clk;24 25#define HIWORD_UPDATE(val, mask, shift) \26 ((val) << (shift) | (mask) << ((shift) + 16))27 28/* register positions shared by PX30, RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */29#define BOOST_PLL_H_CON(x) ((x) * 0x4)30#define BOOST_CLK_CON 0x000831#define BOOST_BOOST_CON 0x000c32#define BOOST_SWITCH_CNT 0x001033#define BOOST_HIGH_PERF_CNT0 0x001434#define BOOST_HIGH_PERF_CNT1 0x001835#define BOOST_STATIS_THRESHOLD 0x001c36#define BOOST_SHORT_SWITCH_CNT 0x002037#define BOOST_SWITCH_THRESHOLD 0x002438#define BOOST_FSM_STATUS 0x002839#define BOOST_PLL_L_CON(x) ((x) * 0x4 + 0x2c)40#define BOOST_RECOVERY_MASK 0x141#define BOOST_RECOVERY_SHIFT 142#define BOOST_SW_CTRL_MASK 0x143#define BOOST_SW_CTRL_SHIFT 244#define BOOST_LOW_FREQ_EN_MASK 0x145#define BOOST_LOW_FREQ_EN_SHIFT 346#define BOOST_BUSY_STATE BIT(8)47 48#define PX30_PLL_CON(x) ((x) * 0x4)49#define PX30_CLKSEL_CON(x) ((x) * 0x4 + 0x100)50#define PX30_CLKGATE_CON(x) ((x) * 0x4 + 0x200)51#define PX30_GLB_SRST_FST 0xb852#define PX30_GLB_SRST_SND 0xbc53#define PX30_SOFTRST_CON(x) ((x) * 0x4 + 0x300)54#define PX30_MODE_CON 0xa055#define PX30_MISC_CON 0xa456#define PX30_SDMMC_CON0 0x38057#define PX30_SDMMC_CON1 0x38458#define PX30_SDIO_CON0 0x38859#define PX30_SDIO_CON1 0x38c60#define PX30_EMMC_CON0 0x39061#define PX30_EMMC_CON1 0x39462 63#define PX30_PMU_PLL_CON(x) ((x) * 0x4)64#define PX30_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x40)65#define PX30_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x80)66#define PX30_PMU_MODE 0x002067 68#define RV1108_PLL_CON(x) ((x) * 0x4)69#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)70#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)71#define RV1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)72#define RV1108_GLB_SRST_FST 0x1c073#define RV1108_GLB_SRST_SND 0x1c474#define RV1108_MISC_CON 0x1cc75#define RV1108_SDMMC_CON0 0x1d876#define RV1108_SDMMC_CON1 0x1dc77#define RV1108_SDIO_CON0 0x1e078#define RV1108_SDIO_CON1 0x1e479#define RV1108_EMMC_CON0 0x1e880#define RV1108_EMMC_CON1 0x1ec81 82#define RV1126_PMU_MODE 0x083#define RV1126_PMU_PLL_CON(x) ((x) * 0x4 + 0x10)84#define RV1126_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x100)85#define RV1126_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x180)86#define RV1126_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x200)87#define RV1126_PLL_CON(x) ((x) * 0x4)88#define RV1126_MODE_CON 0x9089#define RV1126_CLKSEL_CON(x) ((x) * 0x4 + 0x100)90#define RV1126_CLKGATE_CON(x) ((x) * 0x4 + 0x280)91#define RV1126_SOFTRST_CON(x) ((x) * 0x4 + 0x300)92#define RV1126_GLB_SRST_FST 0x40893#define RV1126_GLB_SRST_SND 0x40c94#define RV1126_SDMMC_CON0 0x44095#define RV1126_SDMMC_CON1 0x44496#define RV1126_SDIO_CON0 0x44897#define RV1126_SDIO_CON1 0x44c98#define RV1126_EMMC_CON0 0x45099#define RV1126_EMMC_CON1 0x454100 101#define RK2928_PLL_CON(x) ((x) * 0x4)102#define RK2928_MODE_CON 0x40103#define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44)104#define RK2928_CLKGATE_CON(x) ((x) * 0x4 + 0xd0)105#define RK2928_GLB_SRST_FST 0x100106#define RK2928_GLB_SRST_SND 0x104107#define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110)108#define RK2928_MISC_CON 0x134109 110#define RK3036_SDMMC_CON0 0x144111#define RK3036_SDMMC_CON1 0x148112#define RK3036_SDIO_CON0 0x14c113#define RK3036_SDIO_CON1 0x150114#define RK3036_EMMC_CON0 0x154115#define RK3036_EMMC_CON1 0x158116 117#define RK3228_GLB_SRST_FST 0x1f0118#define RK3228_GLB_SRST_SND 0x1f4119#define RK3228_SDMMC_CON0 0x1c0120#define RK3228_SDMMC_CON1 0x1c4121#define RK3228_SDIO_CON0 0x1c8122#define RK3228_SDIO_CON1 0x1cc123#define RK3228_EMMC_CON0 0x1d8124#define RK3228_EMMC_CON1 0x1dc125 126#define RK3288_PLL_CON(x) RK2928_PLL_CON(x)127#define RK3288_MODE_CON 0x50128#define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60)129#define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160)130#define RK3288_GLB_SRST_FST 0x1b0131#define RK3288_GLB_SRST_SND 0x1b4132#define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8)133#define RK3288_MISC_CON 0x1e8134#define RK3288_SDMMC_CON0 0x200135#define RK3288_SDMMC_CON1 0x204136#define RK3288_SDIO0_CON0 0x208137#define RK3288_SDIO0_CON1 0x20c138#define RK3288_SDIO1_CON0 0x210139#define RK3288_SDIO1_CON1 0x214140#define RK3288_EMMC_CON0 0x218141#define RK3288_EMMC_CON1 0x21c142 143#define RK3308_PLL_CON(x) RK2928_PLL_CON(x)144#define RK3308_CLKSEL_CON(x) ((x) * 0x4 + 0x100)145#define RK3308_CLKGATE_CON(x) ((x) * 0x4 + 0x300)146#define RK3308_GLB_SRST_FST 0xb8147#define RK3308_SOFTRST_CON(x) ((x) * 0x4 + 0x400)148#define RK3308_MODE_CON 0xa0149#define RK3308_SDMMC_CON0 0x480150#define RK3308_SDMMC_CON1 0x484151#define RK3308_SDIO_CON0 0x488152#define RK3308_SDIO_CON1 0x48c153#define RK3308_EMMC_CON0 0x490154#define RK3308_EMMC_CON1 0x494155 156#define RK3328_PLL_CON(x) RK2928_PLL_CON(x)157#define RK3328_CLKSEL_CON(x) ((x) * 0x4 + 0x100)158#define RK3328_CLKGATE_CON(x) ((x) * 0x4 + 0x200)159#define RK3328_GRFCLKSEL_CON(x) ((x) * 0x4 + 0x100)160#define RK3328_GLB_SRST_FST 0x9c161#define RK3328_GLB_SRST_SND 0x98162#define RK3328_SOFTRST_CON(x) ((x) * 0x4 + 0x300)163#define RK3328_MODE_CON 0x80164#define RK3328_MISC_CON 0x84165#define RK3328_SDMMC_CON0 0x380166#define RK3328_SDMMC_CON1 0x384167#define RK3328_SDIO_CON0 0x388168#define RK3328_SDIO_CON1 0x38c169#define RK3328_EMMC_CON0 0x390170#define RK3328_EMMC_CON1 0x394171#define RK3328_SDMMC_EXT_CON0 0x398172#define RK3328_SDMMC_EXT_CON1 0x39C173 174#define RK3368_PLL_CON(x) RK2928_PLL_CON(x)175#define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100)176#define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200)177#define RK3368_GLB_SRST_FST 0x280178#define RK3368_GLB_SRST_SND 0x284179#define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300)180#define RK3368_MISC_CON 0x380181#define RK3368_SDMMC_CON0 0x400182#define RK3368_SDMMC_CON1 0x404183#define RK3368_SDIO0_CON0 0x408184#define RK3368_SDIO0_CON1 0x40c185#define RK3368_SDIO1_CON0 0x410186#define RK3368_SDIO1_CON1 0x414187#define RK3368_EMMC_CON0 0x418188#define RK3368_EMMC_CON1 0x41c189 190#define RK3399_PLL_CON(x) RK2928_PLL_CON(x)191#define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100)192#define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300)193#define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400)194#define RK3399_GLB_SRST_FST 0x500195#define RK3399_GLB_SRST_SND 0x504196#define RK3399_GLB_CNT_TH 0x508197#define RK3399_MISC_CON 0x50c198#define RK3399_RST_CON 0x510199#define RK3399_RST_ST 0x514200#define RK3399_SDMMC_CON0 0x580201#define RK3399_SDMMC_CON1 0x584202#define RK3399_SDIO_CON0 0x588203#define RK3399_SDIO_CON1 0x58c204 205#define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x)206#define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80)207#define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100)208#define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110)209 210#define RK3568_PLL_CON(x) RK2928_PLL_CON(x)211#define RK3568_MODE_CON0 0xc0212#define RK3568_MISC_CON0 0xc4213#define RK3568_MISC_CON1 0xc8214#define RK3568_MISC_CON2 0xcc215#define RK3568_GLB_CNT_TH 0xd0216#define RK3568_GLB_SRST_FST 0xd4217#define RK3568_GLB_SRST_SND 0xd8218#define RK3568_GLB_RST_CON 0xdc219#define RK3568_GLB_RST_ST 0xe0220#define RK3568_CLKSEL_CON(x) ((x) * 0x4 + 0x100)221#define RK3568_CLKGATE_CON(x) ((x) * 0x4 + 0x300)222#define RK3568_SOFTRST_CON(x) ((x) * 0x4 + 0x400)223#define RK3568_SDMMC0_CON0 0x580224#define RK3568_SDMMC0_CON1 0x584225#define RK3568_SDMMC1_CON0 0x588226#define RK3568_SDMMC1_CON1 0x58c227#define RK3568_SDMMC2_CON0 0x590228#define RK3568_SDMMC2_CON1 0x594229#define RK3568_EMMC_CON0 0x598230#define RK3568_EMMC_CON1 0x59c231 232#define RK3568_PMU_PLL_CON(x) RK2928_PLL_CON(x)233#define RK3568_PMU_MODE_CON0 0x80234#define RK3568_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x100)235#define RK3568_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x180)236#define RK3568_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x200)237 238#define RK3576_PHP_CRU_BASE 0x8000239#define RK3576_SECURE_NS_CRU_BASE 0x10000240#define RK3576_PMU_CRU_BASE 0x20000241#define RK3576_BIGCORE_CRU_BASE 0x38000242#define RK3576_LITCORE_CRU_BASE 0x40000243#define RK3576_CCI_CRU_BASE 0x48000244 245#define RK3576_PLL_CON(x) RK2928_PLL_CON(x)246#define RK3576_MODE_CON0 0x280247#define RK3576_BPLL_MODE_CON0 (RK3576_BIGCORE_CRU_BASE + 0x280)248#define RK3576_LPLL_MODE_CON0 (RK3576_LITCORE_CRU_BASE + 0x280)249#define RK3576_PPLL_MODE_CON0 (RK3576_PHP_CRU_BASE + 0x280)250#define RK3576_CLKSEL_CON(x) ((x) * 0x4 + 0x300)251#define RK3576_CLKGATE_CON(x) ((x) * 0x4 + 0x800)252#define RK3576_SOFTRST_CON(x) ((x) * 0x4 + 0xa00)253#define RK3576_GLB_CNT_TH 0xc00254#define RK3576_GLB_SRST_FST 0xc08255#define RK3576_GLB_SRST_SND 0xc0c256#define RK3576_GLB_RST_CON 0xc10257#define RK3576_GLB_RST_ST 0xc04258#define RK3576_SDIO_CON0 0xC24259#define RK3576_SDIO_CON1 0xC28260#define RK3576_SDMMC_CON0 0xC30261#define RK3576_SDMMC_CON1 0xC34262 263#define RK3576_PHP_CLKSEL_CON(x) ((x) * 0x4 + RK3576_PHP_CRU_BASE + 0x300)264#define RK3576_PHP_CLKGATE_CON(x) ((x) * 0x4 + RK3576_PHP_CRU_BASE + 0x800)265#define RK3576_PHP_SOFTRST_CON(x) ((x) * 0x4 + RK3576_PHP_CRU_BASE + 0xa00)266 267#define RK3576_PMU_PLL_CON(x) ((x) * 0x4 + RK3576_PHP_CRU_BASE)268#define RK3576_PMU_CLKSEL_CON(x) ((x) * 0x4 + RK3576_PMU_CRU_BASE + 0x300)269#define RK3576_PMU_CLKGATE_CON(x) ((x) * 0x4 + RK3576_PMU_CRU_BASE + 0x800)270#define RK3576_PMU_SOFTRST_CON(x) ((x) * 0x4 + RK3576_PMU_CRU_BASE + 0xa00)271 272#define RK3576_SECURE_NS_CLKSEL_CON(x) ((x) * 0x4 + RK3576_SECURE_NS_CRU_BASE + 0x300)273#define RK3576_SECURE_NS_CLKGATE_CON(x) ((x) * 0x4 + RK3576_SECURE_NS_CRU_BASE + 0x800)274#define RK3576_SECURE_NS_SOFTRST_CON(x) ((x) * 0x4 + RK3576_SECURE_NS_CRU_BASE + 0xa00)275 276#define RK3576_CCI_CLKSEL_CON(x) ((x) * 0x4 + RK3576_CCI_CRU_BASE + 0x300)277#define RK3576_CCI_CLKGATE_CON(x) ((x) * 0x4 + RK3576_CCI_CRU_BASE + 0x800)278#define RK3576_CCI_SOFTRST_CON(x) ((x) * 0x4 + RK3576_CCI_CRU_BASE + 0xa00)279 280#define RK3576_BPLL_CON(x) ((x) * 0x4 + RK3576_BIGCORE_CRU_BASE)281#define RK3576_BIGCORE_CLKSEL_CON(x) ((x) * 0x4 + RK3576_BIGCORE_CRU_BASE + 0x300)282#define RK3576_BIGCORE_CLKGATE_CON(x) ((x) * 0x4 + RK3576_BIGCORE_CRU_BASE + 0x800)283#define RK3576_BIGCORE_SOFTRST_CON(x) ((x) * 0x4 + RK3576_BIGCORE_CRU_BASE + 0xa00)284#define RK3576_LPLL_CON(x) ((x) * 0x4 + RK3576_CCI_CRU_BASE)285#define RK3576_LITCORE_CLKSEL_CON(x) ((x) * 0x4 + RK3576_LITCORE_CRU_BASE + 0x300)286#define RK3576_LITCORE_CLKGATE_CON(x) ((x) * 0x4 + RK3576_LITCORE_CRU_BASE + 0x800)287#define RK3576_LITCORE_SOFTRST_CON(x) ((x) * 0x4 + RK3576_LITCORE_CRU_BASE + 0xa00)288#define RK3576_NON_SECURE_GATING_CON00 0xc48289 290#define RK3588_PHP_CRU_BASE 0x8000291#define RK3588_PMU_CRU_BASE 0x30000292#define RK3588_BIGCORE0_CRU_BASE 0x50000293#define RK3588_BIGCORE1_CRU_BASE 0x52000294#define RK3588_DSU_CRU_BASE 0x58000295 296#define RK3588_PLL_CON(x) RK2928_PLL_CON(x)297#define RK3588_MODE_CON0 0x280298#define RK3588_B0_PLL_MODE_CON0 (RK3588_BIGCORE0_CRU_BASE + 0x280)299#define RK3588_B1_PLL_MODE_CON0 (RK3588_BIGCORE1_CRU_BASE + 0x280)300#define RK3588_LPLL_MODE_CON0 (RK3588_DSU_CRU_BASE + 0x280)301#define RK3588_CLKSEL_CON(x) ((x) * 0x4 + 0x300)302#define RK3588_CLKGATE_CON(x) ((x) * 0x4 + 0x800)303#define RK3588_SOFTRST_CON(x) ((x) * 0x4 + 0xa00)304#define RK3588_GLB_CNT_TH 0xc00305#define RK3588_GLB_SRST_FST 0xc08306#define RK3588_GLB_SRST_SND 0xc0c307#define RK3588_GLB_RST_CON 0xc10308#define RK3588_GLB_RST_ST 0xc04309#define RK3588_SDIO_CON0 0xC24310#define RK3588_SDIO_CON1 0xC28311#define RK3588_SDMMC_CON0 0xC30312#define RK3588_SDMMC_CON1 0xC34313 314#define RK3588_PHP_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0x800)315#define RK3588_PHP_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0xa00)316 317#define RK3588_PMU_PLL_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE)318#define RK3588_PMU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x300)319#define RK3588_PMU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x800)320#define RK3588_PMU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0xa00)321 322#define RK3588_B0_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE)323#define RK3588_BIGCORE0_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x300)324#define RK3588_BIGCORE0_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x800)325#define RK3588_BIGCORE0_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0xa00)326#define RK3588_B1_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE)327#define RK3588_BIGCORE1_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x300)328#define RK3588_BIGCORE1_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x800)329#define RK3588_BIGCORE1_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0xa00)330#define RK3588_LPLL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE)331#define RK3588_DSU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x300)332#define RK3588_DSU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x800)333#define RK3588_DSU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0xa00)334 335enum rockchip_pll_type {336 pll_rk3036,337 pll_rk3066,338 pll_rk3328,339 pll_rk3399,340 pll_rk3588,341 pll_rk3588_core,342 pll_rk3588_ddr,343};344 345#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \346 _postdiv2, _dsmpd, _frac) \347{ \348 .rate = _rate##U, \349 .fbdiv = _fbdiv, \350 .postdiv1 = _postdiv1, \351 .refdiv = _refdiv, \352 .postdiv2 = _postdiv2, \353 .dsmpd = _dsmpd, \354 .frac = _frac, \355}356 357#define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \358{ \359 .rate = _rate##U, \360 .nr = _nr, \361 .nf = _nf, \362 .no = _no, \363 .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \364}365 366#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \367{ \368 .rate = _rate##U, \369 .nr = _nr, \370 .nf = _nf, \371 .no = _no, \372 .nb = _nb, \373}374 375#define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \376{ \377 .rate = _rate##U, \378 .p = _p, \379 .m = _m, \380 .s = _s, \381 .k = _k, \382}383 384/**385 * struct rockchip_clk_provider - information about clock provider386 * @reg_base: virtual address for the register base.387 * @clk_data: holds clock related data like clk* and number of clocks.388 * @cru_node: device-node of the clock-provider389 * @grf: regmap of the general-register-files syscon390 * @lock: maintains exclusion between callbacks for a given clock-provider.391 */392struct rockchip_clk_provider {393 void __iomem *reg_base;394 struct clk_onecell_data clk_data;395 struct device_node *cru_node;396 struct regmap *grf;397 spinlock_t lock;398};399 400struct rockchip_pll_rate_table {401 unsigned long rate;402 union {403 struct {404 /* for RK3066 */405 unsigned int nr;406 unsigned int nf;407 unsigned int no;408 unsigned int nb;409 };410 struct {411 /* for RK3036/RK3399 */412 unsigned int fbdiv;413 unsigned int postdiv1;414 unsigned int refdiv;415 unsigned int postdiv2;416 unsigned int dsmpd;417 unsigned int frac;418 };419 struct {420 /* for RK3588 */421 unsigned int m;422 unsigned int p;423 unsigned int s;424 unsigned int k;425 };426 };427};428 429/**430 * struct rockchip_pll_clock - information about pll clock431 * @id: platform specific id of the clock.432 * @name: name of this pll clock.433 * @parent_names: name of the parent clock.434 * @num_parents: number of parents435 * @flags: optional flags for basic clock.436 * @con_offset: offset of the register for configuring the PLL.437 * @mode_offset: offset of the register for configuring the PLL-mode.438 * @mode_shift: offset inside the mode-register for the mode of this pll.439 * @lock_shift: offset inside the lock register for the lock status.440 * @type: Type of PLL to be registered.441 * @pll_flags: hardware-specific flags442 * @rate_table: Table of usable pll rates443 *444 * Flags:445 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the446 * rate_table parameters and ajust them if necessary.447 */448struct rockchip_pll_clock {449 unsigned int id;450 const char *name;451 const char *const *parent_names;452 u8 num_parents;453 unsigned long flags;454 int con_offset;455 int mode_offset;456 int mode_shift;457 int lock_shift;458 enum rockchip_pll_type type;459 u8 pll_flags;460 struct rockchip_pll_rate_table *rate_table;461};462 463#define ROCKCHIP_PLL_SYNC_RATE BIT(0)464 465#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \466 _lshift, _pflags, _rtable) \467 { \468 .id = _id, \469 .type = _type, \470 .name = _name, \471 .parent_names = _pnames, \472 .num_parents = ARRAY_SIZE(_pnames), \473 .flags = CLK_GET_RATE_NOCACHE | _flags, \474 .con_offset = _con, \475 .mode_offset = _mode, \476 .mode_shift = _mshift, \477 .lock_shift = _lshift, \478 .pll_flags = _pflags, \479 .rate_table = _rtable, \480 }481 482struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,483 enum rockchip_pll_type pll_type,484 const char *name, const char *const *parent_names,485 u8 num_parents, int con_offset, int grf_lock_offset,486 int lock_shift, int mode_offset, int mode_shift,487 struct rockchip_pll_rate_table *rate_table,488 unsigned long flags, u8 clk_pll_flags);489 490struct rockchip_cpuclk_clksel {491 int reg;492 u32 val;493};494 495#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 6496#define ROCKCHIP_CPUCLK_MAX_CORES 4497struct rockchip_cpuclk_rate_table {498 unsigned long prate;499 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];500 struct rockchip_cpuclk_clksel pre_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];501 struct rockchip_cpuclk_clksel post_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];502};503 504/**505 * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock506 * @core_reg[]: register offset of the cores setting register507 * @div_core_shift[]: cores divider offset used to divide the pll value508 * @div_core_mask[]: cores divider mask509 * @num_cores: number of cpu cores510 * @mux_core_reg: register offset of the cores select parent511 * @mux_core_alt: mux value to select alternate parent512 * @mux_core_main: mux value to select main parent of core513 * @mux_core_shift: offset of the core multiplexer514 * @mux_core_mask: core multiplexer mask515 */516struct rockchip_cpuclk_reg_data {517 int core_reg[ROCKCHIP_CPUCLK_MAX_CORES];518 u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES];519 u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES];520 int num_cores;521 int mux_core_reg;522 u8 mux_core_alt;523 u8 mux_core_main;524 u8 mux_core_shift;525 u32 mux_core_mask;526};527 528struct clk *rockchip_clk_register_cpuclk(const char *name,529 const char *const *parent_names, u8 num_parents,530 const struct rockchip_cpuclk_reg_data *reg_data,531 const struct rockchip_cpuclk_rate_table *rates,532 int nrates, void __iomem *reg_base, spinlock_t *lock);533 534struct clk *rockchip_clk_register_mmc(const char *name,535 const char *const *parent_names, u8 num_parents,536 void __iomem *reg, int shift);537 538/*539 * DDRCLK flags, including method of setting the rate540 * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate.541 */542#define ROCKCHIP_DDRCLK_SIP BIT(0)543 544struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,545 const char *const *parent_names,546 u8 num_parents, int mux_offset,547 int mux_shift, int mux_width,548 int div_shift, int div_width,549 int ddr_flags, void __iomem *reg_base,550 spinlock_t *lock);551 552#define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0)553 554struct clk *rockchip_clk_register_inverter(const char *name,555 const char *const *parent_names, u8 num_parents,556 void __iomem *reg, int shift, int flags,557 spinlock_t *lock);558 559struct clk *rockchip_clk_register_muxgrf(const char *name,560 const char *const *parent_names, u8 num_parents,561 int flags, struct regmap *grf, int reg,562 int shift, int width, int mux_flags);563 564#define PNAME(x) static const char *const x[] __initconst565 566enum rockchip_clk_branch_type {567 branch_composite,568 branch_mux,569 branch_muxgrf,570 branch_divider,571 branch_fraction_divider,572 branch_gate,573 branch_mmc,574 branch_inverter,575 branch_factor,576 branch_ddrclk,577 branch_half_divider,578};579 580struct rockchip_clk_branch {581 unsigned int id;582 enum rockchip_clk_branch_type branch_type;583 const char *name;584 const char *const *parent_names;585 u8 num_parents;586 unsigned long flags;587 int muxdiv_offset;588 u8 mux_shift;589 u8 mux_width;590 u8 mux_flags;591 u32 *mux_table;592 int div_offset;593 u8 div_shift;594 u8 div_width;595 u8 div_flags;596 struct clk_div_table *div_table;597 int gate_offset;598 u8 gate_shift;599 u8 gate_flags;600 struct rockchip_clk_branch *child;601};602 603#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\604 df, go, gs, gf) \605 { \606 .id = _id, \607 .branch_type = branch_composite, \608 .name = cname, \609 .parent_names = pnames, \610 .num_parents = ARRAY_SIZE(pnames), \611 .flags = f, \612 .muxdiv_offset = mo, \613 .mux_shift = ms, \614 .mux_width = mw, \615 .mux_flags = mf, \616 .div_shift = ds, \617 .div_width = dw, \618 .div_flags = df, \619 .gate_offset = go, \620 .gate_shift = gs, \621 .gate_flags = gf, \622 }623 624#define COMPOSITE_DIV_OFFSET(_id, cname, pnames, f, mo, ms, mw, \625 mf, do, ds, dw, df, go, gs, gf) \626 { \627 .id = _id, \628 .branch_type = branch_composite, \629 .name = cname, \630 .parent_names = pnames, \631 .num_parents = ARRAY_SIZE(pnames), \632 .flags = f, \633 .muxdiv_offset = mo, \634 .mux_shift = ms, \635 .mux_width = mw, \636 .mux_flags = mf, \637 .div_offset = do, \638 .div_shift = ds, \639 .div_width = dw, \640 .div_flags = df, \641 .gate_offset = go, \642 .gate_shift = gs, \643 .gate_flags = gf, \644 }645 646#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \647 go, gs, gf) \648 { \649 .id = _id, \650 .branch_type = branch_composite, \651 .name = cname, \652 .parent_names = (const char *[]){ pname }, \653 .num_parents = 1, \654 .flags = f, \655 .muxdiv_offset = mo, \656 .div_shift = ds, \657 .div_width = dw, \658 .div_flags = df, \659 .gate_offset = go, \660 .gate_shift = gs, \661 .gate_flags = gf, \662 }663 664#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\665 df, dt, go, gs, gf) \666 { \667 .id = _id, \668 .branch_type = branch_composite, \669 .name = cname, \670 .parent_names = (const char *[]){ pname }, \671 .num_parents = 1, \672 .flags = f, \673 .muxdiv_offset = mo, \674 .div_shift = ds, \675 .div_width = dw, \676 .div_flags = df, \677 .div_table = dt, \678 .gate_offset = go, \679 .gate_shift = gs, \680 .gate_flags = gf, \681 }682 683#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \684 go, gs, gf) \685 { \686 .id = _id, \687 .branch_type = branch_composite, \688 .name = cname, \689 .parent_names = pnames, \690 .num_parents = ARRAY_SIZE(pnames), \691 .flags = f, \692 .muxdiv_offset = mo, \693 .mux_shift = ms, \694 .mux_width = mw, \695 .mux_flags = mf, \696 .gate_offset = go, \697 .gate_shift = gs, \698 .gate_flags = gf, \699 }700 701#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \702 ds, dw, df) \703 { \704 .id = _id, \705 .branch_type = branch_composite, \706 .name = cname, \707 .parent_names = pnames, \708 .num_parents = ARRAY_SIZE(pnames), \709 .flags = f, \710 .muxdiv_offset = mo, \711 .mux_shift = ms, \712 .mux_width = mw, \713 .mux_flags = mf, \714 .div_shift = ds, \715 .div_width = dw, \716 .div_flags = df, \717 .gate_offset = -1, \718 }719 720#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \721 mw, mf, ds, dw, df, dt) \722 { \723 .id = _id, \724 .branch_type = branch_composite, \725 .name = cname, \726 .parent_names = pnames, \727 .num_parents = ARRAY_SIZE(pnames), \728 .flags = f, \729 .muxdiv_offset = mo, \730 .mux_shift = ms, \731 .mux_width = mw, \732 .mux_flags = mf, \733 .div_shift = ds, \734 .div_width = dw, \735 .div_flags = df, \736 .div_table = dt, \737 .gate_offset = -1, \738 }739 740#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\741 { \742 .id = _id, \743 .branch_type = branch_fraction_divider, \744 .name = cname, \745 .parent_names = (const char *[]){ pname }, \746 .num_parents = 1, \747 .flags = f, \748 .muxdiv_offset = mo, \749 .div_shift = 16, \750 .div_width = 16, \751 .div_flags = df, \752 .gate_offset = go, \753 .gate_shift = gs, \754 .gate_flags = gf, \755 }756 757#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \758 { \759 .id = _id, \760 .branch_type = branch_fraction_divider, \761 .name = cname, \762 .parent_names = (const char *[]){ pname }, \763 .num_parents = 1, \764 .flags = f, \765 .muxdiv_offset = mo, \766 .div_shift = 16, \767 .div_width = 16, \768 .div_flags = df, \769 .gate_offset = go, \770 .gate_shift = gs, \771 .gate_flags = gf, \772 .child = ch, \773 }774 775#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \776 { \777 .id = _id, \778 .branch_type = branch_fraction_divider, \779 .name = cname, \780 .parent_names = (const char *[]){ pname }, \781 .num_parents = 1, \782 .flags = f, \783 .muxdiv_offset = mo, \784 .div_shift = 16, \785 .div_width = 16, \786 .div_flags = df, \787 .gate_offset = -1, \788 .child = ch, \789 }790 791#define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw, \792 ds, dw, df) \793 { \794 .id = _id, \795 .branch_type = branch_ddrclk, \796 .name = cname, \797 .parent_names = pnames, \798 .num_parents = ARRAY_SIZE(pnames), \799 .flags = f, \800 .muxdiv_offset = mo, \801 .mux_shift = ms, \802 .mux_width = mw, \803 .div_shift = ds, \804 .div_width = dw, \805 .div_flags = df, \806 .gate_offset = -1, \807 }808 809#define MUX(_id, cname, pnames, f, o, s, w, mf) \810 { \811 .id = _id, \812 .branch_type = branch_mux, \813 .name = cname, \814 .parent_names = pnames, \815 .num_parents = ARRAY_SIZE(pnames), \816 .flags = f, \817 .muxdiv_offset = o, \818 .mux_shift = s, \819 .mux_width = w, \820 .mux_flags = mf, \821 .gate_offset = -1, \822 }823 824#define MUXTBL(_id, cname, pnames, f, o, s, w, mf, mt) \825 { \826 .id = _id, \827 .branch_type = branch_mux, \828 .name = cname, \829 .parent_names = pnames, \830 .num_parents = ARRAY_SIZE(pnames), \831 .flags = f, \832 .muxdiv_offset = o, \833 .mux_shift = s, \834 .mux_width = w, \835 .mux_flags = mf, \836 .gate_offset = -1, \837 .mux_table = mt, \838 }839 840#define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \841 { \842 .id = _id, \843 .branch_type = branch_muxgrf, \844 .name = cname, \845 .parent_names = pnames, \846 .num_parents = ARRAY_SIZE(pnames), \847 .flags = f, \848 .muxdiv_offset = o, \849 .mux_shift = s, \850 .mux_width = w, \851 .mux_flags = mf, \852 .gate_offset = -1, \853 }854 855#define DIV(_id, cname, pname, f, o, s, w, df) \856 { \857 .id = _id, \858 .branch_type = branch_divider, \859 .name = cname, \860 .parent_names = (const char *[]){ pname }, \861 .num_parents = 1, \862 .flags = f, \863 .muxdiv_offset = o, \864 .div_shift = s, \865 .div_width = w, \866 .div_flags = df, \867 .gate_offset = -1, \868 }869 870#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \871 { \872 .id = _id, \873 .branch_type = branch_divider, \874 .name = cname, \875 .parent_names = (const char *[]){ pname }, \876 .num_parents = 1, \877 .flags = f, \878 .muxdiv_offset = o, \879 .div_shift = s, \880 .div_width = w, \881 .div_flags = df, \882 .div_table = dt, \883 }884 885#define GATE(_id, cname, pname, f, o, b, gf) \886 { \887 .id = _id, \888 .branch_type = branch_gate, \889 .name = cname, \890 .parent_names = (const char *[]){ pname }, \891 .num_parents = 1, \892 .flags = f, \893 .gate_offset = o, \894 .gate_shift = b, \895 .gate_flags = gf, \896 }897 898#define MMC(_id, cname, pname, offset, shift) \899 { \900 .id = _id, \901 .branch_type = branch_mmc, \902 .name = cname, \903 .parent_names = (const char *[]){ pname }, \904 .num_parents = 1, \905 .muxdiv_offset = offset, \906 .div_shift = shift, \907 }908 909#define INVERTER(_id, cname, pname, io, is, if) \910 { \911 .id = _id, \912 .branch_type = branch_inverter, \913 .name = cname, \914 .parent_names = (const char *[]){ pname }, \915 .num_parents = 1, \916 .muxdiv_offset = io, \917 .div_shift = is, \918 .div_flags = if, \919 }920 921#define FACTOR(_id, cname, pname, f, fm, fd) \922 { \923 .id = _id, \924 .branch_type = branch_factor, \925 .name = cname, \926 .parent_names = (const char *[]){ pname }, \927 .num_parents = 1, \928 .flags = f, \929 .div_shift = fm, \930 .div_width = fd, \931 }932 933#define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \934 { \935 .id = _id, \936 .branch_type = branch_factor, \937 .name = cname, \938 .parent_names = (const char *[]){ pname }, \939 .num_parents = 1, \940 .flags = f, \941 .div_shift = fm, \942 .div_width = fd, \943 .gate_offset = go, \944 .gate_shift = gb, \945 .gate_flags = gf, \946 }947 948#define COMPOSITE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\949 df, go, gs, gf) \950 { \951 .id = _id, \952 .branch_type = branch_half_divider, \953 .name = cname, \954 .parent_names = pnames, \955 .num_parents = ARRAY_SIZE(pnames), \956 .flags = f, \957 .muxdiv_offset = mo, \958 .mux_shift = ms, \959 .mux_width = mw, \960 .mux_flags = mf, \961 .div_shift = ds, \962 .div_width = dw, \963 .div_flags = df, \964 .gate_offset = go, \965 .gate_shift = gs, \966 .gate_flags = gf, \967 }968 969#define COMPOSITE_NOGATE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, \970 ds, dw, df) \971 { \972 .id = _id, \973 .branch_type = branch_half_divider, \974 .name = cname, \975 .parent_names = pnames, \976 .num_parents = ARRAY_SIZE(pnames), \977 .flags = f, \978 .muxdiv_offset = mo, \979 .mux_shift = ms, \980 .mux_width = mw, \981 .mux_flags = mf, \982 .div_shift = ds, \983 .div_width = dw, \984 .div_flags = df, \985 .gate_offset = -1, \986 }987 988#define COMPOSITE_NOMUX_HALFDIV(_id, cname, pname, f, mo, ds, dw, df, \989 go, gs, gf) \990 { \991 .id = _id, \992 .branch_type = branch_half_divider, \993 .name = cname, \994 .parent_names = (const char *[]){ pname }, \995 .num_parents = 1, \996 .flags = f, \997 .muxdiv_offset = mo, \998 .div_shift = ds, \999 .div_width = dw, \1000 .div_flags = df, \1001 .gate_offset = go, \1002 .gate_shift = gs, \1003 .gate_flags = gf, \1004 }1005 1006#define DIV_HALF(_id, cname, pname, f, o, s, w, df) \1007 { \1008 .id = _id, \1009 .branch_type = branch_half_divider, \1010 .name = cname, \1011 .parent_names = (const char *[]){ pname }, \1012 .num_parents = 1, \1013 .flags = f, \1014 .muxdiv_offset = o, \1015 .div_shift = s, \1016 .div_width = w, \1017 .div_flags = df, \1018 .gate_offset = -1, \1019 }1020 1021/* SGRF clocks are only accessible from secure mode, so not controllable */1022#define SGRF_GATE(_id, cname, pname) \1023 FACTOR(_id, cname, pname, 0, 1, 1)1024 1025struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,1026 void __iomem *base, unsigned long nr_clks);1027void rockchip_clk_of_add_provider(struct device_node *np,1028 struct rockchip_clk_provider *ctx);1029unsigned long rockchip_clk_find_max_clk_id(struct rockchip_clk_branch *list,1030 unsigned int nr_clk);1031void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,1032 struct rockchip_clk_branch *list,1033 unsigned int nr_clk);1034void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,1035 struct rockchip_pll_clock *pll_list,1036 unsigned int nr_pll, int grf_lock_offset);1037void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,1038 unsigned int lookup_id, const char *name,1039 const char *const *parent_names, u8 num_parents,1040 const struct rockchip_cpuclk_reg_data *reg_data,1041 const struct rockchip_cpuclk_rate_table *rates,1042 int nrates);1043void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);1044void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,1045 unsigned int reg, void (*cb)(void));1046 1047#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)1048 1049struct clk *rockchip_clk_register_halfdiv(const char *name,1050 const char *const *parent_names,1051 u8 num_parents, void __iomem *base,1052 int muxdiv_offset, u8 mux_shift,1053 u8 mux_width, u8 mux_flags,1054 u8 div_shift, u8 div_width,1055 u8 div_flags, int gate_offset,1056 u8 gate_shift, u8 gate_flags,1057 unsigned long flags,1058 spinlock_t *lock);1059 1060#ifdef CONFIG_RESET_CONTROLLER1061void rockchip_register_softrst_lut(struct device_node *np,1062 const int *lookup_table,1063 unsigned int num_regs,1064 void __iomem *base, u8 flags);1065#else1066static inline void rockchip_register_softrst_lut(struct device_node *np,1067 const int *lookup_table,1068 unsigned int num_regs,1069 void __iomem *base, u8 flags)1070{1071}1072#endif1073 1074static inline void rockchip_register_softrst(struct device_node *np,1075 unsigned int num_regs,1076 void __iomem *base, u8 flags)1077{1078 return rockchip_register_softrst_lut(np, NULL, num_regs, base, flags);1079}1080 1081void rk3576_rst_init(struct device_node *np, void __iomem *reg_base);1082void rk3588_rst_init(struct device_node *np, void __iomem *reg_base);1083 1084#endif1085