Commit 02339b0e authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Add PWM block

parent f6e5b259
......@@ -15,12 +15,63 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _INCLUDE_BLOCK_AM335X_ADC_
#define _INCLUDE_BLOCK_AM335X_ADC_
#ifndef _INCLUDE_AM335X_
#define _INCLUDE_AM335X_
#include <inttypes.h>
#include <unistd.h>
#define AM335X_ADC_BASE 0x44e0d000
#define AM335X_ADC_SIZE 0x00002000
#define AM335X_PWMSS0_BASE 0x48300000
#define AM335X_PWMSS1_BASE 0x48302000
#define AM335X_PWMSS2_BASE 0x48304000
#define AM335X_PWMSS_SIZE 0x00001000
#define AM335X_PWMSS_REG_IDVER 0x000
#define AM335X_PWMSS_IDVER_SCHEME_GET(x) (((x) & 0xc0000000) >> 30)
#define AM335X_PWMSS_IDVER_FUNC_GET(x) (((x) & 0x0fff0000) >> 16)
#define AM335X_PWMSS_IDVER_FUNC 0x000
#define AM335X_PWMSS_IDVER_X_MAJOR_GET(x) (((x) & 0x00000700) >> 8)
#define AM335X_PWMSS_IDVER_Y_MINOR_GET(x) (((x) & 0x0000001f) )
#define AM335X_PWMSS_REG_SYSCONFIG 0x004
#define AM335X_PWMSS_REG_CLKCONFIG 0x008
#define AM335X_PWMSS_REG_CLKSTATUS 0x00c
#define AM335X_PWMSS_REG_EPWM_TBCTL 0x200
#define AM335X_PWMSS_REG_EPWM_TBSTS 0x202
#define AM335X_PWMSS_REG_EPWM_TBPHSHR 0x204
#define AM335X_PWMSS_REG_EPWM_TBPHS 0x206
#define AM335X_PWMSS_REG_EPWM_TBCNT 0x208
#define AM335X_PWMSS_REG_EPWM_TBPRD 0x20a
#define AM335X_PWMSS_REG_EPWM_CMPCTL 0x20e
#define AM335X_PWMSS_REG_EPWM_CMPAHR 0x210
#define AM335X_PWMSS_REG_EPWM_CMPA 0x212
#define AM335X_PWMSS_REG_EPWM_CMPB 0x214
#define AM335X_PWMSS_REG_EPWM_AQCTLA 0x216
#define AM335X_PWMSS_REG_EPWM_AQCTLB 0x218
#define AM335X_PWMSS_REG_EPWM_AQSFRC 0x21a
#define AM335X_PWMSS_REG_EPWM_AQCSFRC 0x21c
#define AM335X_PWMSS_REG_EPWM_DBCTL 0x21e
#define AM335X_PWMSS_REG_EPWM_DBRED 0x220
#define AM335X_PWMSS_REG_EPWM_DBFED 0x222
#define AM335X_PWMSS_REG_EPWM_TZSEL 0x224
#define AM335X_PWMSS_REG_EPWM_TZCTL 0x228
#define AM335X_PWMSS_REG_EPWM_TZEINT 0x22a
#define AM335X_PWMSS_REG_EPWM_TZFLG 0x22c
#define AM335X_PWMSS_REG_EPWM_TZCLR 0x22e
#define AM335X_PWMSS_REG_EPWM_TZFRC 0x230
#define AM335X_PWMSS_REG_EPWM_ETSEL 0x232
#define AM335X_PWMSS_REG_EPWM_ETPS 0x234
#define AM335X_PWMSS_REG_EPWM_ETFLG 0x236
#define AM335X_PWMSS_REG_EPWM_ETCLR 0x238
#define AM335X_PWMSS_REG_EPWM_ETFRC 0x23a
#define AM335X_PWMSS_REG_EPWM_PCCTL 0x23c
#define AM335X_PWMSS_REG_EPWM_HRCNFG 0x2c0
#define AM335X_ADC_REG_REVISION 0x000
#define AM335X_ADC_REVISION_SCHEME_GET(x) (((x) & 0xc0000000) >> 30)
#define AM335X_ADC_REVISION_FUNC_GET(x) (((x) & 0x0fff0000) >> 16)
......@@ -106,4 +157,34 @@
#define AM335X_ADC_FACTOR (1.8/4096.0)
#endif /* _INCLUDE_BLOCK_AM335X_ADC_ */
static inline uint32_t am335x_read32(void *base, size_t reg_offset)
{
volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset);
return *reg;
}
static inline void am335x_write32(void *base, size_t reg_offset, uint32_t value)
{
volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset);
*reg = value;
}
static inline uint16_t am335x_read16(void *base, size_t reg_offset)
{
volatile uint16_t *reg = (uint16_t *)((char *)base + reg_offset);
return *reg;
}
static inline void am335x_write16(void *base, size_t reg_offset, uint16_t value)
{
volatile uint16_t *reg = (uint16_t *)((char *)base + reg_offset);
*reg = value;
}
#endif /* _INCLUDE_AM335X_ */
......@@ -16,7 +16,7 @@
*/
#include "block_am335x_adc.h"
#include "am335x.h"
#include <controller/controller_block.h>
#include <log/log.h>
......@@ -24,8 +24,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>
#include <unistd.h>
struct controller_block_private {
......@@ -37,20 +35,6 @@ struct controller_block_private {
void *base;
};
static uint32_t adc_read(void *base, size_t reg_offset)
{
volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset);
return *reg;
}
static void adc_write(void *base, size_t reg_offset, uint32_t value)
{
volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset);
*reg = value;
}
static void adc_calculate(struct controller_block *adc)
{
struct controller_block_private *priv = adc->private;
......@@ -59,13 +43,13 @@ static void adc_calculate(struct controller_block *adc)
uint32_t count;
do {
count = adc_read(base, AM335X_ADC_REG_FIFO0COUNT);
count = am335x_read32(base, AM335X_ADC_REG_FIFO0COUNT);
} while (count != 8);
for (; count; count--) {
int id;
data = adc_read(base, AM335X_ADC_REG_FIFO0DATA);
data = am335x_read32(base, AM335X_ADC_REG_FIFO0DATA);
id = AM335X_ADC_FIFODATA_ID_GET(data);
priv->ain[id] =
......@@ -73,7 +57,7 @@ static void adc_calculate(struct controller_block *adc)
priv->offset[id];
}
adc_write(base, AM335X_ADC_REG_STEPENABLE,
am335x_write32(base, AM335X_ADC_REG_STEPENABLE,
AM335X_ADC_STEPENABLE_STEP1 | AM335X_ADC_STEPENABLE_STEP2 |
AM335X_ADC_STEPENABLE_STEP3 | AM335X_ADC_STEPENABLE_STEP4 |
AM335X_ADC_STEPENABLE_STEP5 | AM335X_ADC_STEPENABLE_STEP6 |
......@@ -189,7 +173,7 @@ struct controller_block * block_am335x_adc_create(char *name)
}
log_send(LOG_T_DEBUG, "%s: ADC mapped @ %p", name, base);
reg = adc_read(base, AM335X_ADC_REG_REVISION);
reg = am335x_read32(base, AM335X_ADC_REG_REVISION);
log_send(LOG_T_DEBUG,
"%s: REVISION: 0x%" PRIx32 ": func: 0x%03x rev: %d.%d",
name, reg, AM335X_ADC_REVISION_FUNC_GET(reg),
......@@ -200,81 +184,81 @@ struct controller_block * block_am335x_adc_create(char *name)
goto err_rev;
}
adc_write(base, AM335X_ADC_REG_CTRL, AM335X_ADC_CTRL_SC_WP_N);
am335x_write32(base, AM335X_ADC_REG_CTRL, AM335X_ADC_CTRL_SC_WP_N);
adc_write(base, AM335X_ADC_REG_IRQENABLE_CLR,
am335x_write32(base, AM335X_ADC_REG_IRQENABLE_CLR,
AM335X_ADC_IRQENABLE_CLR_ALL);
adc_write(base, AM335X_ADC_REG_DMAENABLE_CLR,
am335x_write32(base, AM335X_ADC_REG_DMAENABLE_CLR,
AM335X_ADC_DMAENABLE_CLR_ALL);
adc_write(base, AM335X_ADC_REG_ADC_CLKDIV, 0);
am335x_write32(base, AM335X_ADC_REG_ADC_CLKDIV, 0);
adc_write(base, AM335X_ADC_REG_IDLECONFIG, 0);
adc_write(base, AM335X_ADC_REG_TS_CHARGE_DELAY, 1);
am335x_write32(base, AM335X_ADC_REG_IDLECONFIG, 0);
am335x_write32(base, AM335X_ADC_REG_TS_CHARGE_DELAY, 1);
adc_write(base, AM335X_ADC_REG_STEPCONFIG1,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG1,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY1, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY1, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG2,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG2,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(1) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY2, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY2, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG3,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG3,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(2) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY3, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY3, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG4,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG4,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(3) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY4, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY4, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG5,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG5,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(4) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY5, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY5, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG6,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG6,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(5) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY6, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY6, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG7,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG7,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(6) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY7, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY7, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG8,
am335x_write32(base, AM335X_ADC_REG_STEPCONFIG8,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(7) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY8, 0);
am335x_write32(base, AM335X_ADC_REG_STEPDELAY8, 0);
adc_write(base, AM335X_ADC_REG_CTRL,
am335x_write32(base, AM335X_ADC_REG_CTRL,
AM335X_ADC_CTRL_SC_WP_N |
AM335X_ADC_CTRL_SID |
AM335X_ADC_CTRL_ENABLE);
adc_write(base, AM335X_ADC_REG_STEPENABLE,
am335x_write32(base, AM335X_ADC_REG_STEPENABLE,
AM335X_ADC_STEPENABLE_STEP1 | AM335X_ADC_STEPENABLE_STEP2 |
AM335X_ADC_STEPENABLE_STEP3 | AM335X_ADC_STEPENABLE_STEP4 |
AM335X_ADC_STEPENABLE_STEP5 | AM335X_ADC_STEPENABLE_STEP6 |
......
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "am335x.h"
#include <controller/controller_block.h>
#include <log/log.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>
#include <unistd.h>
struct controller_block_private {
float *in;
void *base;
};
static void pwm_calculate(struct controller_block *pwm)
{
}
static struct controller_block_param_list params[] = {
{ NULL },
};
static void param_set(struct controller_block *pwm, int param, va_list val)
{
}
static struct controller_block_interm_list interms[] = {
{ "in", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, in) },
{ NULL },
};
struct controller_block * block_am335x_pwm_create(char *name, va_list ap)
{
struct controller_block *pwm;
int fd;
void *base;
uint32_t reg;
int pwm_nr;
size_t offset;
pwm_nr = va_arg(ap, int);
if (pwm_nr < 0 || pwm_nr > 2) {
log_send(LOG_T_ERROR, "%s: pwm%d is not valid. (valid: 0-2)",
name, pwm_nr);
return NULL;
}
switch (pwm_nr) {
case 0:
offset = AM335X_PWMSS0_BASE;
break;
case 1:
offset = AM335X_PWMSS1_BASE;
break;
case 2:
offset = AM335X_PWMSS2_BASE;
break;
}
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0 ) {
log_send(LOG_T_ERROR, "%s: Error opening /dev/mem", name);
close(fd);
return NULL;
}
base = mmap(NULL, AM335X_PWMSS_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, offset);
close(fd);
if (!base) {
log_send(LOG_T_ERROR, "Mapping PWM failed");
return NULL;
}
log_send(LOG_T_DEBUG, "%s: PWM mapped @ %p", name, base);
reg = am335x_read32(base, AM335X_PWMSS_REG_IDVER);
log_send(LOG_T_DEBUG,
"%s: IDVER: 0x%" PRIx32 ": func: 0x%03x rev: %d.%d",
name, reg, AM335X_PWMSS_IDVER_FUNC_GET(reg),
AM335X_PWMSS_IDVER_X_MAJOR_GET(reg),
AM335X_PWMSS_IDVER_Y_MINOR_GET(reg));
if (AM335X_PWMSS_IDVER_FUNC_GET(reg) != AM335X_PWMSS_IDVER_FUNC) {
log_send(LOG_T_ERROR, "Unexpected functional number");
goto err_rev;
}
if (!(pwm = controller_block_alloc("am355x_pwm", name, sizeof(struct controller_block_private))))
goto err_alloc;
if (controller_block_interm_list_init(pwm, interms))
goto err_interm;
pwm->private->base = base;
pwm->calculate = pwm_calculate;
if (controller_block_param_list_init(pwm, params))
goto err_param;
pwm->param_set = param_set;
controller_block_add(pwm);
return pwm;
err_param:
err_interm:
controller_block_free(pwm);
err_alloc:
err_rev:
munmap(base, AM335X_PWMSS_SIZE);
return NULL;
}
......@@ -2,7 +2,8 @@
BLOCK_TARGETS := $(LIBDIR)/libam335x.la
BLOCK_SRCS := \
$(DIR)/block_am335x_adc.c
$(DIR)/block_am335x_adc.c \
$(DIR)/block_am335x_pwm.c
BLOCK_OBJS := $(BLOCK_SRCS:.c=.lo)
......
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