clock: add Quark SE clock control

Quark SE provides various clock controllers through its SCSS block.
Peripheral, external, sensor, and others.

This current drivers provides only the clock gating capability, for
peripheral, external and sensor. But it could support divider and more
other features once defined in the generic API.

Note: such clock has _nothing_ to do with a Real Time Clock (RTC).
An RTC provide clock timing like a watch would do. Here the clock
controller is about circuit clocking.

Change-Id: I1a365ae730dfc6be7686271f7fbb693e64a6ff6f
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2015-11-21 21:16:01 -05:00 committed by Anas Nashif
commit 714dd9786b
7 changed files with 376 additions and 0 deletions

View file

@ -57,4 +57,6 @@ source "drivers/rtc/Kconfig"
source "drivers/watchdog/Kconfig" source "drivers/watchdog/Kconfig"
source "drivers/clock_control/Kconfig"
endmenu endmenu

View file

@ -20,3 +20,4 @@ obj-$(CONFIG_ADC) += adc/
obj-$(CONFIG_ETHERNET) += ethernet/ obj-$(CONFIG_ETHERNET) += ethernet/
obj-$(CONFIG_WATCHDOG) += watchdog/ obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_RTC) += rtc/ obj-$(CONFIG_RTC) += rtc/
obj-$(CONFIG_CLOCK_CONTROL) += clock_control/

View file

@ -0,0 +1,87 @@
# Kconfig - Clock controller driver configuration options
#
# Copyright (c) 2015 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Clock controller drivers
#
menuconfig CLOCK_CONTROL
bool
prompt "Hardware clock controller support"
default n
help
Enable support for hardware clock controller. Such hardware can
provide clock for other subsystem, and thus can be also used for
power efficiency by controlling their clock. Note that this has
nothing to do with RTC.
config CLOCK_CONTROL_DEBUG
bool
prompt "Hardware clock controller drivers debug output"
depends on CLOCK_CONTROL
default n
config CLOCK_CONTROL_QUARK_SE
bool
prompt "Quark SE Clock controller support"
depends on CLOCK_CONTROL && PLATFORM_QUARK_SE_X86
default n
help
Enable support for the Quark SE clock driver.
config CLOCK_CONTROL_QUARK_SE_PERIPHERAL
bool
prompt "Quark SE peripheral clock support"
depends on CLOCK_CONTROL_QUARK_SE
default n
help
Enable support for Quark SE peripheral clock which controls the
clock of I2C, SPI, GPIO controllers and more.
config CLOCK_CONTROL_QUARK_SE_PERIPHERAL_DRV_NAME
string
prompt "Quark SE peripheral clock device name"
depends on CLOCK_CONTROL_QUARK_SE_PERIPHERAL
default "clk_peripheral"
config CLOCK_CONTROL_QUARK_SE_EXTERNAL
bool
prompt "Quark SE external clock support"
depends on CLOCK_CONTROL_QUARK_SE
default n
help
Enable support for Quark SE external sub-system clock.
config CLOCK_CONTROL_QUARK_SE_EXTERNAL_DRV_NAME
string
prompt "Quark SE external clock device name"
depends on CLOCK_CONTROL_QUARK_SE_PERIPHERAL
default "clk_external"
config CLOCK_CONTROL_QUARK_SE_SENSOR
bool
prompt "Quark SE sensor clock support"
depends on CLOCK_CONTROL_QUARK_SE
default n
help
Enable support for Quark SE sensor sub-system clock.
config CLOCK_CONTROL_QUARK_SE_SENSOR_DRV_NAME
string
prompt "Quark SE sensor clock device name"
depends on CLOCK_CONTROL_QUARK_SE_PERIPHERAL
default "clk_sensor"

View file

@ -0,0 +1 @@
obj-$(CONFIG_CLOCK_CONTROL_QUARK_SE) += quark_se_clock_control.o

View file

@ -0,0 +1,138 @@
/* quark_se_clock_control.c - Clock controller driver for Quark SE */
/*
* Copyright (c) 2015 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <nanokernel.h>
#include <arch/cpu.h>
#include <misc/__assert.h>
#include <board.h>
#include <device.h>
#include <init.h>
#include <sys_io.h>
#include <clock_control.h>
#include <clock_control/quark_se_clock_control.h>
#ifndef CONFIG_CLOCK_DEBUG
#define DBG(...) {; }
#else
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define DBG printf
#else
#include <misc/printk.h>
#define DBG printk
#endif /* CONFIG_STDOUT_CONSOLE */
#endif /* CONFIG_CLOCK_DEBUG */
struct quark_se_clock_control_config {
uint32_t base_address;
};
static inline int quark_se_clock_control_on(struct device *dev,
clock_control_subsys_t sub_system)
{
struct quark_se_clock_control_config *info = dev->config->config_info;
uint32_t subsys = POINTER_TO_INT(sub_system);
if (sub_system == CLOCK_CONTROL_SUBSYS_ALL) {
DBG("Enabling all clock gates on dev %p\n", dev);
sys_write32(0xffffffff, info->base_address);
return DEV_OK;
}
DBG("Enabling clock gate on dev %p subsystem %u\n", dev, subsys);
return sys_test_and_set_bit(info->base_address, subsys);
}
static inline int quark_se_clock_control_off(struct device *dev,
clock_control_subsys_t sub_system)
{
struct quark_se_clock_control_config *info = dev->config->config_info;
uint32_t subsys = POINTER_TO_INT(sub_system);
if (sub_system == CLOCK_CONTROL_SUBSYS_ALL) {
DBG("Disabling all clock gates on dev %p\n", dev);
sys_write32(0x00000000, info->base_address);
return DEV_OK;
}
DBG("clock gate on dev %p subsystem %u\n", dev, subsys);
return sys_test_and_clear_bit(info->base_address, subsys);
}
static struct clock_control_driver_api quark_se_clock_control_api = {
.on = quark_se_clock_control_on,
.off = quark_se_clock_control_off
};
int quark_se_clock_control_init(struct device *dev)
{
dev->driver_api = &quark_se_clock_control_api;
DBG("Quark Se clock controller driver initialized on device: %p\n",
dev);
return DEV_OK;
}
#ifdef CONFIG_CLOCK_CONTROL_QUARK_SE_PERIPHERAL
struct quark_se_clock_control_config clock_quark_se_peripheral_config = {
.base_address = CLOCK_PERIPHERAL_BASE_ADDR
};
DECLARE_DEVICE_INIT_CONFIG(clock_quark_se_peripheral,
CONFIG_CLOCK_CONTROL_QUARK_SE_PERIPHERAL_DRV_NAME,
&quark_se_clock_control_init,
&clock_quark_se_peripheral_config);
pre_kernel_early_init(clock_quark_se_peripheral, NULL);
#endif /* CONFIG_CLOCK_CONTROL_QUARK_SE_PERIPHERAL */
#ifdef CONFIG_CLOCK_CONTROL_QUARK_SE_EXTERNAL
struct quark_se_clock_control_config clock_quark_se_external_config = {
.base_address = CLOCK_EXTERNAL_BASE_ADDR
};
DECLARE_DEVICE_INIT_CONFIG(clock_quark_se_external,
CONFIG_CLOCK_CONTROL_QUARK_SE_EXTERNAL_DRV_NAME,
&quark_se_clock_control_init,
&clock_quark_se_external_config);
pre_kernel_early_init(clock_quark_se_external, NULL);
#endif /* CONFIG_CLOCK_CONTROL_QUARK_SE_EXTERNAL */
#ifdef CONFIG_CLOCK_CONTROL_QUARK_SE_SENSOR
struct quark_se_clock_control_config clock_quark_se_sensor_config = {
.base_address = CLOCK_SENSOR_BASE_ADDR
};
DECLARE_DEVICE_INIT_CONFIG(clock_quark_se_sensor,
CONFIG_CLOCK_CONTROL_QUARK_SE_SENSOR_DRV_NAME,
&quark_se_clock_control_init,
&clock_quark_se_sensor_config);
pre_kernel_early_init(clock_quark_se_sensor, NULL);
#endif /* CONFIG_CLOCK_CONTROL_QUARK_SE_SENSOR */

83
include/clock_control.h Normal file
View file

@ -0,0 +1,83 @@
/* clock_control.h - public clock controller driver API */
/*
* Copyright (c) 2015 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CLOCK_CONTROL_H__
#define __CLOCK_CONTROL_H__
#include <stdint.h>
#include <stddef.h>
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Clock control API */
/* Used to select all subsystem of a clock controller */
#define CLOCK_CONTROL_SUBSYS_ALL NULL
/**
* clock_control_subsys_t is a type to identify a clock controller sub-system.
* Such data pointed is opaque and relevant only to the clock controller
* driver instance being used.
*/
typedef void *clock_control_subsys_t;
typedef int (*clock_control)(struct device *dev, clock_control_subsys_t sys);
struct clock_control_driver_api {
clock_control on;
clock_control off;
};
/**
* @brief Enable the clock of a sub-system controlled by the device
* @param dev Pointer to the device structure for the clock controller driver
* instance
* @param sys A pointer to an opaque data representing the sub-system
*/
static inline int clock_control_on(struct device *dev,
clock_control_subsys_t sys)
{
struct clock_control_driver_api *api;
api = (struct clock_control_driver_api *)dev->driver_api;
return api->on(dev, sys);
}
/**
* @brief Disable the clock of a sub-system controlled by the device
* @param dev Pointer to the device structure for the clock controller driver
* instance
* @param sys A pointer to an opaque data representing the sub-system
*/
static inline int clock_control_off(struct device *dev,
clock_control_subsys_t sys)
{
struct clock_control_driver_api *api;
api = (struct clock_control_driver_api *)dev->driver_api;
return api->off(dev, sys);
}
#ifdef __cplusplus
}
#endif
#endif /* __CLOCK_CONTROL_H__ */

View file

@ -0,0 +1,64 @@
/* quark_se_clock_control.h - Clock controller header for Quark SE */
/*
* Copyright (c) 2015 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __QUARK_SE_CLOCK_CONTROL_H__
#define __QUARK_SE_CLOCK_CONTROL_H__
enum quark_se_peripheral_clocks {
QUARK_SE_PERIPH_PCLK_EN = 0,
QUARK_SE_CCU_PERIPH_PCLK_EN,
QUARK_SE_CCU_I2C_M0_PCLK_EN,
QUARK_SE_CCU_I2C_M1_PCLK_EN,
QUARK_SE_CCU_SPI_S_PCLK_EN,
QUARK_SE_CCU_SPI_M0_PCLK_EN,
QUARK_SE_CCU_SPI_M1_PCLK_EN,
QUARK_SE_CCU_GPIO_INTR_PCLK_EN,
QUARK_SE_CCU_PERIPH_GPIO_DB_PCLK_EN,
QUARK_SE_CCU_I2S_PCLK_EN,
QUARK_SE_CCU_WDT_PCLK_EN_SW,
QUARK_SE_CCU_RTC_PCLK_EN_SW,
QUARK_SE_CCU_PWM_PCLK_EN_SW,
QUARK_SE_CCU_GPIO_PCLK_EN_SW,
QUARK_SE_CCU_SPI_M0_PCLK_EN_SW,
QUARK_SE_CCU_SPI_M1_PCLK_EN_SW,
QUARK_SE_CCU_SPI_PCLK_EN_SW,
QUARK_SE_CCU_UARTA_PCLK_EN_SW,
QUARK_SE_CCU_UARTB_PCLK_EN_SW,
QUARK_SE_CCU_I2C_M0_PCLK_EN_SW,
QUARK_SE_CCU_I2C_M1_PCLK_EN_SW,
QUARK_SE_CCU_I2S_PCLK_EN_SW,
};
enum quark_se_external_clocks {
QUARK_SE_CCU_EXT_RTC_EN = 0,
QUARK_SE_CCU_EXT_CLK_EN,
QUARK_SE_CCU_EXT_CLK_DIV_EN,
};
enum quark_se_sensor_clocks {
QUARK_SE_CCU_SENSOR_CLK_EN = 0,
QUARK_SE_CCU_SS_I2C_M0_CLK_EN,
QUARK_SE_CCU_SS_I2C_M1_CLK_EN,
QUARK_SE_CCU_SS_SPI_M0_CLK_EN,
QUARK_SE_CCU_SS_SPI_M1_CLK_EN,
QUARK_SE_CCU_SS_GPIO_INTR_CLK_EN,
QUARK_SE_CCU_SS_GPIO_DB_CLK_EN,
QUARK_SE_CCU_ADC_CLK_EN,
};
#endif /* __QUARK_SE_CLOCK_CONTROL_H__ */