rtc: Introduce QMSI RTC device driver

This patch introduces the 'QMSI RTC device driver' which is simply a shim
driver based on RTC driver provided by QMSI BSP.

Some config options are independent of the driver implementation used,
so use a consistent name for them. In this case RTC Interrupt number and
Priority use the same config options for both the QMSI and DesignWare
drivers.

In order to enable this driver, the following options should be set:
CONFIG_QMSI_DRIVERS=y
CONFIG_QMSI_INSTALL_PATH="/path/to/libqmsi/directory"
CONFIG_RTC=y
CONFIG_RTC_QMSI=y

Change-Id: I48292406e5472e5786f3b9abbeb71016a273bfec
Signed-off-by: Andre Guedes <andre.guedes@intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
This commit is contained in:
Andre Guedes 2016-01-06 16:59:18 -02:00 committed by Anas Nashif
commit 7b0076a777
8 changed files with 150 additions and 32 deletions

View file

@ -169,11 +169,12 @@ endif
if RTC if RTC
config RTC_IRQ
default 2
if RTC_DW if RTC_DW
config RTC_DW_BASE_ADDR config RTC_DW_BASE_ADDR
default 0xB0000400 default 0xB0000400
config RTC_DW_IRQ
default 2
endif endif
endif endif

View file

@ -190,6 +190,8 @@ endif
endif endif
if RTC if RTC
config RTC_IRQ
default 11
if RTC_DW if RTC_DW
config RTC_DW_CLOCK_GATE config RTC_DW_CLOCK_GATE
def_bool n def_bool n
@ -199,8 +201,6 @@ config RTC_DW_CLOCK_GATE_SUBSYS
default 11 default 11
config RTC_DW_BASE_ADDR config RTC_DW_BASE_ADDR
default 0xB0000400 default 0xB0000400
config RTC_DW_IRQ
default 11
endif endif
endif endif

View file

@ -27,19 +27,39 @@ menuconfig RTC
if RTC if RTC
config RTC_IRQ
int "Interrupt number"
default 0
help
RTC interrupt number
config RTC_IRQ_PRI
int "Interrupt priority"
default 2
help
RTC interrupt priority.
config RTC_DRV_NAME
string "Driver instance name"
default "RTC_0"
depends on RTC
help
RTC driver instance name
config RTC_QMSI
depends on QMSI_DRIVERS
bool "QMSI RTC Driver"
default n
help
Build QMSI RTC driver.
config RTC_DW config RTC_DW
depends on !RTC_QMSI
bool "Build Designware RTC Driver" bool "Build Designware RTC Driver"
default n default n
help help
Designware RTC driver. Designware RTC driver.
config RTC_DW_DRV_NAME
string "Driver instance name"
default "RTC_DW"
depends on RTC_DW
help
Designware RTC driver instance name
config RTC_DW_CLOCK_GATE config RTC_DW_CLOCK_GATE
bool "Enable clock gating" bool "Enable clock gating"
depends on RTC_DW depends on RTC_DW
@ -65,17 +85,4 @@ config RTC_DW_BASE_ADDR
help help
Base address to access RTC DesignWare controller registers Base address to access RTC DesignWare controller registers
config RTC_DW_IRQ
int "Interrupt number"
default 0
depends on RTC_DW
help
DesignWare RTC interrupt number
config RTC_DW_IRQ_PRI
int "Interrupt priority"
default 2
depends on RTC_DW
help
DesignWare RTC interrupt priority.
endif # RTC endif # RTC

View file

@ -1,2 +1,5 @@
ccflags-$(CONFIG_RTC_QMSI) += -I$(CONFIG_QMSI_INSTALL_PATH)/include
obj-$(CONFIG_RTC) += rtc_static_irq_stubs.o obj-$(CONFIG_RTC) += rtc_static_irq_stubs.o
obj-$(CONFIG_RTC_DW) += rtc_dw.o obj-$(CONFIG_RTC_DW) += rtc_dw.o
obj-$(CONFIG_RTC_QMSI) += rtc_qmsi.o

View file

@ -190,13 +190,13 @@ static struct rtc_driver_api funcs = {
}; };
/* IRQ_CONFIG needs the flags variable declared by IRQ_CONNECT_STATIC */ /* IRQ_CONFIG needs the flags variable declared by IRQ_CONNECT_STATIC */
IRQ_CONNECT_STATIC(rtc, CONFIG_RTC_DW_IRQ, IRQ_CONNECT_STATIC(rtc, CONFIG_RTC_IRQ,
CONFIG_RTC_DW_IRQ_PRI, rtc_dw_isr, 0, 0); CONFIG_RTC_IRQ_PRI, rtc_dw_isr, 0, 0);
int rtc_dw_init(struct device *dev) int rtc_dw_init(struct device *dev)
{ {
IRQ_CONFIG(rtc, CONFIG_RTC_DW_IRQ); IRQ_CONFIG(rtc, CONFIG_RTC_IRQ);
irq_enable(CONFIG_RTC_DW_IRQ); irq_enable(CONFIG_RTC_IRQ);
_rtc_dw_int_unmask(); _rtc_dw_int_unmask();
@ -216,7 +216,7 @@ struct rtc_dw_dev_config rtc_dev = {
#endif #endif
}; };
DECLARE_DEVICE_INIT_CONFIG(rtc, CONFIG_RTC_DW_DRV_NAME, DECLARE_DEVICE_INIT_CONFIG(rtc, CONFIG_RTC_DRV_NAME,
&rtc_dw_init, &rtc_dev); &rtc_dw_init, &rtc_dev);
SYS_DEFINE_DEVICE(rtc, &rtc_runtime, SECONDARY, SYS_DEFINE_DEVICE(rtc, &rtc_runtime, SECONDARY,

103
drivers/rtc/rtc_qmsi.c Normal file
View file

@ -0,0 +1,103 @@
/*
* 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 <device.h>
#include <drivers/ioapic.h>
#include <init.h>
#include <nanokernel.h>
#include <rtc.h>
#include "qm_rtc.h"
IRQ_CONNECT_STATIC(rtc, CONFIG_RTC_IRQ, CONFIG_RTC_IRQ_PRI, qm_rtc_isr_0,
0, IOAPIC_EDGE | IOAPIC_HIGH);
static struct device *rtc_qmsi_dev;
static void (*user_callback)(struct device *dev);
static void rtc_qmsi_enable(struct device *dev)
{
clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);
}
static void rtc_qmsi_disable(struct device *dev)
{
clk_periph_disable(CLK_PERIPH_RTC_REGISTER);
}
static void rtc_callback(void)
{
if (user_callback)
user_callback(rtc_qmsi_dev);
}
static int rtc_qmsi_set_config(struct device *dev, struct rtc_config *cfg)
{
qm_rtc_config_t qm_cfg;
qm_cfg.init_val = cfg->init_val;
qm_cfg.alarm_en = cfg->alarm_enable;
qm_cfg.alarm_val = cfg->alarm_val;
qm_cfg.callback = rtc_callback;
user_callback = cfg->cb_fn;
if (qm_rtc_set_config(QM_RTC_0, &qm_cfg) != QM_RC_OK)
return DEV_FAIL;
return DEV_OK;
}
static int rtc_qmsi_set_alarm(struct device *dev, const uint32_t alarm_val)
{
return qm_rtc_set_alarm(QM_RTC_0, alarm_val) == QM_RC_OK ? DEV_OK : DEV_FAIL;
}
static uint32_t rtc_qmsi_read(struct device *dev)
{
return QM_RTC[QM_RTC_0].rtc_ccvr;
}
static struct rtc_driver_api api = {
.enable = rtc_qmsi_enable,
.disable = rtc_qmsi_disable,
.read = rtc_qmsi_read,
.set_config = rtc_qmsi_set_config,
.set_alarm = rtc_qmsi_set_alarm,
};
static int rtc_qmsi_init(struct device *dev)
{
IRQ_CONFIG(rtc, CONFIG_RTC_IRQ);
/* Unmask RTC interrupt */
irq_enable(CONFIG_RTC_IRQ);
/* Route RTC interrupt to Lakemont */
QM_SCSS_INT->int_rtc_mask &= ~BIT(0);
dev->driver_api = &api;
return DEV_OK;
}
DECLARE_DEVICE_INIT_CONFIG(rtc, CONFIG_RTC_DRV_NAME,
&rtc_qmsi_init, NULL);
SYS_DEFINE_DEVICE(rtc, NULL, SECONDARY,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
static struct device *rtc_qmsi_dev = SYS_GET_DEVICE(rtc);

View file

@ -26,6 +26,12 @@
#endif #endif
#endif #endif
#if defined(CONFIG_RTC_QMSI)
#if defined(CONFIG_IOAPIC) || defined(CONFIG_MVIC)
ioapic_mkstub rtc qm_rtc_isr_0 0
#endif
#endif /* CONFIG_RTC_QMSI */
/* externs (internal APIs) */ /* externs (internal APIs) */
GTEXT(_IntEnt) GTEXT(_IntEnt)

View file

@ -20,9 +20,7 @@
#include <rtc.h> #include <rtc.h>
#include <misc/printk.h> #include <misc/printk.h>
#define ALARM (RTC_ALARM_MINUTE / 6) #define ALARM (RTC_ALARM_MINUTE / 6)
#define RTC_DRIVER CONFIG_RTC_DW_DRV_NAME
void test_rtc_interrupt_fn(struct device *rtc_dev) void test_rtc_interrupt_fn(struct device *rtc_dev)
{ {
@ -38,7 +36,7 @@ void main(void)
struct device *rtc_dev; struct device *rtc_dev;
printk("Test RTC driver\n"); printk("Test RTC driver\n");
rtc_dev = device_get_binding(RTC_DRIVER); rtc_dev = device_get_binding(CONFIG_RTC_DRV_NAME);
config.init_val = 0; config.init_val = 0;
config.alarm_enable = 1; config.alarm_enable = 1;