diff options
Diffstat (limited to 'drivers/clk/stm32/clk-stm32mp13.c')
-rw-r--r-- | drivers/clk/stm32/clk-stm32mp13.c | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c new file mode 100644 index 000000000000..a2a6bbb4ace5 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32mp13.c @@ -0,0 +1,520 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics. + */ + +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/stm32mp13-clks.h> +#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 struct clock_config stm32mp13_clock_cfg[] = { +}; + +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); |