1/* 2 * Copyright 2019, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#pragma once 14 15#include <platsupport/timer.h> 16 17#include <utils/util.h> 18#include <stdint.h> 19#include <stdbool.h> 20 21/* The input frequence is 0.5 of the CPU frequency which is 1GHz by default */ 22#define PWM_INPUT_FREQ (500*1000*1000) 23#define PWM0_PADDR 0x10020000 24#define PWM1_PADDR 0x10021000 25 26#define PWM0_INTERRUPT0 42 27#define PWM0_INTERRUPT1 43 28#define PWM0_INTERRUPT2 44 29#define PWM0_INTERRUPT3 45 30 31#define PWM1_INTERRUPT0 46 32#define PWM1_INTERRUPT1 47 33#define PWM1_INTERRUPT2 48 34#define PWM1_INTERRUPT3 49 35 36/** 37 * When used in UPCOUNTER, pwm_handle_irq needs to be called on each interrupt 38 * to handle the overflow. This device doesn't seem to have a way to tell that 39 * an overflow happened other than by the delivery of an IRQ. This means that 40 * if pwm_get_time is called before pwm_handle_irq the time could be incorrect. 41 */ 42typedef enum PWM_MODE { 43 TIMEOUT, 44 UPCOUNTER, 45} pwm_mode_t; 46 47typedef struct { 48 /* vaddr pwm is mapped to */ 49 void *vaddr; 50 pwm_mode_t mode; 51} pwm_config_t; 52 53/* Memory map for pwm */ 54struct pwm_map { 55 uint32_t pwmcfg; 56 uint32_t res0; 57 uint32_t pwmcount; 58 uint32_t res1; 59 uint32_t pwms; 60 uint32_t res2; 61 uint32_t res3; 62 uint32_t res4; 63 uint32_t pwmcmp0; 64 uint32_t pwmcmp1; 65 uint32_t pwmcmp2; 66 uint32_t pwmcmp3; 67}; 68 69typedef struct pwm { 70 volatile struct pwm_map *pwm_map; 71 uint64_t time_h; 72 pwm_mode_t mode; 73} pwm_t; 74 75static UNUSED timer_properties_t pwm_properties = { 76 .upcounter = true, 77 .bit_width = 31, 78 .irqs = 4, 79 .periodic_timeouts = true, 80 .relative_timeouts = true, 81 .absolute_timeouts = false, 82 .timeouts = true, 83}; 84 85int pwm_start(pwm_t *pwm); 86int pwm_stop(pwm_t *pwm); 87void pwm_handle_irq(pwm_t *pwm, uint32_t irq); 88uint64_t pwm_get_time(pwm_t *pwm); 89int pwm_set_timeout(pwm_t *pwm, uint64_t ns, bool periodic); 90int pwm_init(pwm_t *pwm, pwm_config_t config); 91