-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: clock_control: Introduce revision 3 of CCM driver
This commit introduces a new version of the CCM driver. The purpose of this is to make the CCM driver usable by all NXP SoCs despite the changes in the HAL API. With this driver, each SoC will have to define its own clock tree and a few common operations such as clock enable/disable, set_rate and get_rate. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
- Loading branch information
1 parent
a7498c3
commit f4a6785
Showing
6 changed files
with
282 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Copyright 2023 NXP | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config CLOCK_CONTROL_MCUX_CCM_REV3 | ||
bool "MCUX CCM Rev3 driver" | ||
default y | ||
depends on DT_HAS_NXP_IMX_CCM_REV3_ENABLED | ||
help | ||
Enable support for mcux ccm rev3 driver. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright 2023 NXP | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <zephyr/sys/util.h> | ||
#include <zephyr/drivers/clock_control.h> | ||
#include <zephyr/drivers/clock_control/clock_control_mcux_ccm_rev3.h> | ||
|
||
/* Used for driver binding */ | ||
#define DT_DRV_COMPAT nxp_imx_ccm_rev3 | ||
|
||
extern struct imx_ccm_data mcux_ccm_data; | ||
extern struct imx_ccm_config mcux_ccm_config; | ||
|
||
static int mcux_ccm_on_off(const struct device *dev, | ||
clock_control_subsys_t sys, bool on) | ||
{ | ||
uint32_t clock_name; | ||
const struct imx_ccm_config *cfg; | ||
|
||
clock_name = (uintptr_t)sys; | ||
cfg = dev->config; | ||
|
||
/* validate clock_name */ | ||
if (clock_name >= cfg->clock_config->clock_num) | ||
return -EINVAL; | ||
|
||
return imx_ccm_clock_on_off(dev, &cfg->clock_config->clocks[clock_name], on); | ||
} | ||
|
||
static int mcux_ccm_on(const struct device *dev, clock_control_subsys_t sys) | ||
{ | ||
return mcux_ccm_on_off(dev, sys, true); | ||
} | ||
|
||
static int mcux_ccm_off(const struct device *dev, clock_control_subsys_t sys) | ||
{ | ||
return mcux_ccm_on_off(dev, sys, false); | ||
} | ||
|
||
static int mcux_ccm_get_rate(const struct device *dev, | ||
clock_control_subsys_t sys, uint32_t *rate) | ||
{ | ||
uint32_t clock_name, returned_rate; | ||
const struct imx_ccm_config *cfg; | ||
|
||
clock_name = (uintptr_t)sys; | ||
cfg = dev->config; | ||
|
||
/* validate clock_name */ | ||
if (clock_name >= cfg->clock_config->clock_num) | ||
return -EINVAL; | ||
|
||
returned_rate = imx_ccm_clock_get_rate(dev, &cfg->clock_config->clocks[clock_name]); | ||
|
||
if (returned_rate > 0) { | ||
*rate = returned_rate; | ||
return 0; | ||
} else { | ||
return returned_rate; | ||
} | ||
} | ||
|
||
static int mcux_ccm_set_rate(const struct device *dev, | ||
clock_control_subsys_t sys, clock_control_subsys_rate_t rate) | ||
{ | ||
uint32_t clock_name, requested_rate; | ||
const struct imx_ccm_config *cfg; | ||
|
||
clock_name = (uintptr_t)sys; | ||
requested_rate = (uintptr_t)rate; | ||
cfg = dev->config; | ||
|
||
/* validate clock_name */ | ||
if (clock_name >= cfg->clock_config->clock_num) | ||
return -EINVAL; | ||
|
||
return imx_ccm_clock_set_rate(dev, &cfg->clock_config->clocks[clock_name], requested_rate); | ||
} | ||
|
||
static int mcux_ccm_init(const struct device *dev) | ||
{ | ||
return imx_ccm_init(dev); | ||
} | ||
|
||
static const struct clock_control_driver_api mcux_ccm_driver_api = { | ||
.on = mcux_ccm_on, | ||
.off = mcux_ccm_off, | ||
.get_rate = mcux_ccm_get_rate, | ||
.set_rate = mcux_ccm_set_rate, | ||
}; | ||
|
||
/* there's only one CCM per SoC */ | ||
DEVICE_DT_INST_DEFINE(0, | ||
&mcux_ccm_init, | ||
NULL, | ||
&mcux_ccm_data, &mcux_ccm_config, | ||
PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, | ||
&mcux_ccm_driver_api); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Copyright 2023 NXP | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
description: i.MX CCM (Clock Controller Module) Rev 3 IP node | ||
|
||
compatible: "nxp,imx-ccm-rev3" | ||
|
||
include: [clock-controller.yaml, base.yaml] | ||
|
||
properties: | ||
reg: | ||
required: true | ||
|
||
"#clock-cells": | ||
const: 2 | ||
|
||
clock-cells: | ||
- name | ||
- freq |
149 changes: 149 additions & 0 deletions
149
include/zephyr/drivers/clock_control/clock_control_mcux_ccm_rev3.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
/* | ||
* Copyright 2023 NXP | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_MCUX_CCM_H_ | ||
#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_MCUX_CCM_H_ | ||
|
||
#include <stdint.h> | ||
#include <zephyr/device.h> | ||
|
||
#define IMX_CCM_MAX_SOURCES 4 | ||
|
||
#define IMX_CCM_FIXED_FREQ(src) ((src).source.fixed.freq) | ||
#define IMX_CCM_PLL_MAX_FREQ(src) ((src).source.pll.max_freq) | ||
#define IMX_CCM_RATE_LIMIT(src) \ | ||
((src).type == IMX_CCM_TYPE_FIXED ? \ | ||
IMX_CCM_FIXED_FREQ(src) : IMX_CCM_PLL_MAX_FREQ(src)) | ||
|
||
enum imx_ccm_clock_state { | ||
IMX_CCM_CLOCK_STATE_INIT = 0, /* initial state - clock may be gated or not */ | ||
IMX_CCM_CLOCK_STATE_GATED, /* clock is gated */ | ||
IMX_CCM_CLOCK_STATE_UNGATED, /* clock is not gated */ | ||
}; | ||
|
||
enum imx_ccm_type { | ||
IMX_CCM_TYPE_FIXED = 1, | ||
IMX_CCM_TYPE_PLL, | ||
IMX_CCM_TYPE_MAX, | ||
}; | ||
|
||
struct imx_ccm_fixed { | ||
char *name; | ||
uint32_t id; | ||
uint32_t freq; | ||
}; | ||
|
||
struct imx_ccm_pll { | ||
char *name; | ||
uint32_t id; | ||
uint32_t max_freq; /* maximum allowed frequency */ | ||
uint32_t offset; /* offset from PLL regmap */ | ||
}; | ||
|
||
struct imx_ccm_source { | ||
enum imx_ccm_type type; /* source type - fixed or PLL */ | ||
union { | ||
struct imx_ccm_fixed fixed; | ||
struct imx_ccm_pll pll; | ||
} source; | ||
}; | ||
|
||
struct imx_ccm_clock_root { | ||
char *name; | ||
uint32_t id; | ||
struct imx_ccm_source sources[IMX_CCM_MAX_SOURCES]; | ||
uint32_t source_num; | ||
}; | ||
|
||
struct imx_ccm_clock { | ||
char *name; | ||
uint32_t id; | ||
struct imx_ccm_clock_root root; | ||
|
||
uint32_t lpcg_regmap_phys; | ||
uint32_t lpcg_regmap_size; | ||
mm_reg_t lpcg_regmap; | ||
|
||
uint32_t state; | ||
}; | ||
|
||
/* there are a few possible restrictions regarding the clock array: | ||
* | ||
* 1) The index of the clock sources needs to match the | ||
* MUX value. | ||
* e.g: | ||
* The clock root called lpuartx_clock_root has | ||
* the following possible MUX values: | ||
* 00 => PLL0 | ||
* 01 => PLL1 | ||
* 10 => PLL2 | ||
* 11 => PLL3 | ||
* This means that the clock root structure needs | ||
* to be defined as follows: | ||
* struct imx_ccm_clock_root root = { | ||
* .name = "some_name", | ||
* .id = ID_FROM_NXP_HAL, | ||
* .sources = {PLL0, PLL1, PLL2, PLL3}, | ||
* .source_num = 4, | ||
* } | ||
* * note: this restriction is optional as some developers may choose not to | ||
* follow it for their SoC. | ||
* | ||
* | ||
* 2) The macros defined in zephyr/clock/soc_name_ccm.h need to match the indexes | ||
* from the clock array. | ||
* e.g: lpuart1_clock is found at index 5 in the clock array. This means | ||
* that SOC_NAME_LPUART1_CLOCK needs to have value 5. | ||
* | ||
* * note: this restriction is mandatory as it's used in the CCM driver. | ||
* | ||
* 3) The ID value from a clock IP/root/source needs to be a value from the NXP HAL. | ||
* * note: this restriction is optional as some developers may choose not | ||
* to follow it for their SoC. | ||
*/ | ||
struct imx_ccm_clock_config { | ||
uint32_t clock_num; | ||
struct imx_ccm_clock *clocks; | ||
}; | ||
|
||
struct imx_ccm_config { | ||
struct imx_ccm_clock_config *clock_config; | ||
|
||
uint32_t regmap_phys; | ||
uint32_t regmap_size; | ||
|
||
uint32_t pll_regmap_phys; | ||
uint32_t pll_regmap_size; | ||
}; | ||
|
||
|
||
struct imx_ccm_data { | ||
mm_reg_t regmap; | ||
mm_reg_t pll_regmap; | ||
|
||
uint32_t ipc_handle; | ||
}; | ||
|
||
/* disable/enable a given clock | ||
* | ||
* it's up to the user of the clock control API to | ||
* make sure that the sequence of operations is valid. | ||
*/ | ||
int imx_ccm_clock_on_off(const struct device *dev, struct imx_ccm_clock *clk, bool on); | ||
|
||
/* get the frequency of a given clock */ | ||
int imx_ccm_clock_get_rate(const struct device *dev, struct imx_ccm_clock *clk); | ||
|
||
/* set the rate of a clock. | ||
* | ||
* if successful, the function will return the new rate which | ||
* may differ from the requested rate. | ||
*/ | ||
int imx_ccm_clock_set_rate(const struct device *dev, struct imx_ccm_clock *clk, uint32_t rate); | ||
|
||
int imx_ccm_init(const struct device *dev); | ||
|
||
#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_MCUX_CCM_H_ */ |