diff --git a/MAINTAINERS b/MAINTAINERS index 790f853472d..12f2fdd13ce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -141,6 +141,7 @@ S: Supported F: arch/nios2/ F: include/arch/nios2/ F: drivers/serial/uart_altera_jtag.c +F: drivers/timer/altera_avalon_timer.c NORDIC MDK M: Carles Cufi diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index a5114e3121e..dd3f42694a2 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -141,14 +141,15 @@ config CORTEX_M_SYSTICK This module implements a kernel device driver for the Cortex-M processor SYSTICK timer and provides the standard "system clock driver" interfaces. -config NIOS2_AVALON_TIMER - bool "Nios II Avalon Interval Timer" +config ALTERA_AVALON_TIMER + bool "Altera Avalon Interval Timer" default y depends on NIOS2 help - This module implements a kernel device driver for the Nios II Avalon - Interval Timer as described in the Embedded IP documentation. It - provides the standard "system clock driver" interfaces. + This module implements a kernel device driver for the Altera Avalon + Interval Timer as described in the Embedded IP documentation, for use + with Nios II and possibly other Altera soft CPUs. It provides the + standard "system clock driver" interfaces. config SYSTEM_CLOCK_DISABLE bool "API to disable system clock" diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index cf5037fd0d4..d1b440b825d 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -1,7 +1,7 @@ obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_LOAPIC_TIMER) += loapic_timer.o obj-$(CONFIG_ARCV2_TIMER) += arcv2_timer0.o -obj-$(CONFIG_NIOS2_AVALON_TIMER) += nios2_avalon_timer.o +obj-$(CONFIG_ALTERA_AVALON_TIMER) += altera_avalon_timer.o _CORTEX_M_SYSTICK_AND_GDB_INFO_yy = y obj-$(CONFIG_CORTEX_M_SYSTICK) += cortex_m_systick.o diff --git a/drivers/timer/altera_avalon_timer.c b/drivers/timer/altera_avalon_timer.c new file mode 100644 index 00000000000..8062df953d9 --- /dev/null +++ b/drivers/timer/altera_avalon_timer.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016 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 + +/* STATUS register */ +#define ALTERA_AVALON_TIMER_STATUS_REG 0 +#define ALTERA_AVALON_TIMER_STATUS_TO_MSK (0x1) +#define ALTERA_AVALON_TIMER_STATUS_TO_OFST (0) +#define ALTERA_AVALON_TIMER_STATUS_RUN_MSK (0x2) +#define ALTERA_AVALON_TIMER_STATUS_RUN_OFST (1) + +/* CONTROL register */ +#define ALTERA_AVALON_TIMER_CONTROL_REG 1 +#define ALTERA_AVALON_TIMER_CONTROL_ITO_MSK (0x1) +#define ALTERA_AVALON_TIMER_CONTROL_ITO_OFST (0) +#define ALTERA_AVALON_TIMER_CONTROL_CONT_MSK (0x2) +#define ALTERA_AVALON_TIMER_CONTROL_CONT_OFST (1) +#define ALTERA_AVALON_TIMER_CONTROL_START_MSK (0x4) +#define ALTERA_AVALON_TIMER_CONTROL_START_OFST (2) +#define ALTERA_AVALON_TIMER_CONTROL_STOP_MSK (0x8) +#define ALTERA_AVALON_TIMER_CONTROL_STOP_OFST (3) + +/* Period and SnapShot Register for COUNTER_SIZE = 32 */ +/*----------------------------------------------------*/ +/* PERIODL register */ +#define ALTERA_AVALON_TIMER_PERIODL_REG 2 +#define ALTERA_AVALON_TIMER_PERIODL_MSK (0xFFFF) +#define ALTERA_AVALON_TIMER_PERIODL_OFST (0) + +/* PERIODH register */ +#define ALTERA_AVALON_TIMER_PERIODH_REG 3 +#define ALTERA_AVALON_TIMER_PERIODH_MSK (0xFFFF) +#define ALTERA_AVALON_TIMER_PERIODH_OFST (0) + +/* SNAPL register */ +#define ALTERA_AVALON_TIMER_SNAPL_REG 4 +#define ALTERA_AVALON_TIMER_SNAPL_MSK (0xFFFF) +#define ALTERA_AVALON_TIMER_SNAPL_OFST (0) + +/* SNAPH register */ +#define ALTERA_AVALON_TIMER_SNAPH_REG 5 +#define ALTERA_AVALON_TIMER_SNAPH_MSK (0xFFFF) +#define ALTERA_AVALON_TIMER_SNAPH_OFST (0) + +static uint32_t accumulated_cycle_count; + +static uint32_t get_snapshot(void) +{ +#if TIMER_0_SNAPSHOT + uint32_t snap, s1, s2; + int key; + + key = irq_lock(); + + /* Writing any data to one of the snapshot registers populates all + * of them with the value of the counter. The data written is ignored + */ + _nios2_reg_write((void *)TIMER_0_BASE, ALTERA_AVALON_TIMER_SNAPL_REG, + 1); + + s1 = _nios2_reg_read((void *)TIMER_0_BASE, + ALTERA_AVALON_TIMER_SNAPL_REG) & + ALTERA_AVALON_TIMER_SNAPL_MSK; + s2 = _nios2_reg_read((void *)TIMER_0_BASE, + ALTERA_AVALON_TIMER_SNAPH_REG) & + ALTERA_AVALON_TIMER_SNAPH_MSK; + + irq_unlock(key); + + snap = s1 | (s2 << 16); + + return sys_clock_hw_cycles_per_tick - snap; +#else + return 0; +#endif +} + + +static void timer_irq_handler(void *unused) +{ + ARG_UNUSED(unused); + + /* Clear the interrupt */ + _nios2_reg_write((void *)TIMER_0_BASE, ALTERA_AVALON_TIMER_STATUS_REG, + 0); + accumulated_cycle_count += sys_clock_hw_cycles_per_tick; + + _sys_clock_tick_announce(); +} + + +#ifdef CONFIG_TICKLESS_IDLE +#error "Tickless idle not yet implemented for Avalon timer" +#endif + + +int _sys_clock_driver_init(struct device *device) +{ + ARG_UNUSED(device); + +#if TIMER_0_FIXED_PERIOD +#error "Can't set timer period!" +#else + _nios2_reg_write((void *)TIMER_0_BASE, ALTERA_AVALON_TIMER_PERIODL_REG, + sys_clock_hw_cycles_per_tick & 0xFFFF); + _nios2_reg_write((void *)TIMER_0_BASE, ALTERA_AVALON_TIMER_PERIODH_REG, + (sys_clock_hw_cycles_per_tick >> 16) & 0xFFFF); +#endif + + IRQ_CONNECT(TIMER_0_IRQ, 0, timer_irq_handler, NULL, 0); + irq_enable(TIMER_0_IRQ); + + /* Initial configuration: Generate interrupts, run continuously, + * start running + */ + _nios2_reg_write((void *)TIMER_0_BASE, ALTERA_AVALON_TIMER_CONTROL_REG, + ALTERA_AVALON_TIMER_CONTROL_ITO_MSK | + ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | + ALTERA_AVALON_TIMER_CONTROL_START_MSK); + return 0; +} + + +/** + * + * @brief Read the platform's timer hardware + * + * This routine returns the current time in terms of timer hardware clock + * cycles. + * + * @return up counter of elapsed clock cycles + */ +uint32_t sys_cycle_get_32(void) +{ + return accumulated_cycle_count + get_snapshot(); +} + diff --git a/drivers/timer/nios2_avalon_timer.c b/drivers/timer/nios2_avalon_timer.c deleted file mode 100644 index 6e4b38922bb..00000000000 --- a/drivers/timer/nios2_avalon_timer.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016 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 - -int _sys_clock_driver_init(struct device *device) -{ - ARG_UNUSED(device); - - /* STUB */ - - return 0; -} - -/** - * - * @brief Read the platform's timer hardware - * - * This routine returns the current time in terms of timer hardware clock - * cycles. - * - * @return up counter of elapsed clock cycles - */ -uint32_t sys_cycle_get_32(void) -{ - /* STUB */ - return 0; -} -