Commit a49f5fbf authored by Raptor Engineering Development Team's avatar Raptor Engineering Development Team
Browse files

Add intiial driver for simple PWM peripheral

parent d662e59b
......@@ -33,6 +33,7 @@ target_sources(app PRIVATE
${KESTREL_SOURCE_DIR}/src/flash_filesystem.c
${KESTREL_SOURCE_DIR}/src/fsi.c
${KESTREL_SOURCE_DIR}/src/kestrel.c
${KESTREL_SOURCE_DIR}/src/simple_pwm.c
${KESTREL_SOURCE_DIR}/src/webservice.c
${KESTREL_SOURCE_DIR}/src/webportal.c
${KESTREL_SOURCE_DIR}/src/direct_uart.c
......
......@@ -32,6 +32,7 @@ LOG_MODULE_REGISTER(kestrel_core, LOG_LEVEL_DBG);
#include "aquila.h"
#include "ipmi_bt.h"
#include "opencores_i2c.h"
#include "simple_pwm.h"
#include "kestrel.h"
......@@ -3455,6 +3456,10 @@ int kestrel_init(void)
// initialize_i2c_master((uint8_t*)I2CMASTER3_BASE, 100000);
initialize_i2c_master((uint8_t *)I2CMASTER4_BASE, 100000);
#ifdef SIMPLEPWM_BASE
initialize_pwm_controller(SIMPLEPWM_BASE);
#endif
// Check for Aquila core presence
if ((read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_DEVICE_ID_HIGH) == AQUILA_LPC_DEVICE_ID_HIGH) &&
(read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_DEVICE_ID_LOW) == AQUILA_LPC_DEVICE_ID_LOW))
......
// © 2020 - 2021 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
#include <logging/log.h>
LOG_MODULE_REGISTER(kestrel_pwm, LOG_LEVEL_DBG);
#include "simple_pwm.h"
#include "utility.h"
#include <generated/csr.h>
#include <generated/soc.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define KESTREL_LOG(...) LOG_INF(__VA_ARGS__)
int initialize_pwm_controller(uint8_t *base_address)
{
KESTREL_LOG("Configuring PWM controller at address %p...", base_address);
if ((*((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_DEVICE_ID_HIGH)) != SIMPLE_PWM_DEVICE_ID_HIGH) ||
(*((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_DEVICE_ID_LOW)) != SIMPLE_PWM_DEVICE_ID_LOW))
{
return -1;
}
uint32_t opencores_spi_version = *((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_DEVICE_VERSION));
KESTREL_LOG("OpenCores I2C master found, device version %0d.%0d.%d",
(opencores_spi_version >> SIMPLE_PWM_VERSION_MAJOR_SHIFT) & SIMPLE_PWM_VERSION_MAJOR_MASK,
(opencores_spi_version >> SIMPLE_PWM_VERSION_MINOR_SHIFT) & SIMPLE_PWM_VERSION_MINOR_MASK,
(opencores_spi_version >> SIMPLE_PWM_VERSION_PATCH_SHIFT) & SIMPLE_PWM_VERSION_PATCH_MASK);
{
KESTREL_LOG("Disabling PWM outputs");
set_pwm_value(base_address, 0, 0x00);
set_pwm_value(base_address, 1, 0x00);
set_pwm_value(base_address, 2, 0x00);
set_pwm_value(base_address, 3, 0x00);
return 0;
}
return 1;
}
int set_pwm_value(uint8_t *base_address, uint8_t channel, uint8_t value)
{
uint32_t dword;
dword = *((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_PWM_CTL));
dword &= ~(0xff << (channel * 8));
dword |= (value & 0xff) << (channel * 8);
*((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_PWM_CTL)) = dword;
return 0;
}
uint8_t get_pwm_value(uint8_t *base_address, uint8_t channel)
{
return (*((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_PWM_CTL)) >> (channel * 8)) & 0xff;
}
int get_tach_value(uint8_t *base_address, uint8_t channel)
{
uint16_t raw_tach_value = 0;
int rps = 0;
int rpm = 0;
if ((channel == 0) || (channel == 1))
{
raw_tach_value = (*((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_TACH_01)) >> ((channel & 0x1) * 16)) & 0xffff;
}
else if ((channel == 2) || (channel == 3))
{
raw_tach_value = (*((volatile uint32_t *)(base_address + SIMPLE_PWM_MASTER_TACH_23)) >> ((channel & 0x1) * 16)) & 0xffff;
}
// Compute RPM
rps = raw_tach_value * SIMPLE_PWM_TACH_SAMPLE_RATE_HZ;
rpm = rps * 60;
return rpm;
}
// © 2020 - 2021 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
#ifndef _SIMPLE_PWM_H
#define _SIMPLE_PWM_H
#include <stdint.h>
#define SIMPLE_PWM_MASTER_DEVICE_ID_LOW 0x0
#define SIMPLE_PWM_MASTER_DEVICE_ID_HIGH 0x4
#define SIMPLE_PWM_MASTER_DEVICE_VERSION 0x8
#define SIMPLE_PWM_MASTER_PWM_CTL 0xc
#define SIMPLE_PWM_MASTER_TACH_01 0x10
#define SIMPLE_PWM_MASTER_TACH_23 0x14
#define SIMPLE_PWM_DEVICE_ID_HIGH 0x4932434d
#define SIMPLE_PWM_DEVICE_ID_LOW 0x4f50574d
#define SIMPLE_PWM_VERSION_MAJOR_MASK 0xffff
#define SIMPLE_PWM_VERSION_MAJOR_SHIFT 16
#define SIMPLE_PWM_VERSION_MINOR_MASK 0xff
#define SIMPLE_PWM_VERSION_MINOR_SHIFT 8
#define SIMPLE_PWM_VERSION_PATCH_MASK 0xff
#define SIMPLE_PWM_VERSION_PATCH_SHIFT 0
#define SIMPLE_PWM_MASTER_PWM_0_MASK 0xff
#define SIMPLE_PWM_MASTER_PWM_0_SHIFT 0
#define SIMPLE_PWM_MASTER_PWM_1_MASK 0xff
#define SIMPLE_PWM_MASTER_PWM_1_SHIFT 8
#define SIMPLE_PWM_MASTER_PWM_2_MASK 0xff
#define SIMPLE_PWM_MASTER_PWM_2_SHIFT 16
#define SIMPLE_PWM_MASTER_PWM_3_MASK 0xff
#define SIMPLE_PWM_MASTER_PWM_3_SHIFT 24
#define SIMPLE_PWM_MASTER_TACH_0_MASK 0xffff
#define SIMPLE_PWM_MASTER_TACH_0_SHIFT 0
#define SIMPLE_PWM_MASTER_TACH_1_MASK 0xffff
#define SIMPLE_PWM_MASTER_TACH_1_SHIFT 16
#define SIMPLE_PWM_MASTER_TACH_2_MASK 0xffff
#define SIMPLE_PWM_MASTER_TACH_2_SHIFT 0
#define SIMPLE_PWM_MASTER_TACH_3_MASK 0xffff
#define SIMPLE_PWM_MASTER_TACH_3_SHIFT 16
// This is currently hard-wired into the HDL to save die area
#define SIMPLE_PWM_TACH_SAMPLE_RATE_HZ 5
int initialize_pwm_controller(uint8_t *base_address);
int set_pwm_value(uint8_t *base_address, uint8_t channel, uint8_t value);
uint8_t get_pwm_value(uint8_t *base_address, uint8_t channel);
int get_tach_value(uint8_t *base_address, uint8_t channel);
#endif // _SIMPLE_PWM_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment