// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) STMicroelectronics 2022 - All Rights Reserved * Author: Gabriel Fernandez for STMicroelectronics. */ #include #include #include #include #include #include "clk-stm32-core.h" #include "stm32mp13_rcc.h" #define RCC_CLR_OFFSET 0x4 /* STM32 Gates definition */ enum enum_gate_cfg { GATE_MCO1, GATE_MCO2, GATE_DBGCK, GATE_TRACECK, GATE_DDRC1, GATE_DDRC1LP, GATE_DDRPHYC, GATE_DDRPHYCLP, GATE_DDRCAPB, GATE_DDRCAPBLP, GATE_AXIDCG, GATE_DDRPHYCAPB, GATE_DDRPHYCAPBLP, GATE_TIM2, GATE_TIM3, GATE_TIM4, GATE_TIM5, GATE_TIM6, GATE_TIM7, GATE_LPTIM1, GATE_SPI2, GATE_SPI3, GATE_USART3, GATE_UART4, GATE_UART5, GATE_UART7, GATE_UART8, GATE_I2C1, GATE_I2C2, GATE_SPDIF, GATE_TIM1, GATE_TIM8, GATE_SPI1, GATE_USART6, GATE_SAI1, GATE_SAI2, GATE_DFSDM, GATE_ADFSDM, GATE_FDCAN, GATE_LPTIM2, GATE_LPTIM3, GATE_LPTIM4, GATE_LPTIM5, GATE_VREF, GATE_DTS, GATE_PMBCTRL, GATE_HDP, GATE_SYSCFG, GATE_DCMIPP, GATE_DDRPERFM, GATE_IWDG2APB, GATE_USBPHY, GATE_STGENRO, GATE_LTDC, GATE_RTCAPB, GATE_TZC, GATE_ETZPC, GATE_IWDG1APB, GATE_BSEC, GATE_STGENC, GATE_USART1, GATE_USART2, GATE_SPI4, GATE_SPI5, GATE_I2C3, GATE_I2C4, GATE_I2C5, GATE_TIM12, GATE_TIM13, GATE_TIM14, GATE_TIM15, GATE_TIM16, GATE_TIM17, GATE_DMA1, GATE_DMA2, GATE_DMAMUX1, GATE_DMA3, GATE_DMAMUX2, GATE_ADC1, GATE_ADC2, GATE_USBO, GATE_TSC, GATE_GPIOA, GATE_GPIOB, GATE_GPIOC, GATE_GPIOD, GATE_GPIOE, GATE_GPIOF, GATE_GPIOG, GATE_GPIOH, GATE_GPIOI, GATE_PKA, GATE_SAES, GATE_CRYP1, GATE_HASH1, GATE_RNG1, GATE_BKPSRAM, GATE_AXIMC, GATE_MCE, GATE_ETH1CK, GATE_ETH1TX, GATE_ETH1RX, GATE_ETH1MAC, GATE_FMC, GATE_QSPI, GATE_SDMMC1, GATE_SDMMC2, GATE_CRC1, GATE_USBH, GATE_ETH2CK, GATE_ETH2TX, GATE_ETH2RX, GATE_ETH2MAC, GATE_ETH1STP, GATE_ETH2STP, GATE_MDMA, GATE_NB }; #define _CFG_GATE(_id, _offset, _bit_idx, _offset_clr)\ [(_id)] = {\ .offset = (_offset),\ .bit_idx = (_bit_idx),\ .set_clr = (_offset_clr),\ } #define CFG_GATE(_id, _offset, _bit_idx)\ _CFG_GATE(_id, _offset, _bit_idx, 0) #define CFG_GATE_SETCLR(_id, _offset, _bit_idx)\ _CFG_GATE(_id, _offset, _bit_idx, RCC_CLR_OFFSET) static struct stm32_gate_cfg stm32mp13_gates[] = { CFG_GATE(GATE_MCO1, RCC_MCO1CFGR, 12), CFG_GATE(GATE_MCO2, RCC_MCO2CFGR, 12), CFG_GATE(GATE_DBGCK, RCC_DBGCFGR, 8), CFG_GATE(GATE_TRACECK, RCC_DBGCFGR, 9), CFG_GATE(GATE_DDRC1, RCC_DDRITFCR, 0), CFG_GATE(GATE_DDRC1LP, RCC_DDRITFCR, 1), CFG_GATE(GATE_DDRPHYC, RCC_DDRITFCR, 4), CFG_GATE(GATE_DDRPHYCLP, RCC_DDRITFCR, 5), CFG_GATE(GATE_DDRCAPB, RCC_DDRITFCR, 6), CFG_GATE(GATE_DDRCAPBLP, RCC_DDRITFCR, 7), CFG_GATE(GATE_AXIDCG, RCC_DDRITFCR, 8), CFG_GATE(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9), CFG_GATE(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10), CFG_GATE_SETCLR(GATE_TIM2, RCC_MP_APB1ENSETR, 0), CFG_GATE_SETCLR(GATE_TIM3, RCC_MP_APB1ENSETR, 1), CFG_GATE_SETCLR(GATE_TIM4, RCC_MP_APB1ENSETR, 2), CFG_GATE_SETCLR(GATE_TIM5, RCC_MP_APB1ENSETR, 3), CFG_GATE_SETCLR(GATE_TIM6, RCC_MP_APB1ENSETR, 4), CFG_GATE_SETCLR(GATE_TIM7, RCC_MP_APB1ENSETR, 5), CFG_GATE_SETCLR(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9), CFG_GATE_SETCLR(GATE_SPI2, RCC_MP_APB1ENSETR, 11), CFG_GATE_SETCLR(GATE_SPI3, RCC_MP_APB1ENSETR, 12), CFG_GATE_SETCLR(GATE_USART3, RCC_MP_APB1ENSETR, 15), CFG_GATE_SETCLR(GATE_UART4, RCC_MP_APB1ENSETR, 16), CFG_GATE_SETCLR(GATE_UART5, RCC_MP_APB1ENSETR, 17), CFG_GATE_SETCLR(GATE_UART7, RCC_MP_APB1ENSETR, 18), CFG_GATE_SETCLR(GATE_UART8, RCC_MP_APB1ENSETR, 19), CFG_GATE_SETCLR(GATE_I2C1, RCC_MP_APB1ENSETR, 21), CFG_GATE_SETCLR(GATE_I2C2, RCC_MP_APB1ENSETR, 22), CFG_GATE_SETCLR(GATE_SPDIF, RCC_MP_APB1ENSETR, 26), CFG_GATE_SETCLR(GATE_TIM1, RCC_MP_APB2ENSETR, 0), CFG_GATE_SETCLR(GATE_TIM8, RCC_MP_APB2ENSETR, 1), CFG_GATE_SETCLR(GATE_SPI1, RCC_MP_APB2ENSETR, 8), CFG_GATE_SETCLR(GATE_USART6, RCC_MP_APB2ENSETR, 13), CFG_GATE_SETCLR(GATE_SAI1, RCC_MP_APB2ENSETR, 16), CFG_GATE_SETCLR(GATE_SAI2, RCC_MP_APB2ENSETR, 17), CFG_GATE_SETCLR(GATE_DFSDM, RCC_MP_APB2ENSETR, 20), CFG_GATE_SETCLR(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21), CFG_GATE_SETCLR(GATE_FDCAN, RCC_MP_APB2ENSETR, 24), CFG_GATE_SETCLR(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0), CFG_GATE_SETCLR(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1), CFG_GATE_SETCLR(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2), CFG_GATE_SETCLR(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3), CFG_GATE_SETCLR(GATE_VREF, RCC_MP_APB3ENSETR, 13), CFG_GATE_SETCLR(GATE_DTS, RCC_MP_APB3ENSETR, 16), CFG_GATE_SETCLR(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17), CFG_GATE_SETCLR(GATE_HDP, RCC_MP_APB3ENSETR, 20), CFG_GATE_SETCLR(GATE_SYSCFG, RCC_MP_NS_APB3ENSETR, 0), CFG_GATE_SETCLR(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1), CFG_GATE_SETCLR(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8), CFG_GATE_SETCLR(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15), CFG_GATE_SETCLR(GATE_USBPHY, RCC_MP_APB4ENSETR, 16), CFG_GATE_SETCLR(GATE_STGENRO, RCC_MP_APB4ENSETR, 20), CFG_GATE_SETCLR(GATE_LTDC, RCC_MP_NS_APB4ENSETR, 0), CFG_GATE_SETCLR(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8), CFG_GATE_SETCLR(GATE_TZC, RCC_MP_APB5ENSETR, 11), CFG_GATE_SETCLR(GATE_ETZPC, RCC_MP_APB5ENSETR, 13), CFG_GATE_SETCLR(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15), CFG_GATE_SETCLR(GATE_BSEC, RCC_MP_APB5ENSETR, 16), CFG_GATE_SETCLR(GATE_STGENC, RCC_MP_APB5ENSETR, 20), CFG_GATE_SETCLR(GATE_USART1, RCC_MP_APB6ENSETR, 0), CFG_GATE_SETCLR(GATE_USART2, RCC_MP_APB6ENSETR, 1), CFG_GATE_SETCLR(GATE_SPI4, RCC_MP_APB6ENSETR, 2), CFG_GATE_SETCLR(GATE_SPI5, RCC_MP_APB6ENSETR, 3), CFG_GATE_SETCLR(GATE_I2C3, RCC_MP_APB6ENSETR, 4), CFG_GATE_SETCLR(GATE_I2C4, RCC_MP_APB6ENSETR, 5), CFG_GATE_SETCLR(GATE_I2C5, RCC_MP_APB6ENSETR, 6), CFG_GATE_SETCLR(GATE_TIM12, RCC_MP_APB6ENSETR, 7), CFG_GATE_SETCLR(GATE_TIM13, RCC_MP_APB6ENSETR, 8), CFG_GATE_SETCLR(GATE_TIM14, RCC_MP_APB6ENSETR, 9), CFG_GATE_SETCLR(GATE_TIM15, RCC_MP_APB6ENSETR, 10), CFG_GATE_SETCLR(GATE_TIM16, RCC_MP_APB6ENSETR, 11), CFG_GATE_SETCLR(GATE_TIM17, RCC_MP_APB6ENSETR, 12), CFG_GATE_SETCLR(GATE_DMA1, RCC_MP_AHB2ENSETR, 0), CFG_GATE_SETCLR(GATE_DMA2, RCC_MP_AHB2ENSETR, 1), CFG_GATE_SETCLR(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2), CFG_GATE_SETCLR(GATE_DMA3, RCC_MP_AHB2ENSETR, 3), CFG_GATE_SETCLR(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4), CFG_GATE_SETCLR(GATE_ADC1, RCC_MP_AHB2ENSETR, 5), CFG_GATE_SETCLR(GATE_ADC2, RCC_MP_AHB2ENSETR, 6), CFG_GATE_SETCLR(GATE_USBO, RCC_MP_AHB2ENSETR, 8), CFG_GATE_SETCLR(GATE_TSC, RCC_MP_AHB4ENSETR, 15), CFG_GATE_SETCLR(GATE_GPIOA, RCC_MP_NS_AHB4ENSETR, 0), CFG_GATE_SETCLR(GATE_GPIOB, RCC_MP_NS_AHB4ENSETR, 1), CFG_GATE_SETCLR(GATE_GPIOC, RCC_MP_NS_AHB4ENSETR, 2), CFG_GATE_SETCLR(GATE_GPIOD, RCC_MP_NS_AHB4ENSETR, 3), CFG_GATE_SETCLR(GATE_GPIOE, RCC_MP_NS_AHB4ENSETR, 4), CFG_GATE_SETCLR(GATE_GPIOF, RCC_MP_NS_AHB4ENSETR, 5), CFG_GATE_SETCLR(GATE_GPIOG, RCC_MP_NS_AHB4ENSETR, 6), CFG_GATE_SETCLR(GATE_GPIOH, RCC_MP_NS_AHB4ENSETR, 7), CFG_GATE_SETCLR(GATE_GPIOI, RCC_MP_NS_AHB4ENSETR, 8), CFG_GATE_SETCLR(GATE_PKA, RCC_MP_AHB5ENSETR, 2), CFG_GATE_SETCLR(GATE_SAES, RCC_MP_AHB5ENSETR, 3), CFG_GATE_SETCLR(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4), CFG_GATE_SETCLR(GATE_HASH1, RCC_MP_AHB5ENSETR, 5), CFG_GATE_SETCLR(GATE_RNG1, RCC_MP_AHB5ENSETR, 6), CFG_GATE_SETCLR(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8), CFG_GATE_SETCLR(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16), CFG_GATE_SETCLR(GATE_MCE, RCC_MP_AHB6ENSETR, 1), CFG_GATE_SETCLR(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7), CFG_GATE_SETCLR(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8), CFG_GATE_SETCLR(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9), CFG_GATE_SETCLR(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10), CFG_GATE_SETCLR(GATE_FMC, RCC_MP_AHB6ENSETR, 12), CFG_GATE_SETCLR(GATE_QSPI, RCC_MP_AHB6ENSETR, 14), CFG_GATE_SETCLR(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16), CFG_GATE_SETCLR(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17), CFG_GATE_SETCLR(GATE_CRC1, RCC_MP_AHB6ENSETR, 20), CFG_GATE_SETCLR(GATE_USBH, RCC_MP_AHB6ENSETR, 24), CFG_GATE_SETCLR(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27), CFG_GATE_SETCLR(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28), CFG_GATE_SETCLR(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29), CFG_GATE_SETCLR(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30), CFG_GATE_SETCLR(GATE_ETH1STP, RCC_MP_AHB6LPENSETR, 11), CFG_GATE_SETCLR(GATE_ETH2STP, RCC_MP_AHB6LPENSETR, 31), CFG_GATE_SETCLR(GATE_MDMA, RCC_MP_NS_AHB6ENSETR, 0), }; /* STM32 Divivers definition */ enum enum_div_cfg { DIV_RTC, DIV_HSI, DIV_MCO1, DIV_MCO2, DIV_TRACE, DIV_ETH1PTP, DIV_ETH2PTP, DIV_NB }; static const struct clk_div_table ck_trace_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, { 0 }, }; #define CFG_DIV(_id, _offset, _shift, _width, _flags, _table, _ready)\ [(_id)] = {\ .offset = (_offset),\ .shift = (_shift),\ .width = (_width),\ .flags = (_flags),\ .table = (_table),\ .ready = (_ready),\ } static const struct stm32_div_cfg stm32mp13_dividers[DIV_NB] = { CFG_DIV(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_RDY), CFG_DIV(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL, DIV_NO_RDY), CFG_DIV(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL, DIV_NO_RDY), CFG_DIV(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table, DIV_NO_RDY), CFG_DIV(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL, DIV_NO_RDY), CFG_DIV(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL, DIV_NO_RDY), }; /* STM32 Muxes definition */ enum enum_mux_cfg { MUX_ADC1, MUX_ADC2, MUX_DCMIPP, MUX_ETH1, MUX_ETH2, MUX_FDCAN, MUX_FMC, MUX_I2C12, MUX_I2C3, MUX_I2C4, MUX_I2C5, MUX_LPTIM1, MUX_LPTIM2, MUX_LPTIM3, MUX_LPTIM45, MUX_MCO1, MUX_MCO2, MUX_QSPI, MUX_RNG1, MUX_SAES, MUX_SAI1, MUX_SAI2, MUX_SDMMC1, MUX_SDMMC2, MUX_SPDIF, MUX_SPI1, MUX_SPI23, MUX_SPI4, MUX_SPI5, MUX_STGEN, MUX_UART1, MUX_UART2, MUX_UART4, MUX_UART6, MUX_UART35, MUX_UART78, MUX_USBO, MUX_USBPHY, MUX_NB }; #define _CFG_MUX(_id, _offset, _shift, _witdh, _ready, _flags)\ [_id] = {\ .offset = (_offset),\ .shift = (_shift),\ .width = (_witdh),\ .ready = (_ready),\ .flags = (_flags),\ } #define CFG_MUX(_id, _offset, _shift, _witdh)\ _CFG_MUX(_id, _offset, _shift, _witdh, MUX_NO_RDY, 0) static const struct stm32_mux_cfg stm32mp13_muxes[] = { CFG_MUX(MUX_I2C12, RCC_I2C12CKSELR, 0, 3), CFG_MUX(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3), CFG_MUX(MUX_SPI23, RCC_SPI2S23CKSELR, 0, 3), CFG_MUX(MUX_UART35, RCC_UART35CKSELR, 0, 3), CFG_MUX(MUX_UART78, RCC_UART78CKSELR, 0, 3), CFG_MUX(MUX_ADC1, RCC_ADC12CKSELR, 0, 2), CFG_MUX(MUX_ADC2, RCC_ADC12CKSELR, 2, 2), CFG_MUX(MUX_DCMIPP, RCC_DCMIPPCKSELR, 0, 2), CFG_MUX(MUX_ETH1, RCC_ETH12CKSELR, 0, 2), CFG_MUX(MUX_ETH2, RCC_ETH12CKSELR, 8, 2), CFG_MUX(MUX_FDCAN, RCC_FDCANCKSELR, 0, 2), CFG_MUX(MUX_I2C3, RCC_I2C345CKSELR, 0, 3), CFG_MUX(MUX_I2C4, RCC_I2C345CKSELR, 3, 3), CFG_MUX(MUX_I2C5, RCC_I2C345CKSELR, 6, 3), CFG_MUX(MUX_LPTIM1, RCC_LPTIM1CKSELR, 0, 3), CFG_MUX(MUX_LPTIM2, RCC_LPTIM23CKSELR, 0, 3), CFG_MUX(MUX_LPTIM3, RCC_LPTIM23CKSELR, 3, 3), CFG_MUX(MUX_MCO1, RCC_MCO1CFGR, 0, 3), CFG_MUX(MUX_MCO2, RCC_MCO2CFGR, 0, 3), CFG_MUX(MUX_RNG1, RCC_RNG1CKSELR, 0, 2), CFG_MUX(MUX_SAES, RCC_SAESCKSELR, 0, 2), CFG_MUX(MUX_SAI1, RCC_SAI1CKSELR, 0, 3), CFG_MUX(MUX_SAI2, RCC_SAI2CKSELR, 0, 3), CFG_MUX(MUX_SPDIF, RCC_SPDIFCKSELR, 0, 2), CFG_MUX(MUX_SPI1, RCC_SPI2S1CKSELR, 0, 3), CFG_MUX(MUX_SPI4, RCC_SPI45CKSELR, 0, 3), CFG_MUX(MUX_SPI5, RCC_SPI45CKSELR, 3, 3), CFG_MUX(MUX_STGEN, RCC_STGENCKSELR, 0, 2), CFG_MUX(MUX_UART1, RCC_UART12CKSELR, 0, 3), CFG_MUX(MUX_UART2, RCC_UART12CKSELR, 3, 3), CFG_MUX(MUX_UART4, RCC_UART4CKSELR, 0, 3), CFG_MUX(MUX_UART6, RCC_UART6CKSELR, 0, 3), CFG_MUX(MUX_USBO, RCC_USBCKSELR, 4, 1), CFG_MUX(MUX_USBPHY, RCC_USBCKSELR, 0, 2), CFG_MUX(MUX_FMC, RCC_FMCCKSELR, 0, 2), CFG_MUX(MUX_QSPI, RCC_QSPICKSELR, 0, 2), CFG_MUX(MUX_SDMMC1, RCC_SDMMC12CKSELR, 0, 3), CFG_MUX(MUX_SDMMC2, RCC_SDMMC12CKSELR, 3, 3), }; static const char * const eth12_src[] = { "pll4_p", "pll3_q" }; static struct clk_stm32_mux ck_ker_eth1 = { .mux_id = MUX_ETH1, .hw.init = CLK_HW_INIT_PARENTS("ck_ker_eth1", eth12_src, &clk_stm32_mux_ops, CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), }; static const struct clock_config stm32mp13_clock_cfg[] = { STM32_MUX_CFG(NO_ID, ck_ker_eth1), }; static u16 stm32mp13_cpt_gate[GATE_NB]; static struct clk_stm32_clock_data stm32mp13_clock_data = { .gate_cpt = stm32mp13_cpt_gate, .gates = stm32mp13_gates, .muxes = stm32mp13_muxes, .dividers = stm32mp13_dividers, }; static const struct stm32_rcc_match_data stm32mp13_data = { .tab_clocks = stm32mp13_clock_cfg, .num_clocks = ARRAY_SIZE(stm32mp13_clock_cfg), .clock_data = &stm32mp13_clock_data, .maxbinding = STM32MP1_LAST_CLK, .clear_offset = RCC_CLR_OFFSET, }; static const struct of_device_id stm32mp13_match_data[] = { { .compatible = "st,stm32mp13-rcc", .data = &stm32mp13_data, }, { } }; MODULE_DEVICE_TABLE(of, stm32mp13_match_data); static int stm32mp1_rcc_init(struct device *dev) { void __iomem *rcc_base; int ret = -ENOMEM; rcc_base = of_iomap(dev_of_node(dev), 0); if (!rcc_base) { dev_err(dev, "%pOFn: unable to map resource", dev_of_node(dev)); goto out; } ret = stm32_rcc_init(dev, stm32mp13_match_data, rcc_base); out: if (ret) { if (rcc_base) iounmap(rcc_base); of_node_put(dev_of_node(dev)); } return ret; } static int get_clock_deps(struct device *dev) { static const char * const clock_deps_name[] = { "hsi", "hse", "csi", "lsi", "lse", }; size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name); struct clk **clk_deps; int i; clk_deps = devm_kzalloc(dev, deps_size, GFP_KERNEL); if (!clk_deps) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) { struct clk *clk = of_clk_get_by_name(dev_of_node(dev), clock_deps_name[i]); if (IS_ERR(clk)) { if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT) return PTR_ERR(clk); } else { /* Device gets a reference count on the clock */ clk_deps[i] = devm_clk_get(dev, __clk_get_name(clk)); clk_put(clk); } } return 0; } static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int ret = get_clock_deps(dev); if (!ret) ret = stm32mp1_rcc_init(dev); return ret; } static int stm32mp1_rcc_clocks_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *child, *np = dev_of_node(dev); for_each_available_child_of_node(np, child) of_clk_del_provider(child); return 0; } static struct platform_driver stm32mp13_rcc_clocks_driver = { .driver = { .name = "stm32mp13_rcc", .of_match_table = stm32mp13_match_data, }, .probe = stm32mp1_rcc_clocks_probe, .remove = stm32mp1_rcc_clocks_remove, }; static int __init stm32mp13_clocks_init(void) { return platform_driver_register(&stm32mp13_rcc_clocks_driver); } core_initcall(stm32mp13_clocks_init);