Commit 7090f939 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Add clock enabling to PWM.

Add pin mux setting.
parent faff5c5e
/* /*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014 Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014, 2015
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -67,7 +67,10 @@ void *am335x_mem(size_t base, size_t size) ...@@ -67,7 +67,10 @@ void *am335x_mem(size_t base, size_t size)
goto err_open; goto err_open;
} }
map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, base); map = mmap(NULL, size,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_LOCKED,
fd, base);
close(fd); close(fd);
if (!map) { if (!map) {
log_send(LOG_T_ERROR, "am335x: mmap 0x%zx bytes @ 0x%08zx failed", log_send(LOG_T_ERROR, "am335x: mmap 0x%zx bytes @ 0x%08zx failed",
...@@ -78,6 +81,9 @@ void *am335x_mem(size_t base, size_t size) ...@@ -78,6 +81,9 @@ void *am335x_mem(size_t base, size_t size)
log_send(LOG_T_DEBUG, "am335x: 0x%zx bytes mapped @ 0x%08zx", log_send(LOG_T_DEBUG, "am335x: 0x%zx bytes mapped @ 0x%08zx",
size, base); size, base);
entry->base = base;
entry->size = size;
entry->map = map;
entry->next = mapped_list; entry->next = mapped_list;
mapped_list = entry; mapped_list = entry;
...@@ -115,7 +121,7 @@ int am335x_cm_enable(size_t cm_off) ...@@ -115,7 +121,7 @@ int am335x_cm_enable(size_t cm_off)
if (reg == AM335X_CM_IDLEST_FUNCTIONAL) if (reg == AM335X_CM_IDLEST_FUNCTIONAL)
log_send(LOG_T_DEBUG, "am335x: CM 0x%x: state: functional", cm_off); log_send(LOG_T_DEBUG, "am335x: CM 0x%x: state: functional", cm_off);
if (reg == AM335X_CM_IDLEST_TRANSITION) if (reg == AM335X_CM_IDLEST_TRANSITION)
log_send(LOG_T_DEBUG, "am335x: CM 0x%x: state: transitining", cm_off); log_send(LOG_T_DEBUG, "am335x: CM 0x%x: state: transitioning", cm_off);
if (reg == AM335X_CM_IDLEST_IDLE) if (reg == AM335X_CM_IDLEST_IDLE)
log_send(LOG_T_DEBUG, "am335x: CM 0x%x: state: idle", cm_off); log_send(LOG_T_DEBUG, "am335x: CM 0x%x: state: idle", cm_off);
if (reg == AM335X_CM_IDLEST_DISABLED) if (reg == AM335X_CM_IDLEST_DISABLED)
...@@ -127,3 +133,66 @@ int am335x_cm_enable(size_t cm_off) ...@@ -127,3 +133,66 @@ int am335x_cm_enable(size_t cm_off)
return 0; return 0;
} }
static void *control_module_base;
static int am335x_control_module_init(void)
{
control_module_base =
am335x_mem(AM335X_CONTROL_MODULE_BASE, AM335X_CONTROL_MODULE_SIZE);
return control_module_base == NULL;
}
int am335x_pinmux_debug(size_t offset)
{
uint32_t reg;
if (!control_module_base) {
if (am335x_control_module_init()) {
log_send(LOG_T_ERROR, "am335x: CONTROL_MODULE init failed");
return -1;
}
}
reg = am335x_read32(control_module_base,
offset + AM335X_CONTROL_MODULE_CONF);
log_send(LOG_T_DEBUG, "am335x: pin @0x%x: 0x%08x: %s, %s, %s, mode %d",
offset, reg,
reg & AM335X_CONTROL_MODULE_PINMUX_SLEWCTRL_SLOW ? "slow" : "fast",
reg & AM335X_CONTROL_MODULE_PINMUX_RX ? "input" : "output",
reg & AM335X_CONTROL_MODULE_PINMUX_PUEN ?
(reg & AM335X_CONTROL_MODULE_PINMUX_PU ? "pull-up" : "pull-down") :
"open",
reg & AM335X_CONTROL_MODULE_PINMUX_MODE_MASK);
return 0;
}
int am335x_pinmux_set(size_t offset, unsigned mode, unsigned flags)
{
uint32_t reg, regr;
int ret = 0;
if (!control_module_base) {
if (am335x_control_module_init()) {
log_send(LOG_T_ERROR, "am335x: CONTROL_MODULE init failed");
return -1;
}
}
reg = (mode & AM335X_CONTROL_MODULE_PINMUX_MODE_MASK) | flags;
// log_send(LOG_T_DEBUG, "am335x: mode: %d reg: 0x%08x", mode, reg);
am335x_write32(control_module_base, offset + AM335X_CONTROL_MODULE_CONF,
reg);
regr = am335x_read32(control_module_base, offset + AM335X_CONTROL_MODULE_CONF);
if (regr != reg) {
log_send(LOG_T_ERROR, "am335x: pinmux cannot be set to 0x%08x: 0x%08x",
reg, regr);
ret = -1;
}
am335x_pinmux_debug(offset);
return ret;
}
/* /*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014 Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014, 2015
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -38,11 +38,33 @@ ...@@ -38,11 +38,33 @@
#define AM335X_CM_MODULEMODE_DISABLE 0x00000000 #define AM335X_CM_MODULEMODE_DISABLE 0x00000000
#define AM335X_CM_MODULEMODE_ENABLE 0x00000002 #define AM335X_CM_MODULEMODE_ENABLE 0x00000002
#define AM335X_CM_PER_EPWMSS1_CLKCTRL 0x000000cc
#define AM335X_CM_PER_EPWMSS0_CLKCTRL 0x000000d4
#define AM335X_CM_PER_EPWMSS2_CLKCTRL 0x000000d8
#define AM335X_CM_WKUP_ADC_TSC_CLKCTRL 0x000004bc #define AM335X_CM_WKUP_ADC_TSC_CLKCTRL 0x000004bc
#define AM335X_ADC_BASE 0x44e0d000 #define AM335X_ADC_BASE 0x44e0d000
#define AM335X_ADC_SIZE 0x00002000 #define AM335X_ADC_SIZE 0x00002000
#define AM335X_CONTROL_MODULE_BASE 0x44e10000
#define AM335X_CONTROL_MODULE_PINMUX_SLEWCTRL_FAST 0x00000000
#define AM335X_CONTROL_MODULE_PINMUX_SLEWCTRL_SLOW 0x00000040
#define AM335X_CONTROL_MODULE_PINMUX_RX 0x00000020
#define AM335X_CONTROL_MODULE_PINMUX_PU 0x00000010
#define AM335X_CONTROL_MODULE_PINMUX_PUEN 0x00000008
#define AM335X_CONTROL_MODULE_PINMUX_MODE_MASK 0x00000007
#define AM335X_CONTROL_MODULE_SIZE 0x00002000
#define AM335X_CONTROL_MODULE_CONF 0x800
#define AM335X_CONTROL_MODULE_CONF_GPMC_AD0 0x000
#define AM335X_CONTROL_MODULE_CONF_MCASP0_ACLKX 0x190 /* P9_31, 1: pwm0 A */
#define AM335X_CONTROL_MODULE_CONF_MCASP0_FSX 0x194 /* P9_29, 1: pwm0 B */
#define AM335X_CONTROL_MODULE_CONF_LCD_DATA0 0x0a0 /* P8_45, 3: pwm2 A */
#define AM335X_CONTROL_MODULE_CONF_LCD_DATA1 0x0a4 /* P8_46, 3: pwm2 B */
#define AM335X_CONTROL_MODULE_CONF_LCD_DATA10 0x0c8 /* P8_36, 2: pwm1 A */
#define AM335X_CONTROL_MODULE_CONF_LCD_DATA11 0x0cc /* P8_34, 2: pwm1 B */
#define AM335X_PWMSS0_BASE 0x48300000 #define AM335X_PWMSS0_BASE 0x48300000
#define AM335X_PWMSS1_BASE 0x48302000 #define AM335X_PWMSS1_BASE 0x48302000
#define AM335X_PWMSS2_BASE 0x48304000 #define AM335X_PWMSS2_BASE 0x48304000
...@@ -285,7 +307,6 @@ ...@@ -285,7 +307,6 @@
static inline uint32_t am335x_read32(void *base, size_t reg_offset) static inline uint32_t am335x_read32(void *base, size_t reg_offset)
{ {
volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset); volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset);
...@@ -315,9 +336,22 @@ static inline void am335x_write16(void *base, size_t reg_offset, uint16_t value) ...@@ -315,9 +336,22 @@ static inline void am335x_write16(void *base, size_t reg_offset, uint16_t value)
*reg = value; *reg = value;
} }
static inline uint8_t am335x_read8(void *base, size_t reg_offset)
{
volatile uint8_t *reg = (uint8_t *)((char *)base + reg_offset);
return *reg;
}
static inline void am335x_write8(void *base, size_t reg_offset, uint8_t value)
{
volatile uint8_t *reg = (uint8_t *)((char *)base + reg_offset);
*reg = value;
}
void *am335x_mem(size_t base, size_t size); void *am335x_mem(size_t base, size_t size);
int am335x_cm_enable(size_t cm_off); int am335x_cm_enable(size_t cm_off);
int am335x_pinmux_set(size_t offset, unsigned mode, unsigned flags);
#endif /* _INCLUDE_AM335X_ */ #endif /* _INCLUDE_AM335X_ */
...@@ -157,6 +157,11 @@ static struct controller_block * block_am335x_pwm_create(char *name, int argc, v ...@@ -157,6 +157,11 @@ static struct controller_block * block_am335x_pwm_create(char *name, int argc, v
uint32_t reg; uint32_t reg;
int pwm_nr; int pwm_nr;
size_t offset; size_t offset;
size_t cm_offset;
size_t pin_a;
size_t pin_b;
unsigned mode_a;
unsigned mode_b;
pwm_nr = va_arg(ap, int); pwm_nr = va_arg(ap, int);
if (pwm_nr < 0 || pwm_nr > 2) { if (pwm_nr < 0 || pwm_nr > 2) {
...@@ -167,15 +172,48 @@ static struct controller_block * block_am335x_pwm_create(char *name, int argc, v ...@@ -167,15 +172,48 @@ static struct controller_block * block_am335x_pwm_create(char *name, int argc, v
switch (pwm_nr) { switch (pwm_nr) {
case 0: case 0:
offset = AM335X_PWMSS0_BASE; offset = AM335X_PWMSS0_BASE;
cm_offset = AM335X_CM_PER_EPWMSS0_CLKCTRL;
pin_a = AM335X_CONTROL_MODULE_CONF_MCASP0_ACLKX;
pin_b = AM335X_CONTROL_MODULE_CONF_MCASP0_FSX;
mode_a = 1;
mode_b = 1;
break; break;
case 1: case 1:
offset = AM335X_PWMSS1_BASE; offset = AM335X_PWMSS1_BASE;
cm_offset = AM335X_CM_PER_EPWMSS1_CLKCTRL;
pin_a = AM335X_CONTROL_MODULE_CONF_LCD_DATA10;
pin_b = AM335X_CONTROL_MODULE_CONF_LCD_DATA11;
mode_a = 2;
mode_b = 2;
break; break;
case 2: case 2:
offset = AM335X_PWMSS2_BASE; offset = AM335X_PWMSS2_BASE;
cm_offset = AM335X_CM_PER_EPWMSS2_CLKCTRL;
pin_a = AM335X_CONTROL_MODULE_CONF_LCD_DATA0;
pin_b = AM335X_CONTROL_MODULE_CONF_LCD_DATA1;
mode_a = 3;
mode_b = 3;
break; break;
} }
if (am335x_cm_enable(cm_offset)) {
log_send(LOG_T_ERROR, "%s: Enabling module failed", name);
return NULL;
}
if (am335x_pinmux_set(pin_a, mode_a,
AM335X_CONTROL_MODULE_PINMUX_SLEWCTRL_FAST |
AM335X_CONTROL_MODULE_PINMUX_RX)) {
log_send(LOG_T_ERROR, "%s: Could not set mux for pin A", name);
return NULL;
}
if (am335x_pinmux_set(pin_b, mode_b,
AM335X_CONTROL_MODULE_PINMUX_SLEWCTRL_FAST |
AM335X_CONTROL_MODULE_PINMUX_RX)) {
log_send(LOG_T_ERROR, "%s: Could not set mux for pin B", name);
return NULL;
}
base = am335x_mem(offset, AM335X_PWMSS_SIZE); base = am335x_mem(offset, AM335X_PWMSS_SIZE);
if (!base) { if (!base) {
log_send(LOG_T_ERROR, "%s: Mapping PWM failed", name); log_send(LOG_T_ERROR, "%s: Mapping PWM failed", name);
......
Supports Markdown
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