diff --git a/drivers/Kconfig b/drivers/Kconfig index e5258c1dbb8..1bc2f59d59a 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -57,4 +57,6 @@ source "drivers/rtc/Kconfig" source "drivers/watchdog/Kconfig" +source "drivers/clock_control/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 0d547920817..2e19bc4fdb8 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_ADC) += adc/ obj-$(CONFIG_ETHERNET) += ethernet/ obj-$(CONFIG_WATCHDOG) += watchdog/ obj-$(CONFIG_RTC) += rtc/ +obj-$(CONFIG_CLOCK_CONTROL) += clock_control/ diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig new file mode 100644 index 00000000000..8eae7cb4ad7 --- /dev/null +++ b/drivers/clock_control/Kconfig @@ -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" diff --git a/drivers/clock_control/Makefile b/drivers/clock_control/Makefile new file mode 100644 index 00000000000..293cb817919 --- /dev/null +++ b/drivers/clock_control/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_CLOCK_CONTROL_QUARK_SE) += quark_se_clock_control.o diff --git a/drivers/clock_control/quark_se_clock_control.c b/drivers/clock_control/quark_se_clock_control.c new file mode 100644 index 00000000000..552feed19b7 --- /dev/null +++ b/drivers/clock_control/quark_se_clock_control.c @@ -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 +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#ifndef CONFIG_CLOCK_DEBUG +#define DBG(...) {; } +#else +#if defined(CONFIG_STDOUT_CONSOLE) +#include +#define DBG printf +#else +#include +#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 */ diff --git a/include/clock_control.h b/include/clock_control.h new file mode 100644 index 00000000000..b48f1ddfcb9 --- /dev/null +++ b/include/clock_control.h @@ -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 +#include +#include + +#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__ */ diff --git a/include/drivers/clock_control/quark_se_clock_control.h b/include/drivers/clock_control/quark_se_clock_control.h new file mode 100644 index 00000000000..639b80e5252 --- /dev/null +++ b/include/drivers/clock_control/quark_se_clock_control.h @@ -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__ */