162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2015 Vladimir Zapolskiy <vz@mleia.com> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/clk.h> 762306a36Sopenharmony_ci#include <linux/clk-provider.h> 862306a36Sopenharmony_ci#include <linux/io.h> 962306a36Sopenharmony_ci#include <linux/of_address.h> 1062306a36Sopenharmony_ci#include <linux/regmap.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <dt-bindings/clock/lpc32xx-clock.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#undef pr_fmt 1562306a36Sopenharmony_ci#define pr_fmt(fmt) "%s: " fmt, __func__ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* Common bitfield definitions for x397 PLL (lock), USB PLL and HCLK PLL */ 1862306a36Sopenharmony_ci#define PLL_CTRL_ENABLE BIT(16) 1962306a36Sopenharmony_ci#define PLL_CTRL_BYPASS BIT(15) 2062306a36Sopenharmony_ci#define PLL_CTRL_DIRECT BIT(14) 2162306a36Sopenharmony_ci#define PLL_CTRL_FEEDBACK BIT(13) 2262306a36Sopenharmony_ci#define PLL_CTRL_POSTDIV (BIT(12)|BIT(11)) 2362306a36Sopenharmony_ci#define PLL_CTRL_PREDIV (BIT(10)|BIT(9)) 2462306a36Sopenharmony_ci#define PLL_CTRL_FEEDDIV (0xFF << 1) 2562306a36Sopenharmony_ci#define PLL_CTRL_LOCK BIT(0) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* Clock registers on System Control Block */ 2862306a36Sopenharmony_ci#define LPC32XX_CLKPWR_DEBUG_CTRL 0x00 2962306a36Sopenharmony_ci#define LPC32XX_CLKPWR_USB_DIV 0x1C 3062306a36Sopenharmony_ci#define LPC32XX_CLKPWR_HCLKDIV_CTRL 0x40 3162306a36Sopenharmony_ci#define LPC32XX_CLKPWR_PWR_CTRL 0x44 3262306a36Sopenharmony_ci#define LPC32XX_CLKPWR_PLL397_CTRL 0x48 3362306a36Sopenharmony_ci#define LPC32XX_CLKPWR_OSC_CTRL 0x4C 3462306a36Sopenharmony_ci#define LPC32XX_CLKPWR_SYSCLK_CTRL 0x50 3562306a36Sopenharmony_ci#define LPC32XX_CLKPWR_LCDCLK_CTRL 0x54 3662306a36Sopenharmony_ci#define LPC32XX_CLKPWR_HCLKPLL_CTRL 0x58 3762306a36Sopenharmony_ci#define LPC32XX_CLKPWR_ADCCLK_CTRL1 0x60 3862306a36Sopenharmony_ci#define LPC32XX_CLKPWR_USB_CTRL 0x64 3962306a36Sopenharmony_ci#define LPC32XX_CLKPWR_SSP_CTRL 0x78 4062306a36Sopenharmony_ci#define LPC32XX_CLKPWR_I2S_CTRL 0x7C 4162306a36Sopenharmony_ci#define LPC32XX_CLKPWR_MS_CTRL 0x80 4262306a36Sopenharmony_ci#define LPC32XX_CLKPWR_MACCLK_CTRL 0x90 4362306a36Sopenharmony_ci#define LPC32XX_CLKPWR_TEST_CLK_CTRL 0xA4 4462306a36Sopenharmony_ci#define LPC32XX_CLKPWR_I2CCLK_CTRL 0xAC 4562306a36Sopenharmony_ci#define LPC32XX_CLKPWR_KEYCLK_CTRL 0xB0 4662306a36Sopenharmony_ci#define LPC32XX_CLKPWR_ADCCLK_CTRL 0xB4 4762306a36Sopenharmony_ci#define LPC32XX_CLKPWR_PWMCLK_CTRL 0xB8 4862306a36Sopenharmony_ci#define LPC32XX_CLKPWR_TIMCLK_CTRL 0xBC 4962306a36Sopenharmony_ci#define LPC32XX_CLKPWR_TIMCLK_CTRL1 0xC0 5062306a36Sopenharmony_ci#define LPC32XX_CLKPWR_SPI_CTRL 0xC4 5162306a36Sopenharmony_ci#define LPC32XX_CLKPWR_FLASHCLK_CTRL 0xC8 5262306a36Sopenharmony_ci#define LPC32XX_CLKPWR_UART3_CLK_CTRL 0xD0 5362306a36Sopenharmony_ci#define LPC32XX_CLKPWR_UART4_CLK_CTRL 0xD4 5462306a36Sopenharmony_ci#define LPC32XX_CLKPWR_UART5_CLK_CTRL 0xD8 5562306a36Sopenharmony_ci#define LPC32XX_CLKPWR_UART6_CLK_CTRL 0xDC 5662306a36Sopenharmony_ci#define LPC32XX_CLKPWR_IRDA_CLK_CTRL 0xE0 5762306a36Sopenharmony_ci#define LPC32XX_CLKPWR_UART_CLK_CTRL 0xE4 5862306a36Sopenharmony_ci#define LPC32XX_CLKPWR_DMA_CLK_CTRL 0xE8 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* Clock registers on USB controller */ 6162306a36Sopenharmony_ci#define LPC32XX_USB_CLK_CTRL 0xF4 6262306a36Sopenharmony_ci#define LPC32XX_USB_CLK_STS 0xF8 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic struct regmap_config lpc32xx_scb_regmap_config = { 6562306a36Sopenharmony_ci .name = "scb", 6662306a36Sopenharmony_ci .reg_bits = 32, 6762306a36Sopenharmony_ci .val_bits = 32, 6862306a36Sopenharmony_ci .reg_stride = 4, 6962306a36Sopenharmony_ci .val_format_endian = REGMAP_ENDIAN_LITTLE, 7062306a36Sopenharmony_ci .max_register = 0x114, 7162306a36Sopenharmony_ci .fast_io = true, 7262306a36Sopenharmony_ci}; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic struct regmap *clk_regmap; 7562306a36Sopenharmony_cistatic void __iomem *usb_clk_vbase; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cienum { 7862306a36Sopenharmony_ci LPC32XX_USB_CLK_OTG = LPC32XX_USB_CLK_HOST + 1, 7962306a36Sopenharmony_ci LPC32XX_USB_CLK_AHB, 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci LPC32XX_USB_CLK_MAX = LPC32XX_USB_CLK_AHB + 1, 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cienum { 8562306a36Sopenharmony_ci /* Start from the last defined clock in dt bindings */ 8662306a36Sopenharmony_ci LPC32XX_CLK_ADC_DIV = LPC32XX_CLK_PERIPH + 1, 8762306a36Sopenharmony_ci LPC32XX_CLK_ADC_RTC, 8862306a36Sopenharmony_ci LPC32XX_CLK_TEST1, 8962306a36Sopenharmony_ci LPC32XX_CLK_TEST2, 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* System clocks, PLL 397x and HCLK PLL clocks */ 9262306a36Sopenharmony_ci LPC32XX_CLK_OSC, 9362306a36Sopenharmony_ci LPC32XX_CLK_SYS, 9462306a36Sopenharmony_ci LPC32XX_CLK_PLL397X, 9562306a36Sopenharmony_ci LPC32XX_CLK_HCLK_DIV_PERIPH, 9662306a36Sopenharmony_ci LPC32XX_CLK_HCLK_DIV, 9762306a36Sopenharmony_ci LPC32XX_CLK_HCLK, 9862306a36Sopenharmony_ci LPC32XX_CLK_ARM, 9962306a36Sopenharmony_ci LPC32XX_CLK_ARM_VFP, 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* USB clocks */ 10262306a36Sopenharmony_ci LPC32XX_CLK_USB_PLL, 10362306a36Sopenharmony_ci LPC32XX_CLK_USB_DIV, 10462306a36Sopenharmony_ci LPC32XX_CLK_USB, 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci /* Only one control PWR_CTRL[10] for both muxes */ 10762306a36Sopenharmony_ci LPC32XX_CLK_PERIPH_HCLK_MUX, 10862306a36Sopenharmony_ci LPC32XX_CLK_PERIPH_ARM_MUX, 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* Only one control PWR_CTRL[2] for all three muxes */ 11162306a36Sopenharmony_ci LPC32XX_CLK_SYSCLK_PERIPH_MUX, 11262306a36Sopenharmony_ci LPC32XX_CLK_SYSCLK_HCLK_MUX, 11362306a36Sopenharmony_ci LPC32XX_CLK_SYSCLK_ARM_MUX, 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* Two clock sources external to the driver */ 11662306a36Sopenharmony_ci LPC32XX_CLK_XTAL_32K, 11762306a36Sopenharmony_ci LPC32XX_CLK_XTAL, 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* Renumbered USB clocks, may have a parent from SCB table */ 12062306a36Sopenharmony_ci LPC32XX_CLK_USB_OFFSET, 12162306a36Sopenharmony_ci LPC32XX_CLK_USB_I2C = LPC32XX_USB_CLK_I2C + LPC32XX_CLK_USB_OFFSET, 12262306a36Sopenharmony_ci LPC32XX_CLK_USB_DEV = LPC32XX_USB_CLK_DEVICE + LPC32XX_CLK_USB_OFFSET, 12362306a36Sopenharmony_ci LPC32XX_CLK_USB_HOST = LPC32XX_USB_CLK_HOST + LPC32XX_CLK_USB_OFFSET, 12462306a36Sopenharmony_ci LPC32XX_CLK_USB_OTG = LPC32XX_USB_CLK_OTG + LPC32XX_CLK_USB_OFFSET, 12562306a36Sopenharmony_ci LPC32XX_CLK_USB_AHB = LPC32XX_USB_CLK_AHB + LPC32XX_CLK_USB_OFFSET, 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* Stub for composite clocks */ 12862306a36Sopenharmony_ci LPC32XX_CLK__NULL, 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Subclocks of composite clocks, clocks above are for CCF */ 13162306a36Sopenharmony_ci LPC32XX_CLK_PWM1_MUX, 13262306a36Sopenharmony_ci LPC32XX_CLK_PWM1_DIV, 13362306a36Sopenharmony_ci LPC32XX_CLK_PWM1_GATE, 13462306a36Sopenharmony_ci LPC32XX_CLK_PWM2_MUX, 13562306a36Sopenharmony_ci LPC32XX_CLK_PWM2_DIV, 13662306a36Sopenharmony_ci LPC32XX_CLK_PWM2_GATE, 13762306a36Sopenharmony_ci LPC32XX_CLK_UART3_MUX, 13862306a36Sopenharmony_ci LPC32XX_CLK_UART3_DIV, 13962306a36Sopenharmony_ci LPC32XX_CLK_UART3_GATE, 14062306a36Sopenharmony_ci LPC32XX_CLK_UART4_MUX, 14162306a36Sopenharmony_ci LPC32XX_CLK_UART4_DIV, 14262306a36Sopenharmony_ci LPC32XX_CLK_UART4_GATE, 14362306a36Sopenharmony_ci LPC32XX_CLK_UART5_MUX, 14462306a36Sopenharmony_ci LPC32XX_CLK_UART5_DIV, 14562306a36Sopenharmony_ci LPC32XX_CLK_UART5_GATE, 14662306a36Sopenharmony_ci LPC32XX_CLK_UART6_MUX, 14762306a36Sopenharmony_ci LPC32XX_CLK_UART6_DIV, 14862306a36Sopenharmony_ci LPC32XX_CLK_UART6_GATE, 14962306a36Sopenharmony_ci LPC32XX_CLK_TEST1_MUX, 15062306a36Sopenharmony_ci LPC32XX_CLK_TEST1_GATE, 15162306a36Sopenharmony_ci LPC32XX_CLK_TEST2_MUX, 15262306a36Sopenharmony_ci LPC32XX_CLK_TEST2_GATE, 15362306a36Sopenharmony_ci LPC32XX_CLK_USB_DIV_DIV, 15462306a36Sopenharmony_ci LPC32XX_CLK_USB_DIV_GATE, 15562306a36Sopenharmony_ci LPC32XX_CLK_SD_DIV, 15662306a36Sopenharmony_ci LPC32XX_CLK_SD_GATE, 15762306a36Sopenharmony_ci LPC32XX_CLK_LCD_DIV, 15862306a36Sopenharmony_ci LPC32XX_CLK_LCD_GATE, 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci LPC32XX_CLK_HW_MAX, 16162306a36Sopenharmony_ci LPC32XX_CLK_MAX = LPC32XX_CLK_SYSCLK_ARM_MUX + 1, 16262306a36Sopenharmony_ci LPC32XX_CLK_CCF_MAX = LPC32XX_CLK_USB_AHB + 1, 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic struct clk *clk[LPC32XX_CLK_MAX]; 16662306a36Sopenharmony_cistatic struct clk_onecell_data clk_data = { 16762306a36Sopenharmony_ci .clks = clk, 16862306a36Sopenharmony_ci .clk_num = LPC32XX_CLK_MAX, 16962306a36Sopenharmony_ci}; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic struct clk *usb_clk[LPC32XX_USB_CLK_MAX]; 17262306a36Sopenharmony_cistatic struct clk_onecell_data usb_clk_data = { 17362306a36Sopenharmony_ci .clks = usb_clk, 17462306a36Sopenharmony_ci .clk_num = LPC32XX_USB_CLK_MAX, 17562306a36Sopenharmony_ci}; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci#define LPC32XX_CLK_PARENTS_MAX 5 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistruct clk_proto_t { 18062306a36Sopenharmony_ci const char *name; 18162306a36Sopenharmony_ci const u8 parents[LPC32XX_CLK_PARENTS_MAX]; 18262306a36Sopenharmony_ci u8 num_parents; 18362306a36Sopenharmony_ci unsigned long flags; 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci#define CLK_PREFIX(LITERAL) LPC32XX_CLK_ ## LITERAL 18762306a36Sopenharmony_ci#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int)) 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#define LPC32XX_CLK_DEFINE(_idx, _name, _flags, ...) \ 19062306a36Sopenharmony_ci [CLK_PREFIX(_idx)] = { \ 19162306a36Sopenharmony_ci .name = _name, \ 19262306a36Sopenharmony_ci .flags = _flags, \ 19362306a36Sopenharmony_ci .parents = { __VA_ARGS__ }, \ 19462306a36Sopenharmony_ci .num_parents = NUMARGS(__VA_ARGS__), \ 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic const struct clk_proto_t clk_proto[LPC32XX_CLK_CCF_MAX] __initconst = { 19862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(XTAL, "xtal", 0x0), 19962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(XTAL_32K, "xtal_32k", 0x0), 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(RTC, "rtc", 0x0, LPC32XX_CLK_XTAL_32K), 20262306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(OSC, "osc", CLK_IGNORE_UNUSED, LPC32XX_CLK_XTAL), 20362306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SYS, "sys", CLK_IGNORE_UNUSED, 20462306a36Sopenharmony_ci LPC32XX_CLK_OSC, LPC32XX_CLK_PLL397X), 20562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(PLL397X, "pll_397x", CLK_IGNORE_UNUSED, 20662306a36Sopenharmony_ci LPC32XX_CLK_RTC), 20762306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(HCLK_PLL, "hclk_pll", CLK_IGNORE_UNUSED, 20862306a36Sopenharmony_ci LPC32XX_CLK_SYS), 20962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(HCLK_DIV_PERIPH, "hclk_div_periph", 21062306a36Sopenharmony_ci CLK_IGNORE_UNUSED, LPC32XX_CLK_HCLK_PLL), 21162306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(HCLK_DIV, "hclk_div", CLK_IGNORE_UNUSED, 21262306a36Sopenharmony_ci LPC32XX_CLK_HCLK_PLL), 21362306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(HCLK, "hclk", CLK_IGNORE_UNUSED, 21462306a36Sopenharmony_ci LPC32XX_CLK_PERIPH_HCLK_MUX), 21562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(PERIPH, "pclk", CLK_IGNORE_UNUSED, 21662306a36Sopenharmony_ci LPC32XX_CLK_SYSCLK_PERIPH_MUX), 21762306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(ARM, "arm", CLK_IGNORE_UNUSED, 21862306a36Sopenharmony_ci LPC32XX_CLK_PERIPH_ARM_MUX), 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(PERIPH_HCLK_MUX, "periph_hclk_mux", 22162306a36Sopenharmony_ci CLK_IGNORE_UNUSED, 22262306a36Sopenharmony_ci LPC32XX_CLK_SYSCLK_HCLK_MUX, LPC32XX_CLK_SYSCLK_PERIPH_MUX), 22362306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(PERIPH_ARM_MUX, "periph_arm_mux", CLK_IGNORE_UNUSED, 22462306a36Sopenharmony_ci LPC32XX_CLK_SYSCLK_ARM_MUX, LPC32XX_CLK_SYSCLK_PERIPH_MUX), 22562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SYSCLK_PERIPH_MUX, "sysclk_periph_mux", 22662306a36Sopenharmony_ci CLK_IGNORE_UNUSED, 22762306a36Sopenharmony_ci LPC32XX_CLK_SYS, LPC32XX_CLK_HCLK_DIV_PERIPH), 22862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SYSCLK_HCLK_MUX, "sysclk_hclk_mux", 22962306a36Sopenharmony_ci CLK_IGNORE_UNUSED, 23062306a36Sopenharmony_ci LPC32XX_CLK_SYS, LPC32XX_CLK_HCLK_DIV), 23162306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SYSCLK_ARM_MUX, "sysclk_arm_mux", CLK_IGNORE_UNUSED, 23262306a36Sopenharmony_ci LPC32XX_CLK_SYS, LPC32XX_CLK_HCLK_PLL), 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(ARM_VFP, "vfp9", CLK_IGNORE_UNUSED, 23562306a36Sopenharmony_ci LPC32XX_CLK_ARM), 23662306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB_PLL, "usb_pll", 23762306a36Sopenharmony_ci CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT, LPC32XX_CLK_USB_DIV), 23862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB_DIV, "usb_div", 0x0, LPC32XX_CLK_OSC), 23962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB, "usb", 0x0, LPC32XX_CLK_USB_PLL), 24062306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(DMA, "dma", 0x0, LPC32XX_CLK_HCLK), 24162306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(MLC, "mlc", 0x0, LPC32XX_CLK_HCLK), 24262306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SLC, "slc", 0x0, LPC32XX_CLK_HCLK), 24362306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(LCD, "lcd", 0x0, LPC32XX_CLK_HCLK), 24462306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(MAC, "mac", 0x0, LPC32XX_CLK_HCLK), 24562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SD, "sd", 0x0, LPC32XX_CLK_ARM), 24662306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(DDRAM, "ddram", CLK_GET_RATE_NOCACHE, 24762306a36Sopenharmony_ci LPC32XX_CLK_SYSCLK_ARM_MUX), 24862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SSP0, "ssp0", 0x0, LPC32XX_CLK_HCLK), 24962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SSP1, "ssp1", 0x0, LPC32XX_CLK_HCLK), 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* 25262306a36Sopenharmony_ci * CLK_GET_RATE_NOCACHE is needed, if UART clock is disabled, its 25362306a36Sopenharmony_ci * divider register does not contain information about selected rate. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(UART3, "uart3", CLK_GET_RATE_NOCACHE, 25662306a36Sopenharmony_ci LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK), 25762306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(UART4, "uart4", CLK_GET_RATE_NOCACHE, 25862306a36Sopenharmony_ci LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK), 25962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(UART5, "uart5", CLK_GET_RATE_NOCACHE, 26062306a36Sopenharmony_ci LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK), 26162306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(UART6, "uart6", CLK_GET_RATE_NOCACHE, 26262306a36Sopenharmony_ci LPC32XX_CLK_PERIPH, LPC32XX_CLK_HCLK), 26362306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(IRDA, "irda", 0x0, LPC32XX_CLK_PERIPH), 26462306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(I2C1, "i2c1", 0x0, LPC32XX_CLK_HCLK), 26562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(I2C2, "i2c2", 0x0, LPC32XX_CLK_HCLK), 26662306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TIMER0, "timer0", 0x0, LPC32XX_CLK_PERIPH), 26762306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TIMER1, "timer1", 0x0, LPC32XX_CLK_PERIPH), 26862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TIMER2, "timer2", 0x0, LPC32XX_CLK_PERIPH), 26962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TIMER3, "timer3", 0x0, LPC32XX_CLK_PERIPH), 27062306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TIMER4, "timer4", 0x0, LPC32XX_CLK_PERIPH), 27162306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TIMER5, "timer5", 0x0, LPC32XX_CLK_PERIPH), 27262306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(WDOG, "watchdog", 0x0, LPC32XX_CLK_PERIPH), 27362306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(I2S0, "i2s0", 0x0, LPC32XX_CLK_HCLK), 27462306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(I2S1, "i2s1", 0x0, LPC32XX_CLK_HCLK), 27562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SPI1, "spi1", 0x0, LPC32XX_CLK_HCLK), 27662306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(SPI2, "spi2", 0x0, LPC32XX_CLK_HCLK), 27762306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(MCPWM, "mcpwm", 0x0, LPC32XX_CLK_HCLK), 27862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(HSTIMER, "hstimer", 0x0, LPC32XX_CLK_PERIPH), 27962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(KEY, "key", 0x0, LPC32XX_CLK_RTC), 28062306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(PWM1, "pwm1", 0x0, 28162306a36Sopenharmony_ci LPC32XX_CLK_RTC, LPC32XX_CLK_PERIPH), 28262306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(PWM2, "pwm2", 0x0, 28362306a36Sopenharmony_ci LPC32XX_CLK_RTC, LPC32XX_CLK_PERIPH), 28462306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(ADC, "adc", 0x0, 28562306a36Sopenharmony_ci LPC32XX_CLK_ADC_RTC, LPC32XX_CLK_ADC_DIV), 28662306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(ADC_DIV, "adc_div", 0x0, LPC32XX_CLK_PERIPH), 28762306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(ADC_RTC, "adc_rtc", 0x0, LPC32XX_CLK_RTC), 28862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TEST1, "test1", 0x0, 28962306a36Sopenharmony_ci LPC32XX_CLK_PERIPH, LPC32XX_CLK_RTC, LPC32XX_CLK_OSC), 29062306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(TEST2, "test2", 0x0, 29162306a36Sopenharmony_ci LPC32XX_CLK_HCLK, LPC32XX_CLK_PERIPH, LPC32XX_CLK_USB, 29262306a36Sopenharmony_ci LPC32XX_CLK_OSC, LPC32XX_CLK_PLL397X), 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* USB controller clocks */ 29562306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB_AHB, "usb_ahb", 0x0, LPC32XX_CLK_USB), 29662306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB_OTG, "usb_otg", 0x0, LPC32XX_CLK_USB_AHB), 29762306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB_I2C, "usb_i2c", 0x0, LPC32XX_CLK_USB_AHB), 29862306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB_DEV, "usb_dev", 0x0, LPC32XX_CLK_USB_OTG), 29962306a36Sopenharmony_ci LPC32XX_CLK_DEFINE(USB_HOST, "usb_host", 0x0, LPC32XX_CLK_USB_OTG), 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistruct lpc32xx_clk { 30362306a36Sopenharmony_ci struct clk_hw hw; 30462306a36Sopenharmony_ci u32 reg; 30562306a36Sopenharmony_ci u32 enable; 30662306a36Sopenharmony_ci u32 enable_mask; 30762306a36Sopenharmony_ci u32 disable; 30862306a36Sopenharmony_ci u32 disable_mask; 30962306a36Sopenharmony_ci u32 busy; 31062306a36Sopenharmony_ci u32 busy_mask; 31162306a36Sopenharmony_ci}; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cienum clk_pll_mode { 31462306a36Sopenharmony_ci PLL_UNKNOWN, 31562306a36Sopenharmony_ci PLL_DIRECT, 31662306a36Sopenharmony_ci PLL_BYPASS, 31762306a36Sopenharmony_ci PLL_DIRECT_BYPASS, 31862306a36Sopenharmony_ci PLL_INTEGER, 31962306a36Sopenharmony_ci PLL_NON_INTEGER, 32062306a36Sopenharmony_ci}; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistruct lpc32xx_pll_clk { 32362306a36Sopenharmony_ci struct clk_hw hw; 32462306a36Sopenharmony_ci u32 reg; 32562306a36Sopenharmony_ci u32 enable; 32662306a36Sopenharmony_ci unsigned long m_div; 32762306a36Sopenharmony_ci unsigned long n_div; 32862306a36Sopenharmony_ci unsigned long p_div; 32962306a36Sopenharmony_ci enum clk_pll_mode mode; 33062306a36Sopenharmony_ci}; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistruct lpc32xx_usb_clk { 33362306a36Sopenharmony_ci struct clk_hw hw; 33462306a36Sopenharmony_ci u32 ctrl_enable; 33562306a36Sopenharmony_ci u32 ctrl_disable; 33662306a36Sopenharmony_ci u32 ctrl_mask; 33762306a36Sopenharmony_ci u32 enable; 33862306a36Sopenharmony_ci u32 busy; 33962306a36Sopenharmony_ci}; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistruct lpc32xx_clk_mux { 34262306a36Sopenharmony_ci struct clk_hw hw; 34362306a36Sopenharmony_ci u32 reg; 34462306a36Sopenharmony_ci u32 mask; 34562306a36Sopenharmony_ci u8 shift; 34662306a36Sopenharmony_ci u32 *table; 34762306a36Sopenharmony_ci u8 flags; 34862306a36Sopenharmony_ci}; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistruct lpc32xx_clk_div { 35162306a36Sopenharmony_ci struct clk_hw hw; 35262306a36Sopenharmony_ci u32 reg; 35362306a36Sopenharmony_ci u8 shift; 35462306a36Sopenharmony_ci u8 width; 35562306a36Sopenharmony_ci const struct clk_div_table *table; 35662306a36Sopenharmony_ci u8 flags; 35762306a36Sopenharmony_ci}; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistruct lpc32xx_clk_gate { 36062306a36Sopenharmony_ci struct clk_hw hw; 36162306a36Sopenharmony_ci u32 reg; 36262306a36Sopenharmony_ci u8 bit_idx; 36362306a36Sopenharmony_ci u8 flags; 36462306a36Sopenharmony_ci}; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci#define to_lpc32xx_clk(_hw) container_of(_hw, struct lpc32xx_clk, hw) 36762306a36Sopenharmony_ci#define to_lpc32xx_pll_clk(_hw) container_of(_hw, struct lpc32xx_pll_clk, hw) 36862306a36Sopenharmony_ci#define to_lpc32xx_usb_clk(_hw) container_of(_hw, struct lpc32xx_usb_clk, hw) 36962306a36Sopenharmony_ci#define to_lpc32xx_mux(_hw) container_of(_hw, struct lpc32xx_clk_mux, hw) 37062306a36Sopenharmony_ci#define to_lpc32xx_div(_hw) container_of(_hw, struct lpc32xx_clk_div, hw) 37162306a36Sopenharmony_ci#define to_lpc32xx_gate(_hw) container_of(_hw, struct lpc32xx_clk_gate, hw) 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic inline bool pll_is_valid(u64 val0, u64 val1, u64 min, u64 max) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci return (val0 >= (val1 * min) && val0 <= (val1 * max)); 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic inline u32 lpc32xx_usb_clk_read(struct lpc32xx_usb_clk *clk) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci return readl(usb_clk_vbase + LPC32XX_USB_CLK_STS); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic inline void lpc32xx_usb_clk_write(struct lpc32xx_usb_clk *clk, u32 val) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci writel(val, usb_clk_vbase + LPC32XX_USB_CLK_CTRL); 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic int clk_mask_enable(struct clk_hw *hw) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct lpc32xx_clk *clk = to_lpc32xx_clk(hw); 39162306a36Sopenharmony_ci u32 val; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (clk->busy_mask && (val & clk->busy_mask) == clk->busy) 39662306a36Sopenharmony_ci return -EBUSY; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return regmap_update_bits(clk_regmap, clk->reg, 39962306a36Sopenharmony_ci clk->enable_mask, clk->enable); 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic void clk_mask_disable(struct clk_hw *hw) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci struct lpc32xx_clk *clk = to_lpc32xx_clk(hw); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci regmap_update_bits(clk_regmap, clk->reg, 40762306a36Sopenharmony_ci clk->disable_mask, clk->disable); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic int clk_mask_is_enabled(struct clk_hw *hw) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci struct lpc32xx_clk *clk = to_lpc32xx_clk(hw); 41362306a36Sopenharmony_ci u32 val; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci return ((val & clk->enable_mask) == clk->enable); 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic const struct clk_ops clk_mask_ops = { 42162306a36Sopenharmony_ci .enable = clk_mask_enable, 42262306a36Sopenharmony_ci .disable = clk_mask_disable, 42362306a36Sopenharmony_ci .is_enabled = clk_mask_is_enabled, 42462306a36Sopenharmony_ci}; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic int clk_pll_enable(struct clk_hw *hw) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw); 42962306a36Sopenharmony_ci u32 val, count; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci regmap_update_bits(clk_regmap, clk->reg, clk->enable, clk->enable); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci for (count = 0; count < 1000; count++) { 43462306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 43562306a36Sopenharmony_ci if (val & PLL_CTRL_LOCK) 43662306a36Sopenharmony_ci break; 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (val & PLL_CTRL_LOCK) 44062306a36Sopenharmony_ci return 0; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci return -ETIMEDOUT; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic void clk_pll_disable(struct clk_hw *hw) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci regmap_update_bits(clk_regmap, clk->reg, clk->enable, 0x0); 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic int clk_pll_is_enabled(struct clk_hw *hw) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw); 45562306a36Sopenharmony_ci u32 val; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci val &= clk->enable | PLL_CTRL_LOCK; 46062306a36Sopenharmony_ci if (val == (clk->enable | PLL_CTRL_LOCK)) 46162306a36Sopenharmony_ci return 1; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci return 0; 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic unsigned long clk_pll_397x_recalc_rate(struct clk_hw *hw, 46762306a36Sopenharmony_ci unsigned long parent_rate) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci return parent_rate * 397; 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_cistatic unsigned long clk_pll_recalc_rate(struct clk_hw *hw, 47362306a36Sopenharmony_ci unsigned long parent_rate) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw); 47662306a36Sopenharmony_ci bool is_direct, is_bypass, is_feedback; 47762306a36Sopenharmony_ci unsigned long rate, cco_rate, ref_rate; 47862306a36Sopenharmony_ci u32 val; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 48162306a36Sopenharmony_ci is_direct = val & PLL_CTRL_DIRECT; 48262306a36Sopenharmony_ci is_bypass = val & PLL_CTRL_BYPASS; 48362306a36Sopenharmony_ci is_feedback = val & PLL_CTRL_FEEDBACK; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci clk->m_div = ((val & PLL_CTRL_FEEDDIV) >> 1) + 1; 48662306a36Sopenharmony_ci clk->n_div = ((val & PLL_CTRL_PREDIV) >> 9) + 1; 48762306a36Sopenharmony_ci clk->p_div = ((val & PLL_CTRL_POSTDIV) >> 11) + 1; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci if (is_direct && is_bypass) { 49062306a36Sopenharmony_ci clk->p_div = 0; 49162306a36Sopenharmony_ci clk->mode = PLL_DIRECT_BYPASS; 49262306a36Sopenharmony_ci return parent_rate; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci if (is_bypass) { 49562306a36Sopenharmony_ci clk->mode = PLL_BYPASS; 49662306a36Sopenharmony_ci return parent_rate / (1 << clk->p_div); 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci if (is_direct) { 49962306a36Sopenharmony_ci clk->p_div = 0; 50062306a36Sopenharmony_ci clk->mode = PLL_DIRECT; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci ref_rate = parent_rate / clk->n_div; 50462306a36Sopenharmony_ci rate = cco_rate = ref_rate * clk->m_div; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if (!is_direct) { 50762306a36Sopenharmony_ci if (is_feedback) { 50862306a36Sopenharmony_ci cco_rate *= (1 << clk->p_div); 50962306a36Sopenharmony_ci clk->mode = PLL_INTEGER; 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci rate /= (1 << clk->p_div); 51262306a36Sopenharmony_ci clk->mode = PLL_NON_INTEGER; 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci pr_debug("%s: %lu: 0x%x: %d/%d/%d, %lu/%lu/%d => %lu\n", 51762306a36Sopenharmony_ci clk_hw_get_name(hw), 51862306a36Sopenharmony_ci parent_rate, val, is_direct, is_bypass, is_feedback, 51962306a36Sopenharmony_ci clk->n_div, clk->m_div, (1 << clk->p_div), rate); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (clk_pll_is_enabled(hw) && 52262306a36Sopenharmony_ci !(pll_is_valid(parent_rate, 1, 1000000, 20000000) 52362306a36Sopenharmony_ci && pll_is_valid(cco_rate, 1, 156000000, 320000000) 52462306a36Sopenharmony_ci && pll_is_valid(ref_rate, 1, 1000000, 27000000))) 52562306a36Sopenharmony_ci pr_err("%s: PLL clocks are not in valid ranges: %lu/%lu/%lu\n", 52662306a36Sopenharmony_ci clk_hw_get_name(hw), 52762306a36Sopenharmony_ci parent_rate, cco_rate, ref_rate); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci return rate; 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, 53362306a36Sopenharmony_ci unsigned long parent_rate) 53462306a36Sopenharmony_ci{ 53562306a36Sopenharmony_ci struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw); 53662306a36Sopenharmony_ci u32 val; 53762306a36Sopenharmony_ci unsigned long new_rate; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci /* Validate PLL clock parameters computed on round rate stage */ 54062306a36Sopenharmony_ci switch (clk->mode) { 54162306a36Sopenharmony_ci case PLL_DIRECT: 54262306a36Sopenharmony_ci val = PLL_CTRL_DIRECT; 54362306a36Sopenharmony_ci val |= (clk->m_div - 1) << 1; 54462306a36Sopenharmony_ci val |= (clk->n_div - 1) << 9; 54562306a36Sopenharmony_ci new_rate = (parent_rate * clk->m_div) / clk->n_div; 54662306a36Sopenharmony_ci break; 54762306a36Sopenharmony_ci case PLL_BYPASS: 54862306a36Sopenharmony_ci val = PLL_CTRL_BYPASS; 54962306a36Sopenharmony_ci val |= (clk->p_div - 1) << 11; 55062306a36Sopenharmony_ci new_rate = parent_rate / (1 << (clk->p_div)); 55162306a36Sopenharmony_ci break; 55262306a36Sopenharmony_ci case PLL_DIRECT_BYPASS: 55362306a36Sopenharmony_ci val = PLL_CTRL_DIRECT | PLL_CTRL_BYPASS; 55462306a36Sopenharmony_ci new_rate = parent_rate; 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci case PLL_INTEGER: 55762306a36Sopenharmony_ci val = PLL_CTRL_FEEDBACK; 55862306a36Sopenharmony_ci val |= (clk->m_div - 1) << 1; 55962306a36Sopenharmony_ci val |= (clk->n_div - 1) << 9; 56062306a36Sopenharmony_ci val |= (clk->p_div - 1) << 11; 56162306a36Sopenharmony_ci new_rate = (parent_rate * clk->m_div) / clk->n_div; 56262306a36Sopenharmony_ci break; 56362306a36Sopenharmony_ci case PLL_NON_INTEGER: 56462306a36Sopenharmony_ci val = 0x0; 56562306a36Sopenharmony_ci val |= (clk->m_div - 1) << 1; 56662306a36Sopenharmony_ci val |= (clk->n_div - 1) << 9; 56762306a36Sopenharmony_ci val |= (clk->p_div - 1) << 11; 56862306a36Sopenharmony_ci new_rate = (parent_rate * clk->m_div) / 56962306a36Sopenharmony_ci (clk->n_div * (1 << clk->p_div)); 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci default: 57262306a36Sopenharmony_ci return -EINVAL; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci /* Sanity check that round rate is equal to the requested one */ 57662306a36Sopenharmony_ci if (new_rate != rate) 57762306a36Sopenharmony_ci return -EINVAL; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci return regmap_update_bits(clk_regmap, clk->reg, 0x1FFFF, val); 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic long clk_hclk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 58362306a36Sopenharmony_ci unsigned long *parent_rate) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw); 58662306a36Sopenharmony_ci u64 m_i, o = rate, i = *parent_rate, d = (u64)rate << 6; 58762306a36Sopenharmony_ci u64 m = 0, n = 0, p = 0; 58862306a36Sopenharmony_ci int p_i, n_i; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), *parent_rate, rate); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (rate > 266500000) 59362306a36Sopenharmony_ci return -EINVAL; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* Have to check all 20 possibilities to find the minimal M */ 59662306a36Sopenharmony_ci for (p_i = 4; p_i >= 0; p_i--) { 59762306a36Sopenharmony_ci for (n_i = 4; n_i > 0; n_i--) { 59862306a36Sopenharmony_ci m_i = div64_u64(o * n_i * (1 << p_i), i); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /* Check for valid PLL parameter constraints */ 60162306a36Sopenharmony_ci if (!(m_i && m_i <= 256 60262306a36Sopenharmony_ci && pll_is_valid(i, n_i, 1000000, 27000000) 60362306a36Sopenharmony_ci && pll_is_valid(i * m_i * (1 << p_i), n_i, 60462306a36Sopenharmony_ci 156000000, 320000000))) 60562306a36Sopenharmony_ci continue; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* Store some intermediate valid parameters */ 60862306a36Sopenharmony_ci if (o * n_i * (1 << p_i) - i * m_i <= d) { 60962306a36Sopenharmony_ci m = m_i; 61062306a36Sopenharmony_ci n = n_i; 61162306a36Sopenharmony_ci p = p_i; 61262306a36Sopenharmony_ci d = o * n_i * (1 << p_i) - i * m_i; 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (d == (u64)rate << 6) { 61862306a36Sopenharmony_ci pr_err("%s: %lu: no valid PLL parameters are found\n", 61962306a36Sopenharmony_ci clk_hw_get_name(hw), rate); 62062306a36Sopenharmony_ci return -EINVAL; 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci clk->m_div = m; 62462306a36Sopenharmony_ci clk->n_div = n; 62562306a36Sopenharmony_ci clk->p_div = p; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* Set only direct or non-integer mode of PLL */ 62862306a36Sopenharmony_ci if (!p) 62962306a36Sopenharmony_ci clk->mode = PLL_DIRECT; 63062306a36Sopenharmony_ci else 63162306a36Sopenharmony_ci clk->mode = PLL_NON_INTEGER; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci o = div64_u64(i * m, n * (1 << p)); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci if (!d) 63662306a36Sopenharmony_ci pr_debug("%s: %lu: found exact match: %llu/%llu/%llu\n", 63762306a36Sopenharmony_ci clk_hw_get_name(hw), rate, m, n, p); 63862306a36Sopenharmony_ci else 63962306a36Sopenharmony_ci pr_debug("%s: %lu: found closest: %llu/%llu/%llu - %llu\n", 64062306a36Sopenharmony_ci clk_hw_get_name(hw), rate, m, n, p, o); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci return o; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic long clk_usb_pll_round_rate(struct clk_hw *hw, unsigned long rate, 64662306a36Sopenharmony_ci unsigned long *parent_rate) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw); 64962306a36Sopenharmony_ci struct clk_hw *usb_div_hw, *osc_hw; 65062306a36Sopenharmony_ci u64 d_i, n_i, m, o; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), *parent_rate, rate); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci /* 65562306a36Sopenharmony_ci * The only supported USB clock is 48MHz, with PLL internal constraints 65662306a36Sopenharmony_ci * on Fclkin, Fcco and Fref this implies that Fcco must be 192MHz 65762306a36Sopenharmony_ci * and post-divider must be 4, this slightly simplifies calculation of 65862306a36Sopenharmony_ci * USB divider, USB PLL N and M parameters. 65962306a36Sopenharmony_ci */ 66062306a36Sopenharmony_ci if (rate != 48000000) 66162306a36Sopenharmony_ci return -EINVAL; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci /* USB divider clock */ 66462306a36Sopenharmony_ci usb_div_hw = clk_hw_get_parent_by_index(hw, 0); 66562306a36Sopenharmony_ci if (!usb_div_hw) 66662306a36Sopenharmony_ci return -EINVAL; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci /* Main oscillator clock */ 66962306a36Sopenharmony_ci osc_hw = clk_hw_get_parent_by_index(usb_div_hw, 0); 67062306a36Sopenharmony_ci if (!osc_hw) 67162306a36Sopenharmony_ci return -EINVAL; 67262306a36Sopenharmony_ci o = clk_hw_get_rate(osc_hw); /* must be in range 1..20 MHz */ 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci /* Check if valid USB divider and USB PLL parameters exists */ 67562306a36Sopenharmony_ci for (d_i = 16; d_i >= 1; d_i--) { 67662306a36Sopenharmony_ci for (n_i = 1; n_i <= 4; n_i++) { 67762306a36Sopenharmony_ci m = div64_u64(192000000 * d_i * n_i, o); 67862306a36Sopenharmony_ci if (!(m && m <= 256 67962306a36Sopenharmony_ci && m * o == 192000000 * d_i * n_i 68062306a36Sopenharmony_ci && pll_is_valid(o, d_i, 1000000, 20000000) 68162306a36Sopenharmony_ci && pll_is_valid(o, d_i * n_i, 1000000, 27000000))) 68262306a36Sopenharmony_ci continue; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci clk->n_div = n_i; 68562306a36Sopenharmony_ci clk->m_div = m; 68662306a36Sopenharmony_ci clk->p_div = 2; 68762306a36Sopenharmony_ci clk->mode = PLL_NON_INTEGER; 68862306a36Sopenharmony_ci *parent_rate = div64_u64(o, d_i); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci return rate; 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci return -EINVAL; 69562306a36Sopenharmony_ci} 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci#define LPC32XX_DEFINE_PLL_OPS(_name, _rc, _sr, _rr) \ 69862306a36Sopenharmony_ci static const struct clk_ops clk_ ##_name ## _ops = { \ 69962306a36Sopenharmony_ci .enable = clk_pll_enable, \ 70062306a36Sopenharmony_ci .disable = clk_pll_disable, \ 70162306a36Sopenharmony_ci .is_enabled = clk_pll_is_enabled, \ 70262306a36Sopenharmony_ci .recalc_rate = _rc, \ 70362306a36Sopenharmony_ci .set_rate = _sr, \ 70462306a36Sopenharmony_ci .round_rate = _rr, \ 70562306a36Sopenharmony_ci } 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ciLPC32XX_DEFINE_PLL_OPS(pll_397x, clk_pll_397x_recalc_rate, NULL, NULL); 70862306a36Sopenharmony_ciLPC32XX_DEFINE_PLL_OPS(hclk_pll, clk_pll_recalc_rate, 70962306a36Sopenharmony_ci clk_pll_set_rate, clk_hclk_pll_round_rate); 71062306a36Sopenharmony_ciLPC32XX_DEFINE_PLL_OPS(usb_pll, clk_pll_recalc_rate, 71162306a36Sopenharmony_ci clk_pll_set_rate, clk_usb_pll_round_rate); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic int clk_ddram_is_enabled(struct clk_hw *hw) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct lpc32xx_clk *clk = to_lpc32xx_clk(hw); 71662306a36Sopenharmony_ci u32 val; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 71962306a36Sopenharmony_ci val &= clk->enable_mask | clk->busy_mask; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci return (val == (BIT(7) | BIT(0)) || 72262306a36Sopenharmony_ci val == (BIT(8) | BIT(1))); 72362306a36Sopenharmony_ci} 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_cistatic int clk_ddram_enable(struct clk_hw *hw) 72662306a36Sopenharmony_ci{ 72762306a36Sopenharmony_ci struct lpc32xx_clk *clk = to_lpc32xx_clk(hw); 72862306a36Sopenharmony_ci u32 val, hclk_div; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 73162306a36Sopenharmony_ci hclk_div = val & clk->busy_mask; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci /* 73462306a36Sopenharmony_ci * DDRAM clock must be 2 times higher than HCLK, 73562306a36Sopenharmony_ci * this implies DDRAM clock can not be enabled, 73662306a36Sopenharmony_ci * if HCLK clock rate is equal to ARM clock rate 73762306a36Sopenharmony_ci */ 73862306a36Sopenharmony_ci if (hclk_div == 0x0 || hclk_div == (BIT(1) | BIT(0))) 73962306a36Sopenharmony_ci return -EINVAL; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci return regmap_update_bits(clk_regmap, clk->reg, 74262306a36Sopenharmony_ci clk->enable_mask, hclk_div << 7); 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic unsigned long clk_ddram_recalc_rate(struct clk_hw *hw, 74662306a36Sopenharmony_ci unsigned long parent_rate) 74762306a36Sopenharmony_ci{ 74862306a36Sopenharmony_ci struct lpc32xx_clk *clk = to_lpc32xx_clk(hw); 74962306a36Sopenharmony_ci u32 val; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (!clk_ddram_is_enabled(hw)) 75262306a36Sopenharmony_ci return 0; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 75562306a36Sopenharmony_ci val &= clk->enable_mask; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci return parent_rate / (val >> 7); 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic const struct clk_ops clk_ddram_ops = { 76162306a36Sopenharmony_ci .enable = clk_ddram_enable, 76262306a36Sopenharmony_ci .disable = clk_mask_disable, 76362306a36Sopenharmony_ci .is_enabled = clk_ddram_is_enabled, 76462306a36Sopenharmony_ci .recalc_rate = clk_ddram_recalc_rate, 76562306a36Sopenharmony_ci}; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_cistatic unsigned long lpc32xx_clk_uart_recalc_rate(struct clk_hw *hw, 76862306a36Sopenharmony_ci unsigned long parent_rate) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci struct lpc32xx_clk *clk = to_lpc32xx_clk(hw); 77162306a36Sopenharmony_ci u32 val, x, y; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 77462306a36Sopenharmony_ci x = (val & 0xFF00) >> 8; 77562306a36Sopenharmony_ci y = val & 0xFF; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci if (x && y) 77862306a36Sopenharmony_ci return (parent_rate * x) / y; 77962306a36Sopenharmony_ci else 78062306a36Sopenharmony_ci return 0; 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic const struct clk_ops lpc32xx_uart_div_ops = { 78462306a36Sopenharmony_ci .recalc_rate = lpc32xx_clk_uart_recalc_rate, 78562306a36Sopenharmony_ci}; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cistatic const struct clk_div_table clk_hclk_div_table[] = { 78862306a36Sopenharmony_ci { .val = 0, .div = 1 }, 78962306a36Sopenharmony_ci { .val = 1, .div = 2 }, 79062306a36Sopenharmony_ci { .val = 2, .div = 4 }, 79162306a36Sopenharmony_ci { }, 79262306a36Sopenharmony_ci}; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_cistatic u32 test1_mux_table[] = { 0, 1, 2, }; 79562306a36Sopenharmony_cistatic u32 test2_mux_table[] = { 0, 1, 2, 5, 7, }; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic int clk_usb_enable(struct clk_hw *hw) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct lpc32xx_usb_clk *clk = to_lpc32xx_usb_clk(hw); 80062306a36Sopenharmony_ci u32 val, ctrl_val, count; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci pr_debug("%s: 0x%x\n", clk_hw_get_name(hw), clk->enable); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci if (clk->ctrl_mask) { 80562306a36Sopenharmony_ci regmap_read(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, &ctrl_val); 80662306a36Sopenharmony_ci regmap_update_bits(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, 80762306a36Sopenharmony_ci clk->ctrl_mask, clk->ctrl_enable); 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci val = lpc32xx_usb_clk_read(clk); 81162306a36Sopenharmony_ci if (clk->busy && (val & clk->busy) == clk->busy) { 81262306a36Sopenharmony_ci if (clk->ctrl_mask) 81362306a36Sopenharmony_ci regmap_write(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, 81462306a36Sopenharmony_ci ctrl_val); 81562306a36Sopenharmony_ci return -EBUSY; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci val |= clk->enable; 81962306a36Sopenharmony_ci lpc32xx_usb_clk_write(clk, val); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci for (count = 0; count < 1000; count++) { 82262306a36Sopenharmony_ci val = lpc32xx_usb_clk_read(clk); 82362306a36Sopenharmony_ci if ((val & clk->enable) == clk->enable) 82462306a36Sopenharmony_ci break; 82562306a36Sopenharmony_ci } 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if ((val & clk->enable) == clk->enable) 82862306a36Sopenharmony_ci return 0; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci if (clk->ctrl_mask) 83162306a36Sopenharmony_ci regmap_write(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, ctrl_val); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci return -ETIMEDOUT; 83462306a36Sopenharmony_ci} 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_cistatic void clk_usb_disable(struct clk_hw *hw) 83762306a36Sopenharmony_ci{ 83862306a36Sopenharmony_ci struct lpc32xx_usb_clk *clk = to_lpc32xx_usb_clk(hw); 83962306a36Sopenharmony_ci u32 val = lpc32xx_usb_clk_read(clk); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci val &= ~clk->enable; 84262306a36Sopenharmony_ci lpc32xx_usb_clk_write(clk, val); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci if (clk->ctrl_mask) 84562306a36Sopenharmony_ci regmap_update_bits(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, 84662306a36Sopenharmony_ci clk->ctrl_mask, clk->ctrl_disable); 84762306a36Sopenharmony_ci} 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cistatic int clk_usb_is_enabled(struct clk_hw *hw) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci struct lpc32xx_usb_clk *clk = to_lpc32xx_usb_clk(hw); 85262306a36Sopenharmony_ci u32 ctrl_val, val; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci if (clk->ctrl_mask) { 85562306a36Sopenharmony_ci regmap_read(clk_regmap, LPC32XX_CLKPWR_USB_CTRL, &ctrl_val); 85662306a36Sopenharmony_ci if ((ctrl_val & clk->ctrl_mask) != clk->ctrl_enable) 85762306a36Sopenharmony_ci return 0; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci val = lpc32xx_usb_clk_read(clk); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci return ((val & clk->enable) == clk->enable); 86362306a36Sopenharmony_ci} 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cistatic unsigned long clk_usb_i2c_recalc_rate(struct clk_hw *hw, 86662306a36Sopenharmony_ci unsigned long parent_rate) 86762306a36Sopenharmony_ci{ 86862306a36Sopenharmony_ci return clk_get_rate(clk[LPC32XX_CLK_PERIPH]); 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_cistatic const struct clk_ops clk_usb_ops = { 87262306a36Sopenharmony_ci .enable = clk_usb_enable, 87362306a36Sopenharmony_ci .disable = clk_usb_disable, 87462306a36Sopenharmony_ci .is_enabled = clk_usb_is_enabled, 87562306a36Sopenharmony_ci}; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_cistatic const struct clk_ops clk_usb_i2c_ops = { 87862306a36Sopenharmony_ci .enable = clk_usb_enable, 87962306a36Sopenharmony_ci .disable = clk_usb_disable, 88062306a36Sopenharmony_ci .is_enabled = clk_usb_is_enabled, 88162306a36Sopenharmony_ci .recalc_rate = clk_usb_i2c_recalc_rate, 88262306a36Sopenharmony_ci}; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_cistatic int lpc32xx_clk_gate_enable(struct clk_hw *hw) 88562306a36Sopenharmony_ci{ 88662306a36Sopenharmony_ci struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); 88762306a36Sopenharmony_ci u32 mask = BIT(clk->bit_idx); 88862306a36Sopenharmony_ci u32 val = (clk->flags & CLK_GATE_SET_TO_DISABLE ? 0x0 : mask); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci return regmap_update_bits(clk_regmap, clk->reg, mask, val); 89162306a36Sopenharmony_ci} 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_cistatic void lpc32xx_clk_gate_disable(struct clk_hw *hw) 89462306a36Sopenharmony_ci{ 89562306a36Sopenharmony_ci struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); 89662306a36Sopenharmony_ci u32 mask = BIT(clk->bit_idx); 89762306a36Sopenharmony_ci u32 val = (clk->flags & CLK_GATE_SET_TO_DISABLE ? mask : 0x0); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci regmap_update_bits(clk_regmap, clk->reg, mask, val); 90062306a36Sopenharmony_ci} 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cistatic int lpc32xx_clk_gate_is_enabled(struct clk_hw *hw) 90362306a36Sopenharmony_ci{ 90462306a36Sopenharmony_ci struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); 90562306a36Sopenharmony_ci u32 val; 90662306a36Sopenharmony_ci bool is_set; 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci regmap_read(clk_regmap, clk->reg, &val); 90962306a36Sopenharmony_ci is_set = val & BIT(clk->bit_idx); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci return (clk->flags & CLK_GATE_SET_TO_DISABLE ? !is_set : is_set); 91262306a36Sopenharmony_ci} 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic const struct clk_ops lpc32xx_clk_gate_ops = { 91562306a36Sopenharmony_ci .enable = lpc32xx_clk_gate_enable, 91662306a36Sopenharmony_ci .disable = lpc32xx_clk_gate_disable, 91762306a36Sopenharmony_ci .is_enabled = lpc32xx_clk_gate_is_enabled, 91862306a36Sopenharmony_ci}; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci#define div_mask(width) ((1 << (width)) - 1) 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_cistatic unsigned int _get_table_div(const struct clk_div_table *table, 92362306a36Sopenharmony_ci unsigned int val) 92462306a36Sopenharmony_ci{ 92562306a36Sopenharmony_ci const struct clk_div_table *clkt; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci for (clkt = table; clkt->div; clkt++) 92862306a36Sopenharmony_ci if (clkt->val == val) 92962306a36Sopenharmony_ci return clkt->div; 93062306a36Sopenharmony_ci return 0; 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_cistatic unsigned int _get_div(const struct clk_div_table *table, 93462306a36Sopenharmony_ci unsigned int val, unsigned long flags, u8 width) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci if (flags & CLK_DIVIDER_ONE_BASED) 93762306a36Sopenharmony_ci return val; 93862306a36Sopenharmony_ci if (table) 93962306a36Sopenharmony_ci return _get_table_div(table, val); 94062306a36Sopenharmony_ci return val + 1; 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_cistatic unsigned long clk_divider_recalc_rate(struct clk_hw *hw, 94462306a36Sopenharmony_ci unsigned long parent_rate) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw); 94762306a36Sopenharmony_ci unsigned int val; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci regmap_read(clk_regmap, divider->reg, &val); 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci val >>= divider->shift; 95262306a36Sopenharmony_ci val &= div_mask(divider->width); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci return divider_recalc_rate(hw, parent_rate, val, divider->table, 95562306a36Sopenharmony_ci divider->flags, divider->width); 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_cistatic long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, 95962306a36Sopenharmony_ci unsigned long *prate) 96062306a36Sopenharmony_ci{ 96162306a36Sopenharmony_ci struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw); 96262306a36Sopenharmony_ci unsigned int bestdiv; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci /* if read only, just return current value */ 96562306a36Sopenharmony_ci if (divider->flags & CLK_DIVIDER_READ_ONLY) { 96662306a36Sopenharmony_ci regmap_read(clk_regmap, divider->reg, &bestdiv); 96762306a36Sopenharmony_ci bestdiv >>= divider->shift; 96862306a36Sopenharmony_ci bestdiv &= div_mask(divider->width); 96962306a36Sopenharmony_ci bestdiv = _get_div(divider->table, bestdiv, divider->flags, 97062306a36Sopenharmony_ci divider->width); 97162306a36Sopenharmony_ci return DIV_ROUND_UP(*prate, bestdiv); 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci return divider_round_rate(hw, rate, prate, divider->table, 97562306a36Sopenharmony_ci divider->width, divider->flags); 97662306a36Sopenharmony_ci} 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_cistatic int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, 97962306a36Sopenharmony_ci unsigned long parent_rate) 98062306a36Sopenharmony_ci{ 98162306a36Sopenharmony_ci struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw); 98262306a36Sopenharmony_ci unsigned int value; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci value = divider_get_val(rate, parent_rate, divider->table, 98562306a36Sopenharmony_ci divider->width, divider->flags); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci return regmap_update_bits(clk_regmap, divider->reg, 98862306a36Sopenharmony_ci div_mask(divider->width) << divider->shift, 98962306a36Sopenharmony_ci value << divider->shift); 99062306a36Sopenharmony_ci} 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_cistatic const struct clk_ops lpc32xx_clk_divider_ops = { 99362306a36Sopenharmony_ci .recalc_rate = clk_divider_recalc_rate, 99462306a36Sopenharmony_ci .round_rate = clk_divider_round_rate, 99562306a36Sopenharmony_ci .set_rate = clk_divider_set_rate, 99662306a36Sopenharmony_ci}; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_cistatic u8 clk_mux_get_parent(struct clk_hw *hw) 99962306a36Sopenharmony_ci{ 100062306a36Sopenharmony_ci struct lpc32xx_clk_mux *mux = to_lpc32xx_mux(hw); 100162306a36Sopenharmony_ci u32 num_parents = clk_hw_get_num_parents(hw); 100262306a36Sopenharmony_ci u32 val; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci regmap_read(clk_regmap, mux->reg, &val); 100562306a36Sopenharmony_ci val >>= mux->shift; 100662306a36Sopenharmony_ci val &= mux->mask; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci if (mux->table) { 100962306a36Sopenharmony_ci u32 i; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci for (i = 0; i < num_parents; i++) 101262306a36Sopenharmony_ci if (mux->table[i] == val) 101362306a36Sopenharmony_ci return i; 101462306a36Sopenharmony_ci return -EINVAL; 101562306a36Sopenharmony_ci } 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci if (val >= num_parents) 101862306a36Sopenharmony_ci return -EINVAL; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci return val; 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_cistatic int clk_mux_set_parent(struct clk_hw *hw, u8 index) 102462306a36Sopenharmony_ci{ 102562306a36Sopenharmony_ci struct lpc32xx_clk_mux *mux = to_lpc32xx_mux(hw); 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci if (mux->table) 102862306a36Sopenharmony_ci index = mux->table[index]; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci return regmap_update_bits(clk_regmap, mux->reg, 103162306a36Sopenharmony_ci mux->mask << mux->shift, index << mux->shift); 103262306a36Sopenharmony_ci} 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_cistatic const struct clk_ops lpc32xx_clk_mux_ro_ops = { 103562306a36Sopenharmony_ci .get_parent = clk_mux_get_parent, 103662306a36Sopenharmony_ci}; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_cistatic const struct clk_ops lpc32xx_clk_mux_ops = { 103962306a36Sopenharmony_ci .get_parent = clk_mux_get_parent, 104062306a36Sopenharmony_ci .set_parent = clk_mux_set_parent, 104162306a36Sopenharmony_ci .determine_rate = __clk_mux_determine_rate, 104262306a36Sopenharmony_ci}; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_cienum lpc32xx_clk_type { 104562306a36Sopenharmony_ci CLK_FIXED, 104662306a36Sopenharmony_ci CLK_MUX, 104762306a36Sopenharmony_ci CLK_DIV, 104862306a36Sopenharmony_ci CLK_GATE, 104962306a36Sopenharmony_ci CLK_COMPOSITE, 105062306a36Sopenharmony_ci CLK_LPC32XX, 105162306a36Sopenharmony_ci CLK_LPC32XX_PLL, 105262306a36Sopenharmony_ci CLK_LPC32XX_USB, 105362306a36Sopenharmony_ci}; 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_cistruct clk_hw_proto0 { 105662306a36Sopenharmony_ci const struct clk_ops *ops; 105762306a36Sopenharmony_ci union { 105862306a36Sopenharmony_ci struct lpc32xx_pll_clk pll; 105962306a36Sopenharmony_ci struct lpc32xx_clk clk; 106062306a36Sopenharmony_ci struct lpc32xx_usb_clk usb_clk; 106162306a36Sopenharmony_ci struct lpc32xx_clk_mux mux; 106262306a36Sopenharmony_ci struct lpc32xx_clk_div div; 106362306a36Sopenharmony_ci struct lpc32xx_clk_gate gate; 106462306a36Sopenharmony_ci }; 106562306a36Sopenharmony_ci}; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_cistruct clk_hw_proto1 { 106862306a36Sopenharmony_ci struct clk_hw_proto0 *mux; 106962306a36Sopenharmony_ci struct clk_hw_proto0 *div; 107062306a36Sopenharmony_ci struct clk_hw_proto0 *gate; 107162306a36Sopenharmony_ci}; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_cistruct clk_hw_proto { 107462306a36Sopenharmony_ci enum lpc32xx_clk_type type; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci union { 107762306a36Sopenharmony_ci struct clk_fixed_rate f; 107862306a36Sopenharmony_ci struct clk_hw_proto0 hw0; 107962306a36Sopenharmony_ci struct clk_hw_proto1 hw1; 108062306a36Sopenharmony_ci }; 108162306a36Sopenharmony_ci}; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci#define LPC32XX_DEFINE_FIXED(_idx, _rate) \ 108462306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 108562306a36Sopenharmony_ci .type = CLK_FIXED, \ 108662306a36Sopenharmony_ci { \ 108762306a36Sopenharmony_ci .f = { \ 108862306a36Sopenharmony_ci .fixed_rate = (_rate), \ 108962306a36Sopenharmony_ci }, \ 109062306a36Sopenharmony_ci }, \ 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci#define LPC32XX_DEFINE_PLL(_idx, _name, _reg, _enable) \ 109462306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 109562306a36Sopenharmony_ci .type = CLK_LPC32XX_PLL, \ 109662306a36Sopenharmony_ci { \ 109762306a36Sopenharmony_ci .hw0 = { \ 109862306a36Sopenharmony_ci .ops = &clk_ ##_name ## _ops, \ 109962306a36Sopenharmony_ci { \ 110062306a36Sopenharmony_ci .pll = { \ 110162306a36Sopenharmony_ci .reg = LPC32XX_CLKPWR_ ## _reg, \ 110262306a36Sopenharmony_ci .enable = (_enable), \ 110362306a36Sopenharmony_ci }, \ 110462306a36Sopenharmony_ci }, \ 110562306a36Sopenharmony_ci }, \ 110662306a36Sopenharmony_ci }, \ 110762306a36Sopenharmony_ci} 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci#define LPC32XX_DEFINE_MUX(_idx, _reg, _shift, _mask, _table, _flags) \ 111062306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 111162306a36Sopenharmony_ci .type = CLK_MUX, \ 111262306a36Sopenharmony_ci { \ 111362306a36Sopenharmony_ci .hw0 = { \ 111462306a36Sopenharmony_ci .ops = (_flags & CLK_MUX_READ_ONLY ? \ 111562306a36Sopenharmony_ci &lpc32xx_clk_mux_ro_ops : \ 111662306a36Sopenharmony_ci &lpc32xx_clk_mux_ops), \ 111762306a36Sopenharmony_ci { \ 111862306a36Sopenharmony_ci .mux = { \ 111962306a36Sopenharmony_ci .reg = LPC32XX_CLKPWR_ ## _reg, \ 112062306a36Sopenharmony_ci .mask = (_mask), \ 112162306a36Sopenharmony_ci .shift = (_shift), \ 112262306a36Sopenharmony_ci .table = (_table), \ 112362306a36Sopenharmony_ci .flags = (_flags), \ 112462306a36Sopenharmony_ci }, \ 112562306a36Sopenharmony_ci }, \ 112662306a36Sopenharmony_ci }, \ 112762306a36Sopenharmony_ci }, \ 112862306a36Sopenharmony_ci} 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci#define LPC32XX_DEFINE_DIV(_idx, _reg, _shift, _width, _table, _flags) \ 113162306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 113262306a36Sopenharmony_ci .type = CLK_DIV, \ 113362306a36Sopenharmony_ci { \ 113462306a36Sopenharmony_ci .hw0 = { \ 113562306a36Sopenharmony_ci .ops = &lpc32xx_clk_divider_ops, \ 113662306a36Sopenharmony_ci { \ 113762306a36Sopenharmony_ci .div = { \ 113862306a36Sopenharmony_ci .reg = LPC32XX_CLKPWR_ ## _reg, \ 113962306a36Sopenharmony_ci .shift = (_shift), \ 114062306a36Sopenharmony_ci .width = (_width), \ 114162306a36Sopenharmony_ci .table = (_table), \ 114262306a36Sopenharmony_ci .flags = (_flags), \ 114362306a36Sopenharmony_ci }, \ 114462306a36Sopenharmony_ci }, \ 114562306a36Sopenharmony_ci }, \ 114662306a36Sopenharmony_ci }, \ 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci#define LPC32XX_DEFINE_GATE(_idx, _reg, _bit, _flags) \ 115062306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 115162306a36Sopenharmony_ci .type = CLK_GATE, \ 115262306a36Sopenharmony_ci { \ 115362306a36Sopenharmony_ci .hw0 = { \ 115462306a36Sopenharmony_ci .ops = &lpc32xx_clk_gate_ops, \ 115562306a36Sopenharmony_ci { \ 115662306a36Sopenharmony_ci .gate = { \ 115762306a36Sopenharmony_ci .reg = LPC32XX_CLKPWR_ ## _reg, \ 115862306a36Sopenharmony_ci .bit_idx = (_bit), \ 115962306a36Sopenharmony_ci .flags = (_flags), \ 116062306a36Sopenharmony_ci }, \ 116162306a36Sopenharmony_ci }, \ 116262306a36Sopenharmony_ci }, \ 116362306a36Sopenharmony_ci }, \ 116462306a36Sopenharmony_ci} 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci#define LPC32XX_DEFINE_CLK(_idx, _reg, _e, _em, _d, _dm, _b, _bm, _ops) \ 116762306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 116862306a36Sopenharmony_ci .type = CLK_LPC32XX, \ 116962306a36Sopenharmony_ci { \ 117062306a36Sopenharmony_ci .hw0 = { \ 117162306a36Sopenharmony_ci .ops = &(_ops), \ 117262306a36Sopenharmony_ci { \ 117362306a36Sopenharmony_ci .clk = { \ 117462306a36Sopenharmony_ci .reg = LPC32XX_CLKPWR_ ## _reg, \ 117562306a36Sopenharmony_ci .enable = (_e), \ 117662306a36Sopenharmony_ci .enable_mask = (_em), \ 117762306a36Sopenharmony_ci .disable = (_d), \ 117862306a36Sopenharmony_ci .disable_mask = (_dm), \ 117962306a36Sopenharmony_ci .busy = (_b), \ 118062306a36Sopenharmony_ci .busy_mask = (_bm), \ 118162306a36Sopenharmony_ci }, \ 118262306a36Sopenharmony_ci }, \ 118362306a36Sopenharmony_ci }, \ 118462306a36Sopenharmony_ci }, \ 118562306a36Sopenharmony_ci} 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci#define LPC32XX_DEFINE_USB(_idx, _ce, _cd, _cm, _e, _b, _ops) \ 118862306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 118962306a36Sopenharmony_ci .type = CLK_LPC32XX_USB, \ 119062306a36Sopenharmony_ci { \ 119162306a36Sopenharmony_ci .hw0 = { \ 119262306a36Sopenharmony_ci .ops = &(_ops), \ 119362306a36Sopenharmony_ci { \ 119462306a36Sopenharmony_ci .usb_clk = { \ 119562306a36Sopenharmony_ci .ctrl_enable = (_ce), \ 119662306a36Sopenharmony_ci .ctrl_disable = (_cd), \ 119762306a36Sopenharmony_ci .ctrl_mask = (_cm), \ 119862306a36Sopenharmony_ci .enable = (_e), \ 119962306a36Sopenharmony_ci .busy = (_b), \ 120062306a36Sopenharmony_ci } \ 120162306a36Sopenharmony_ci }, \ 120262306a36Sopenharmony_ci } \ 120362306a36Sopenharmony_ci }, \ 120462306a36Sopenharmony_ci} 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci#define LPC32XX_DEFINE_COMPOSITE(_idx, _mux, _div, _gate) \ 120762306a36Sopenharmony_ci[CLK_PREFIX(_idx)] = { \ 120862306a36Sopenharmony_ci .type = CLK_COMPOSITE, \ 120962306a36Sopenharmony_ci { \ 121062306a36Sopenharmony_ci .hw1 = { \ 121162306a36Sopenharmony_ci .mux = (CLK_PREFIX(_mux) == LPC32XX_CLK__NULL ? NULL : \ 121262306a36Sopenharmony_ci &clk_hw_proto[CLK_PREFIX(_mux)].hw0), \ 121362306a36Sopenharmony_ci .div = (CLK_PREFIX(_div) == LPC32XX_CLK__NULL ? NULL : \ 121462306a36Sopenharmony_ci &clk_hw_proto[CLK_PREFIX(_div)].hw0), \ 121562306a36Sopenharmony_ci .gate = (CLK_PREFIX(_gate) == LPC32XX_CLK__NULL ? NULL :\ 121662306a36Sopenharmony_ci &clk_hw_proto[CLK_PREFIX(_gate)].hw0), \ 121762306a36Sopenharmony_ci }, \ 121862306a36Sopenharmony_ci }, \ 121962306a36Sopenharmony_ci} 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_cistatic struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = { 122262306a36Sopenharmony_ci LPC32XX_DEFINE_FIXED(RTC, 32768), 122362306a36Sopenharmony_ci LPC32XX_DEFINE_PLL(PLL397X, pll_397x, HCLKPLL_CTRL, BIT(1)), 122462306a36Sopenharmony_ci LPC32XX_DEFINE_PLL(HCLK_PLL, hclk_pll, HCLKPLL_CTRL, PLL_CTRL_ENABLE), 122562306a36Sopenharmony_ci LPC32XX_DEFINE_PLL(USB_PLL, usb_pll, USB_CTRL, PLL_CTRL_ENABLE), 122662306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(OSC, OSC_CTRL, 0, CLK_GATE_SET_TO_DISABLE), 122762306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(USB, USB_CTRL, 18, 0), 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(HCLK_DIV_PERIPH, HCLKDIV_CTRL, 2, 5, NULL, 123062306a36Sopenharmony_ci CLK_DIVIDER_READ_ONLY), 123162306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(HCLK_DIV, HCLKDIV_CTRL, 0, 2, clk_hclk_div_table, 123262306a36Sopenharmony_ci CLK_DIVIDER_READ_ONLY), 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci /* Register 3 read-only muxes with a single control PWR_CTRL[2] */ 123562306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(SYSCLK_PERIPH_MUX, PWR_CTRL, 2, 0x1, NULL, 123662306a36Sopenharmony_ci CLK_MUX_READ_ONLY), 123762306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(SYSCLK_HCLK_MUX, PWR_CTRL, 2, 0x1, NULL, 123862306a36Sopenharmony_ci CLK_MUX_READ_ONLY), 123962306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(SYSCLK_ARM_MUX, PWR_CTRL, 2, 0x1, NULL, 124062306a36Sopenharmony_ci CLK_MUX_READ_ONLY), 124162306a36Sopenharmony_ci /* Register 2 read-only muxes with a single control PWR_CTRL[10] */ 124262306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(PERIPH_HCLK_MUX, PWR_CTRL, 10, 0x1, NULL, 124362306a36Sopenharmony_ci CLK_MUX_READ_ONLY), 124462306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(PERIPH_ARM_MUX, PWR_CTRL, 10, 0x1, NULL, 124562306a36Sopenharmony_ci CLK_MUX_READ_ONLY), 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci /* 3 always on gates with a single control PWR_CTRL[0] same as OSC */ 124862306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(PERIPH, PWR_CTRL, 0, CLK_GATE_SET_TO_DISABLE), 124962306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(HCLK, PWR_CTRL, 0, CLK_GATE_SET_TO_DISABLE), 125062306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(ARM, PWR_CTRL, 0, CLK_GATE_SET_TO_DISABLE), 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(ARM_VFP, DEBUG_CTRL, 4, 0), 125362306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(DMA, DMA_CLK_CTRL, 0, 0), 125462306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(DDRAM, HCLKDIV_CTRL, 0x0, BIT(8) | BIT(7), 125562306a36Sopenharmony_ci 0x0, BIT(8) | BIT(7), 0x0, BIT(1) | BIT(0), clk_ddram_ops), 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TIMER0, TIMCLK_CTRL1, 2, 0), 125862306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TIMER1, TIMCLK_CTRL1, 3, 0), 125962306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TIMER2, TIMCLK_CTRL1, 4, 0), 126062306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TIMER3, TIMCLK_CTRL1, 5, 0), 126162306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TIMER4, TIMCLK_CTRL1, 0, 0), 126262306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TIMER5, TIMCLK_CTRL1, 1, 0), 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(SSP0, SSP_CTRL, 0, 0), 126562306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(SSP1, SSP_CTRL, 1, 0), 126662306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(SPI1, SPI_CTRL, 0, 0), 126762306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(SPI2, SPI_CTRL, 4, 0), 126862306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(I2S0, I2S_CTRL, 0, 0), 126962306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(I2S1, I2S_CTRL, 1, 0), 127062306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(I2C1, I2CCLK_CTRL, 0, 0), 127162306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(I2C2, I2CCLK_CTRL, 1, 0), 127262306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(WDOG, TIMCLK_CTRL, 0, 0), 127362306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(HSTIMER, TIMCLK_CTRL, 1, 0), 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(KEY, KEYCLK_CTRL, 0, 0), 127662306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(MCPWM, TIMCLK_CTRL1, 6, 0), 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0), 127962306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL, 128062306a36Sopenharmony_ci CLK_DIVIDER_ONE_BASED), 128162306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0), 128262306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE), 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0), 128562306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL, 128662306a36Sopenharmony_ci CLK_DIVIDER_ONE_BASED), 128762306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0), 128862306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE), 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(UART3_MUX, UART3_CLK_CTRL, 16, 0x1, NULL, 0), 129162306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(UART3_DIV, UART3_CLK_CTRL, 129262306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops), 129362306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(UART3_GATE, UART_CLK_CTRL, 0, 0), 129462306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(UART3, UART3_MUX, UART3_DIV, UART3_GATE), 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(UART4_MUX, UART4_CLK_CTRL, 16, 0x1, NULL, 0), 129762306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(UART4_DIV, UART4_CLK_CTRL, 129862306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops), 129962306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(UART4_GATE, UART_CLK_CTRL, 1, 0), 130062306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(UART4, UART4_MUX, UART4_DIV, UART4_GATE), 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(UART5_MUX, UART5_CLK_CTRL, 16, 0x1, NULL, 0), 130362306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(UART5_DIV, UART5_CLK_CTRL, 130462306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops), 130562306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(UART5_GATE, UART_CLK_CTRL, 2, 0), 130662306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(UART5, UART5_MUX, UART5_DIV, UART5_GATE), 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(UART6_MUX, UART6_CLK_CTRL, 16, 0x1, NULL, 0), 130962306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(UART6_DIV, UART6_CLK_CTRL, 131062306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops), 131162306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(UART6_GATE, UART_CLK_CTRL, 3, 0), 131262306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(UART6, UART6_MUX, UART6_DIV, UART6_GATE), 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(IRDA, IRDA_CLK_CTRL, 131562306a36Sopenharmony_ci 0, 0, 0, 0, 0, 0, lpc32xx_uart_div_ops), 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(TEST1_MUX, TEST_CLK_CTRL, 5, 0x3, 131862306a36Sopenharmony_ci test1_mux_table, 0), 131962306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TEST1_GATE, TEST_CLK_CTRL, 4, 0), 132062306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(TEST1, TEST1_MUX, _NULL, TEST1_GATE), 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(TEST2_MUX, TEST_CLK_CTRL, 1, 0x7, 132362306a36Sopenharmony_ci test2_mux_table, 0), 132462306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(TEST2_GATE, TEST_CLK_CTRL, 0, 0), 132562306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(TEST2, TEST2_MUX, _NULL, TEST2_GATE), 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(SYS, SYSCLK_CTRL, 0, 0x1, NULL, CLK_MUX_READ_ONLY), 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(USB_DIV_DIV, USB_DIV, 0, 4, NULL, 0), 133062306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0), 133162306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE), 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED), 133462306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9), 133562306a36Sopenharmony_ci 0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops), 133662306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE), 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(LCD_DIV, LCDCLK_CTRL, 0, 5, NULL, 0), 133962306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(LCD_GATE, LCDCLK_CTRL, 5, 0), 134062306a36Sopenharmony_ci LPC32XX_DEFINE_COMPOSITE(LCD, _NULL, LCD_DIV, LCD_GATE), 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(MAC, MACCLK_CTRL, 134362306a36Sopenharmony_ci BIT(2) | BIT(1) | BIT(0), BIT(2) | BIT(1) | BIT(0), 134462306a36Sopenharmony_ci BIT(2) | BIT(1) | BIT(0), BIT(2) | BIT(1) | BIT(0), 134562306a36Sopenharmony_ci 0x0, 0x0, clk_mask_ops), 134662306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(SLC, FLASHCLK_CTRL, 134762306a36Sopenharmony_ci BIT(2) | BIT(0), BIT(2) | BIT(0), 0x0, 134862306a36Sopenharmony_ci BIT(0), BIT(1), BIT(2) | BIT(1), clk_mask_ops), 134962306a36Sopenharmony_ci LPC32XX_DEFINE_CLK(MLC, FLASHCLK_CTRL, 135062306a36Sopenharmony_ci BIT(1), BIT(2) | BIT(1), 0x0, BIT(1), 135162306a36Sopenharmony_ci BIT(2) | BIT(0), BIT(2) | BIT(0), clk_mask_ops), 135262306a36Sopenharmony_ci /* 135362306a36Sopenharmony_ci * ADC/TS clock unfortunately cannot be registered as a composite one 135462306a36Sopenharmony_ci * due to a different connection of gate, div and mux, e.g. gating it 135562306a36Sopenharmony_ci * won't mean that the clock is off, if peripheral clock is its parent: 135662306a36Sopenharmony_ci * 135762306a36Sopenharmony_ci * rtc-->[gate]-->| | 135862306a36Sopenharmony_ci * | mux |--> adc/ts 135962306a36Sopenharmony_ci * pclk-->[div]-->| | 136062306a36Sopenharmony_ci * 136162306a36Sopenharmony_ci * Constraints: 136262306a36Sopenharmony_ci * ADC --- resulting clock must be <= 4.5 MHz 136362306a36Sopenharmony_ci * TS --- resulting clock must be <= 400 KHz 136462306a36Sopenharmony_ci */ 136562306a36Sopenharmony_ci LPC32XX_DEFINE_DIV(ADC_DIV, ADCCLK_CTRL1, 0, 8, NULL, 0), 136662306a36Sopenharmony_ci LPC32XX_DEFINE_GATE(ADC_RTC, ADCCLK_CTRL, 0, 0), 136762306a36Sopenharmony_ci LPC32XX_DEFINE_MUX(ADC, ADCCLK_CTRL1, 8, 0x1, NULL, 0), 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci /* USB controller clocks */ 137062306a36Sopenharmony_ci LPC32XX_DEFINE_USB(USB_AHB, 137162306a36Sopenharmony_ci BIT(24), 0x0, BIT(24), BIT(4), 0, clk_usb_ops), 137262306a36Sopenharmony_ci LPC32XX_DEFINE_USB(USB_OTG, 137362306a36Sopenharmony_ci 0x0, 0x0, 0x0, BIT(3), 0, clk_usb_ops), 137462306a36Sopenharmony_ci LPC32XX_DEFINE_USB(USB_I2C, 137562306a36Sopenharmony_ci 0x0, BIT(23), BIT(23), BIT(2), 0, clk_usb_i2c_ops), 137662306a36Sopenharmony_ci LPC32XX_DEFINE_USB(USB_DEV, 137762306a36Sopenharmony_ci BIT(22), 0x0, BIT(22), BIT(1), BIT(0), clk_usb_ops), 137862306a36Sopenharmony_ci LPC32XX_DEFINE_USB(USB_HOST, 137962306a36Sopenharmony_ci BIT(21), 0x0, BIT(21), BIT(0), BIT(1), clk_usb_ops), 138062306a36Sopenharmony_ci}; 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_cistatic struct clk * __init lpc32xx_clk_register(u32 id) 138362306a36Sopenharmony_ci{ 138462306a36Sopenharmony_ci const struct clk_proto_t *lpc32xx_clk = &clk_proto[id]; 138562306a36Sopenharmony_ci struct clk_hw_proto *clk_hw = &clk_hw_proto[id]; 138662306a36Sopenharmony_ci const char *parents[LPC32XX_CLK_PARENTS_MAX]; 138762306a36Sopenharmony_ci struct clk *clk; 138862306a36Sopenharmony_ci unsigned int i; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci for (i = 0; i < lpc32xx_clk->num_parents; i++) 139162306a36Sopenharmony_ci parents[i] = clk_proto[lpc32xx_clk->parents[i]].name; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci pr_debug("%s: derived from '%s', clock type %d\n", lpc32xx_clk->name, 139462306a36Sopenharmony_ci parents[0], clk_hw->type); 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci switch (clk_hw->type) { 139762306a36Sopenharmony_ci case CLK_LPC32XX: 139862306a36Sopenharmony_ci case CLK_LPC32XX_PLL: 139962306a36Sopenharmony_ci case CLK_LPC32XX_USB: 140062306a36Sopenharmony_ci case CLK_MUX: 140162306a36Sopenharmony_ci case CLK_DIV: 140262306a36Sopenharmony_ci case CLK_GATE: 140362306a36Sopenharmony_ci { 140462306a36Sopenharmony_ci struct clk_init_data clk_init = { 140562306a36Sopenharmony_ci .name = lpc32xx_clk->name, 140662306a36Sopenharmony_ci .parent_names = parents, 140762306a36Sopenharmony_ci .num_parents = lpc32xx_clk->num_parents, 140862306a36Sopenharmony_ci .flags = lpc32xx_clk->flags, 140962306a36Sopenharmony_ci .ops = clk_hw->hw0.ops, 141062306a36Sopenharmony_ci }; 141162306a36Sopenharmony_ci struct clk_hw *hw; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (clk_hw->type == CLK_LPC32XX) 141462306a36Sopenharmony_ci hw = &clk_hw->hw0.clk.hw; 141562306a36Sopenharmony_ci else if (clk_hw->type == CLK_LPC32XX_PLL) 141662306a36Sopenharmony_ci hw = &clk_hw->hw0.pll.hw; 141762306a36Sopenharmony_ci else if (clk_hw->type == CLK_LPC32XX_USB) 141862306a36Sopenharmony_ci hw = &clk_hw->hw0.usb_clk.hw; 141962306a36Sopenharmony_ci else if (clk_hw->type == CLK_MUX) 142062306a36Sopenharmony_ci hw = &clk_hw->hw0.mux.hw; 142162306a36Sopenharmony_ci else if (clk_hw->type == CLK_DIV) 142262306a36Sopenharmony_ci hw = &clk_hw->hw0.div.hw; 142362306a36Sopenharmony_ci else if (clk_hw->type == CLK_GATE) 142462306a36Sopenharmony_ci hw = &clk_hw->hw0.gate.hw; 142562306a36Sopenharmony_ci else 142662306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci hw->init = &clk_init; 142962306a36Sopenharmony_ci clk = clk_register(NULL, hw); 143062306a36Sopenharmony_ci break; 143162306a36Sopenharmony_ci } 143262306a36Sopenharmony_ci case CLK_COMPOSITE: 143362306a36Sopenharmony_ci { 143462306a36Sopenharmony_ci struct clk_hw *mux_hw = NULL, *div_hw = NULL, *gate_hw = NULL; 143562306a36Sopenharmony_ci const struct clk_ops *mops = NULL, *dops = NULL, *gops = NULL; 143662306a36Sopenharmony_ci struct clk_hw_proto0 *mux0, *div0, *gate0; 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci mux0 = clk_hw->hw1.mux; 143962306a36Sopenharmony_ci div0 = clk_hw->hw1.div; 144062306a36Sopenharmony_ci gate0 = clk_hw->hw1.gate; 144162306a36Sopenharmony_ci if (mux0) { 144262306a36Sopenharmony_ci mops = mux0->ops; 144362306a36Sopenharmony_ci mux_hw = &mux0->clk.hw; 144462306a36Sopenharmony_ci } 144562306a36Sopenharmony_ci if (div0) { 144662306a36Sopenharmony_ci dops = div0->ops; 144762306a36Sopenharmony_ci div_hw = &div0->clk.hw; 144862306a36Sopenharmony_ci } 144962306a36Sopenharmony_ci if (gate0) { 145062306a36Sopenharmony_ci gops = gate0->ops; 145162306a36Sopenharmony_ci gate_hw = &gate0->clk.hw; 145262306a36Sopenharmony_ci } 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci clk = clk_register_composite(NULL, lpc32xx_clk->name, 145562306a36Sopenharmony_ci parents, lpc32xx_clk->num_parents, 145662306a36Sopenharmony_ci mux_hw, mops, div_hw, dops, 145762306a36Sopenharmony_ci gate_hw, gops, lpc32xx_clk->flags); 145862306a36Sopenharmony_ci break; 145962306a36Sopenharmony_ci } 146062306a36Sopenharmony_ci case CLK_FIXED: 146162306a36Sopenharmony_ci { 146262306a36Sopenharmony_ci struct clk_fixed_rate *fixed = &clk_hw->f; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci clk = clk_register_fixed_rate(NULL, lpc32xx_clk->name, 146562306a36Sopenharmony_ci parents[0], 0, fixed->fixed_rate); 146662306a36Sopenharmony_ci break; 146762306a36Sopenharmony_ci } 146862306a36Sopenharmony_ci default: 146962306a36Sopenharmony_ci clk = ERR_PTR(-EINVAL); 147062306a36Sopenharmony_ci } 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci return clk; 147362306a36Sopenharmony_ci} 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_cistatic void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate) 147662306a36Sopenharmony_ci{ 147762306a36Sopenharmony_ci u32 val; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci regmap_read(clk_regmap, reg, &val); 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci if (!(val & div_mask)) { 148262306a36Sopenharmony_ci val &= ~gate; 148362306a36Sopenharmony_ci val |= BIT(__ffs(div_mask)); 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci regmap_update_bits(clk_regmap, reg, gate | div_mask, val); 148762306a36Sopenharmony_ci} 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_cistatic void __init lpc32xx_clk_init(struct device_node *np) 149062306a36Sopenharmony_ci{ 149162306a36Sopenharmony_ci unsigned int i; 149262306a36Sopenharmony_ci struct clk *clk_osc, *clk_32k; 149362306a36Sopenharmony_ci void __iomem *base = NULL; 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci /* Ensure that parent clocks are available and valid */ 149662306a36Sopenharmony_ci clk_32k = of_clk_get_by_name(np, clk_proto[LPC32XX_CLK_XTAL_32K].name); 149762306a36Sopenharmony_ci if (IS_ERR(clk_32k)) { 149862306a36Sopenharmony_ci pr_err("failed to find external 32KHz clock: %ld\n", 149962306a36Sopenharmony_ci PTR_ERR(clk_32k)); 150062306a36Sopenharmony_ci return; 150162306a36Sopenharmony_ci } 150262306a36Sopenharmony_ci if (clk_get_rate(clk_32k) != 32768) { 150362306a36Sopenharmony_ci pr_err("invalid clock rate of external 32KHz oscillator\n"); 150462306a36Sopenharmony_ci return; 150562306a36Sopenharmony_ci } 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci clk_osc = of_clk_get_by_name(np, clk_proto[LPC32XX_CLK_XTAL].name); 150862306a36Sopenharmony_ci if (IS_ERR(clk_osc)) { 150962306a36Sopenharmony_ci pr_err("failed to find external main oscillator clock: %ld\n", 151062306a36Sopenharmony_ci PTR_ERR(clk_osc)); 151162306a36Sopenharmony_ci return; 151262306a36Sopenharmony_ci } 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci base = of_iomap(np, 0); 151562306a36Sopenharmony_ci if (!base) { 151662306a36Sopenharmony_ci pr_err("failed to map system control block registers\n"); 151762306a36Sopenharmony_ci return; 151862306a36Sopenharmony_ci } 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci clk_regmap = regmap_init_mmio(NULL, base, &lpc32xx_scb_regmap_config); 152162306a36Sopenharmony_ci if (IS_ERR(clk_regmap)) { 152262306a36Sopenharmony_ci pr_err("failed to regmap system control block: %ld\n", 152362306a36Sopenharmony_ci PTR_ERR(clk_regmap)); 152462306a36Sopenharmony_ci iounmap(base); 152562306a36Sopenharmony_ci return; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci /* 152962306a36Sopenharmony_ci * Divider part of PWM and MS clocks requires a quirk to avoid 153062306a36Sopenharmony_ci * a misinterpretation of formally valid zero value in register 153162306a36Sopenharmony_ci * bitfield, which indicates another clock gate. Instead of 153262306a36Sopenharmony_ci * adding complexity to a gate clock ensure that zero value in 153362306a36Sopenharmony_ci * divider clock is never met in runtime. 153462306a36Sopenharmony_ci */ 153562306a36Sopenharmony_ci lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0)); 153662306a36Sopenharmony_ci lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2)); 153762306a36Sopenharmony_ci lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9)); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci for (i = 1; i < LPC32XX_CLK_MAX; i++) { 154062306a36Sopenharmony_ci clk[i] = lpc32xx_clk_register(i); 154162306a36Sopenharmony_ci if (IS_ERR(clk[i])) { 154262306a36Sopenharmony_ci pr_err("failed to register %s clock: %ld\n", 154362306a36Sopenharmony_ci clk_proto[i].name, PTR_ERR(clk[i])); 154462306a36Sopenharmony_ci clk[i] = NULL; 154562306a36Sopenharmony_ci } 154662306a36Sopenharmony_ci } 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci /* Set 48MHz rate of USB PLL clock */ 155162306a36Sopenharmony_ci clk_set_rate(clk[LPC32XX_CLK_USB_PLL], 48000000); 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci /* These two clocks must be always on independently on consumers */ 155462306a36Sopenharmony_ci clk_prepare_enable(clk[LPC32XX_CLK_ARM]); 155562306a36Sopenharmony_ci clk_prepare_enable(clk[LPC32XX_CLK_HCLK]); 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci /* Enable ARM VFP by default */ 155862306a36Sopenharmony_ci clk_prepare_enable(clk[LPC32XX_CLK_ARM_VFP]); 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci /* Disable enabled by default clocks for NAND MLC and SLC */ 156162306a36Sopenharmony_ci clk_mask_disable(&clk_hw_proto[LPC32XX_CLK_SLC].hw0.clk.hw); 156262306a36Sopenharmony_ci clk_mask_disable(&clk_hw_proto[LPC32XX_CLK_MLC].hw0.clk.hw); 156362306a36Sopenharmony_ci} 156462306a36Sopenharmony_ciCLK_OF_DECLARE(lpc32xx_clk, "nxp,lpc3220-clk", lpc32xx_clk_init); 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_cistatic void __init lpc32xx_usb_clk_init(struct device_node *np) 156762306a36Sopenharmony_ci{ 156862306a36Sopenharmony_ci unsigned int i; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci usb_clk_vbase = of_iomap(np, 0); 157162306a36Sopenharmony_ci if (!usb_clk_vbase) { 157262306a36Sopenharmony_ci pr_err("failed to map address range\n"); 157362306a36Sopenharmony_ci return; 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci for (i = 1; i < LPC32XX_USB_CLK_MAX; i++) { 157762306a36Sopenharmony_ci usb_clk[i] = lpc32xx_clk_register(i + LPC32XX_CLK_USB_OFFSET); 157862306a36Sopenharmony_ci if (IS_ERR(usb_clk[i])) { 157962306a36Sopenharmony_ci pr_err("failed to register %s clock: %ld\n", 158062306a36Sopenharmony_ci clk_proto[i].name, PTR_ERR(usb_clk[i])); 158162306a36Sopenharmony_ci usb_clk[i] = NULL; 158262306a36Sopenharmony_ci } 158362306a36Sopenharmony_ci } 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci of_clk_add_provider(np, of_clk_src_onecell_get, &usb_clk_data); 158662306a36Sopenharmony_ci} 158762306a36Sopenharmony_ciCLK_OF_DECLARE(lpc32xx_usb_clk, "nxp,lpc3220-usb-clk", lpc32xx_usb_clk_init); 1588