pinmux : Quark_SE : add pullup, input enable regs

Adding support for the pinmux pins to set the pullup and input enable
registers.  On the Arduino_101 board some pullup pins specifically can
be used to cause a reset for the Arduino sketch being run.  Its use on
other pins is currently being investigated.

Change-Id: Id3293a4da84ea5bf553bf62ccb12782cb88503a5
Signed-off-by: Dan Kalowsky <daniel.kalowsky@intel.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Dan Kalowsky 2015-12-04 15:05:23 -08:00 committed by Anas Nashif
commit f6694ed31f
2 changed files with 111 additions and 14 deletions

View file

@ -50,7 +50,7 @@ config EOI_FORWARDING_BUG
if PINMUX if PINMUX
config PINMUX_BASE config PINMUX_BASE
default 0xB0800930 default 0xb0800900
endif endif

View file

@ -35,9 +35,14 @@
#endif /*CONFIG_PINMUX_DEV */ #endif /*CONFIG_PINMUX_DEV */
#define PINMUX_PULLUP_OFFSET 0x00
#define PINMUX_SLEW_OFFSET 0x10
#define PINMUX_INPUT_OFFSET 0x20
#define PINMUX_SELECT_OFFSET 0x30
extern struct pin_config mux_config[]; extern struct pin_config mux_config[];
static void _quark_se_select_set(uint32_t base, uint32_t pin, uint32_t mode) static void _quark_se_select(uint32_t base, uint32_t pin, uint32_t mode)
{ {
/* /*
* the registers are 32-bit wide, but each pin requires 2 bits * the registers are 32-bit wide, but each pin requires 2 bits
@ -49,7 +54,8 @@ static void _quark_se_select_set(uint32_t base, uint32_t pin, uint32_t mode)
* Now figure out what is the full address for the register * Now figure out what is the full address for the register
* we are looking for. Add the base register to the register_mask * we are looking for. Add the base register to the register_mask
*/ */
volatile uint32_t *mux_register = (uint32_t *)(base + register_offset); volatile uint32_t *mux_register =
(uint32_t *)(base + PINMUX_SELECT_OFFSET + register_offset);
/* /*
* Finally grab the pin offset within the register * Finally grab the pin offset within the register
@ -66,6 +72,66 @@ static void _quark_se_select_set(uint32_t base, uint32_t pin, uint32_t mode)
(*(mux_register)) = ((*(mux_register)) & ~pin_mask) | mode_mask; (*(mux_register)) = ((*(mux_register)) & ~pin_mask) | mode_mask;
} }
static uint32_t _quark_se_pullup(uint32_t base, uint32_t pin, uint8_t func)
{
/*
* the registers are 32-bit wide, but each pin requires 1 bit
* to set the input enable bit.
*/
uint32_t register_offset = (pin / 32) * 4;
/*
* Now figure out what is the full address for the register
* we are looking for. Add the base register to the register_mask
* Valid values include: 0x900, 0x904, 0x908, and 0x90C
*/
volatile uint32_t *mux_register =
(uint32_t *)(base + PINMUX_PULLUP_OFFSET + register_offset);
/*
* Finally grab the pin offset within the register
*/
uint32_t pin_offset = pin % 32;
/*
* MAGIC NUMBER: 0x1 is used as the pullup is a single bit in a
* 32-bit register.
*/
(*(mux_register)) = ((*(mux_register)) & ~(0x1 << pin_offset)) |
((func & 0x01) << pin_offset);
return DEV_OK;
}
static uint32_t _quark_se_input(uint32_t base, uint32_t pin, uint8_t func)
{
/*
* the registers are 32-bit wide, but each pin requires 1 bit
* to set the input enable bit.
*/
uint32_t register_offset = (pin / 32) * 4;
/*
* Now figure out what is the full address for the register
* we are looking for. Add the base register to the register_mask
* Valid values include: 0x920, 0x924, 0x928, and 0x92C
*/
volatile uint32_t *mux_register =
(uint32_t *)(base + PINMUX_INPUT_OFFSET + register_offset);
/*
* Finally grab the pin offset within the register
*/
uint32_t pin_offset = pin % 32;
/*
* MAGIC NUMBER: 0x1 is used as the pullup is a single bit in a
* 32-bit register.
*/
(*(mux_register)) = ((*(mux_register)) & ~(0x1 << pin_offset)) |
((func & 0x01) << pin_offset);
return DEV_OK;
}
#ifdef CONFIG_PINMUX_DEV #ifdef CONFIG_PINMUX_DEV
static uint32_t _quark_se_select_get(uint32_t base, uint32_t pin) static uint32_t _quark_se_select_get(uint32_t base, uint32_t pin)
@ -80,7 +146,8 @@ static uint32_t _quark_se_select_get(uint32_t base, uint32_t pin)
* Now figure out what is the full address for the register * Now figure out what is the full address for the register
* we are looking for. Add the base register to the register_mask * we are looking for. Add the base register to the register_mask
*/ */
volatile uint32_t *mux_register = (uint32_t *)(base + register_offset); volatile uint32_t *mux_register =
(uint32_t *)(base + PINMUX_SELECT_OFFSET + register_offset);
/* /*
* Finally grab the pin offset within the register * Finally grab the pin offset within the register
@ -101,9 +168,9 @@ static uint32_t _quark_se_select_get(uint32_t base, uint32_t pin)
static uint32_t pinmux_dev_set(struct device *dev, uint32_t pin, uint8_t func) static uint32_t pinmux_dev_set(struct device *dev, uint32_t pin, uint8_t func)
{ {
struct pinmux_config * const pmux = dev->config->config_info; struct pinmux_config const * const pmux = dev->config->config_info;
_quark_se_select_set(pmux->base_address, pin, func); _quark_se_select(pmux->base_address, pin, func);
return DEV_OK; return DEV_OK;
} }
@ -124,7 +191,7 @@ static uint32_t pinmux_dev_set(struct device *dev, uint32_t pin, uint8_t func)
#ifdef CONFIG_PINMUX_DEV #ifdef CONFIG_PINMUX_DEV
static uint32_t pinmux_dev_get(struct device *dev, uint32_t pin, uint8_t *func) static uint32_t pinmux_dev_get(struct device *dev, uint32_t pin, uint8_t *func)
{ {
struct pinmux_config * const pmux = dev->config->config_info; struct pinmux_config const * const pmux = dev->config->config_info;
uint32_t ret; uint32_t ret;
ret = _quark_se_select_get(pmux->base_address, pin); ret = _quark_se_select_get(pmux->base_address, pin);
@ -145,27 +212,57 @@ static uint32_t pinmux_dev_get(struct device *dev, uint32_t pin, uint8_t *func)
} }
#endif /* CONFIG_PINMUX_DEV */ #endif /* CONFIG_PINMUX_DEV */
static uint32_t pinmux_dev_pullup(struct device *dev,
uint32_t pin,
uint8_t func)
{
struct pinmux_config const * const pmux = dev->config->config_info;
_quark_se_pullup(pmux->base_address, pin, func);
return DEV_OK;
}
static uint32_t pinmux_dev_input(struct device *dev, uint32_t pin, uint8_t func)
{
struct pinmux_config const * const pmux = dev->config->config_info;
_quark_se_input(pmux->base_address, pin, func);
return DEV_OK;
}
static struct pinmux_driver_api api_funcs = { static struct pinmux_driver_api api_funcs = {
.set = pinmux_dev_set, .set = pinmux_dev_set,
.get = pinmux_dev_get .get = pinmux_dev_get,
.pullup = pinmux_dev_pullup,
.input = pinmux_dev_input
}; };
#if defined(CONFIG_BOARD_CURIE_101)
int pinmux_initialize(struct device *dev) static inline void _pinmux_pullups(uint32_t base_address)
{ {
struct device_config *dev_cfg = dev->config; _quark_se_pullup(base_address, 104, PINMUX_PULLUP_ENABLE);
struct pinmux_config *pmux = dev_cfg->config_info; }
#else
static inline void _pinmux_pullups(uint32_t base_address) { };
#endif
int pinmux_initialize(struct device *port)
{
struct pinmux_config const * const pmux = port->config->config_info;
int i; int i;
dev->driver_api = &api_funcs; port->driver_api = &api_funcs;
for (i = 0; i < CONFIG_PINMUX_NUM_PINS; i++) { for (i = 0; i < CONFIG_PINMUX_NUM_PINS; i++) {
_quark_se_select_set(pmux->base_address, _quark_se_select(pmux->base_address,
mux_config[i].pin_num, mux_config[i].pin_num,
mux_config[i].mode); mux_config[i].mode);
} }
_pinmux_pullups(pmux->base_address);
return DEV_OK; return DEV_OK;
} }