linux-stable/drivers/clk/stm32/clk-stm32mp13.c
Gabriel Fernandez 637cee5ffc clk: stm32: Introduce STM32MP13 RCC drivers (Reset Clock Controller)
This driver manages Reset and Clock of STM32MP13 soc.
It uses a clk-stm32-core module to manage stm32 gate, mux and divider
for STM32MP13 and for new future soc.

All gates, muxes, dividers are identify by an index and information
are stored in array (register address, shift, with, flags...)
This is useful when we have two clocks with the same gate or
when one mux manages two output clocks.

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@foss.st.com>
Link: https://lore.kernel.org/r/20220516070600.7692-3-gabriel.fernandez@foss.st.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
2022-05-20 21:07:48 -07:00

520 lines
14 KiB
C

// 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);