diff --git a/boards/arduino_101/Makefile b/boards/arduino_101/Makefile index c54615a799e..9c255466e43 100644 --- a/boards/arduino_101/Makefile +++ b/boards/arduino_101/Makefile @@ -3,4 +3,3 @@ ccflags-y += -I$(srctree)/drivers asflags-y := ${ccflags-y} obj-y += board.o -obj-$(CONFIG_PINMUX) += pinmux.o diff --git a/drivers/pinmux/Kconfig b/drivers/pinmux/Kconfig index d7045faa5db..943644320e4 100644 --- a/drivers/pinmux/Kconfig +++ b/drivers/pinmux/Kconfig @@ -39,15 +39,6 @@ config PINMUX_NUM_PINS help Select the number of pins for the pinmux to operate on. -config PINMUX_DEV - bool "Configure pinmux for early board testing" - depends on PINMUX - default n - help - Enables the use of the pinmux_set and pinmux_get functions for early - prototyping on new hardware. WARNING: When using these options, it - is possible to permanently damage the hardware. - config PINMUX_INIT_PRIORITY int prompt "Init priority" diff --git a/drivers/pinmux/Makefile b/drivers/pinmux/Makefile index 69dab3c41eb..c23c9e218bd 100644 --- a/drivers/pinmux/Makefile +++ b/drivers/pinmux/Makefile @@ -2,3 +2,4 @@ ccflags-y +=-I$(srctree)/drivers obj-$(CONFIG_PINMUX_K64) += pinmux_k64.o obj-$(CONFIG_PINMUX_STM32) += pinmux_stm32.o +obj-$(CONFIG_BOARD_ARDUINO_101) += quark_mcu/pinmux_board_arduino_101.o diff --git a/drivers/pinmux/pinmux.h b/drivers/pinmux/pinmux.h index a4117a7bfc7..e0bf200b370 100644 --- a/drivers/pinmux/pinmux.h +++ b/drivers/pinmux/pinmux.h @@ -34,8 +34,6 @@ struct pinmux_config { uint32_t base_address; }; -extern int pinmux_initialize(struct device *port); - #ifdef __cplusplus } #endif diff --git a/boards/arduino_101/pinmux.c b/drivers/pinmux/quark_mcu/pinmux_board_arduino_101.c similarity index 50% rename from boards/arduino_101/pinmux.c rename to drivers/pinmux/quark_mcu/pinmux_board_arduino_101.c index 9b3f8c2165c..0879a3091ae 100644 --- a/boards/arduino_101/pinmux.c +++ b/drivers/pinmux/quark_mcu/pinmux_board_arduino_101.c @@ -1,4 +1,4 @@ -/* pinmux.c - general pinmux operation */ +/* pinmux_board_arduino_101.c - Arduino 101 board pinmux driver */ /* * Copyright (c) 2015 Intel Corporation @@ -22,46 +22,7 @@ #include #include "pinmux/pinmux.h" - -#ifndef CONFIG_PINMUX_DEV -#define PRINT(...) {; } -#else -#if defined(CONFIG_PRINTK) -#include -#define PRINT printk -#elif defined(CONFIG_STDOUT_CONSOLE) -#define PRINT printf -#endif /* CONFIG_PRINTK */ -#endif /*CONFIG_PINMUX_DEV */ - -#define MASK_2_BITS 0x3 -#define PINMUX_PULLUP_OFFSET 0x00 -#define PINMUX_SLEW_OFFSET 0x10 -#define PINMUX_INPUT_OFFSET 0x20 -#define PINMUX_SELECT_OFFSET 0x30 - -#define PINMUX_SELECT_REGISTER(base, reg_offset) \ - (base + PINMUX_SELECT_OFFSET + (reg_offset << 2)) - -/* - * A little decyphering of what is going on here: - * - * Each pinmux register rperesents a bank of 16 pins, 2 bits per pin for a total - * of four possible settings per pin. - * - * The first argument to the macro is name of the uint32_t's that is being used - * to contain the bit patterns for all the configuration registers. The pin - * number divided by 16 selects the correct register bank based on the pin - * number. - * - * The pin number % 16 * 2 selects the position within the register bank for the - * bits controlling the pin. - * - * All but the lower two bits of the config values are masked off to ensure - * that we don't inadvertently affect other pins in the register bank. - */ -#define PIN_CONFIG(A, _pin, _func) \ - (A[((_pin) / 16)] |= ((0x3 & (_func)) << (((_pin) % 16) * 2))) +#include "pinmux_quark_mcu.h" /* * This is the full pinmap that we have available on the board for configuration @@ -187,181 +148,22 @@ static void _pinmux_defaults(uint32_t base) PIN_CONFIG(mux_config, 66, PINMUX_FUNC_B); for (i = 0; i < PINMUX_MAX_REGISTERS; i++) { - PRINT("PINMUX: configuring register i=%d reg=%x", i, - mux_config[i]); sys_write32(mux_config[i], PINMUX_SELECT_REGISTER(base, i)); } } -static int _quark_se_set_mux(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 - */ - volatile uint32_t *mux_register = (uint32_t *)(base + 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 0; -} - static inline void _pinmux_pullups(uint32_t base_address) { - _quark_se_set_mux(base_address + PINMUX_PULLUP_OFFSET, 104, + _quark_mcu_set_mux(base_address + PINMUX_PULLUP_OFFSET, 104, PINMUX_PULLUP_ENABLE); } - -#ifdef CONFIG_PINMUX_DEV -static int pinmux_dev_set(struct device *dev, uint32_t pin, uint32_t func) +static int pinmux_initialize(struct device *port) { - struct pinmux_config * const pmux = dev->config->config_info; - - /* - * the registers are 32-bit wide, but each pin requires 2 bits - * to set the mode (A, B, C, or D). As such we only get 16 - * pins per register... hence the math for the register mask. - */ - uint32_t register_offset = (pin >> 4); - /* - * Now figure out what is the full address for the register - * we are looking for. Add the base register to the register_mask - */ - volatile uint32_t *mux_register = - (uint32_t *)PINMUX_SELECT_REGISTER(pmux->base_address, register_offset); - - /* - * Finally grab the pin offset within the register - */ - uint32_t pin_no = pin % 16; - - /* - * The value 3 is used because that is 2-bits for the mode of each - * pin. The value 2 repesents the bits needed for each pin's mode. - */ - uint32_t pin_mask = MASK_2_BITS << (pin_no << 1); - uint32_t mode_mask = func << (pin_no << 1); - (*(mux_register)) = ((*(mux_register)) & ~pin_mask) | mode_mask; + _pinmux_defaults(CONFIG_PINMUX_BASE); + _pinmux_pullups(CONFIG_PINMUX_BASE); return 0; } -static int pinmux_dev_get(struct device *dev, uint32_t pin, uint32_t *func) -{ - struct pinmux_config * const pmux = dev->config->config_info; - - /* - * the registers are 32-bit wide, but each pin requires 2 bits - * to set the mode (A, B, C, or D). As such we only get 16 - * pins per register... hence the math for the register mask. - */ - uint32_t register_offset = pin >> 4; - /* - * Now figure out what is the full address for the register - * we are looking for. Add the base register to the register_mask - */ - volatile uint32_t *mux_register = - (uint32_t *)PINMUX_SELECT_REGISTER(pmux->base_address, register_offset); - - /* - * Finally grab the pin offset within the register - */ - uint32_t pin_no = pin % 16; - - /* - * The value 3 is used because that is 2-bits for the mode of each - * pin. The value 2 repesents the bits needed for each pin's mode. - */ - uint32_t pin_mask = MASK_2_BITS << (pin_no << 1); - uint32_t mode_mask = (*(mux_register)) & pin_mask; - uint32_t mode = mode_mask >> (pin_no << 1); - - *func = mode; - - return 0; -} -#else -static int pinmux_dev_set(struct device *dev, uint32_t pin, uint32_t func) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(func); - - PRINT("ERROR: %s is not enabled", __func__); - - return -EPERM; -} - -static int pinmux_dev_get(struct device *dev, uint32_t pin, uint32_t *func) -{ - ARG_UNUSED(dev); - ARG_UNUSED(pin); - ARG_UNUSED(func); - - PRINT("ERROR: %s is not enabled", __func__); - - return -EPERM; -} -#endif /* CONFIG_PINMUX_DEV */ - -static int pinmux_dev_pullup(struct device *dev, - uint32_t pin, - uint8_t func) -{ - struct pinmux_config * const pmux = dev->config->config_info; - - _quark_se_set_mux(pmux->base_address + PINMUX_PULLUP_OFFSET, pin, func); - - return 0; -} -static int pinmux_dev_input(struct device *dev, uint32_t pin, uint8_t func) -{ - struct pinmux_config * const pmux = dev->config->config_info; - - _quark_se_set_mux(pmux->base_address + PINMUX_INPUT_OFFSET, pin, func); - - return 0; -} - -static struct pinmux_driver_api api_funcs = { - .set = pinmux_dev_set, - .get = pinmux_dev_get, - .pullup = pinmux_dev_pullup, - .input = pinmux_dev_input -}; - -int pinmux_initialize(struct device *port) -{ - struct pinmux_config * const pmux = port->config->config_info; - - port->driver_api = &api_funcs; - - _pinmux_defaults(pmux->base_address); - _pinmux_pullups(pmux->base_address); - - return 0; -} - -struct pinmux_config board_pmux = { - .base_address = CONFIG_PINMUX_BASE, -}; - -DEVICE_INIT(pmux, PINMUX_NAME, &pinmux_initialize, - NULL, &board_pmux, - SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(pinmux_initialize, SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/drivers/pinmux/quark_mcu/pinmux_quark_mcu.h b/drivers/pinmux/quark_mcu/pinmux_quark_mcu.h new file mode 100644 index 00000000000..8ed90520e56 --- /dev/null +++ b/drivers/pinmux/quark_mcu/pinmux_quark_mcu.h @@ -0,0 +1,73 @@ +/* pinmux_quark_mcu.h - pinmux operation for generic Quark MCU boards */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define PINMUX_PULLUP_OFFSET 0x00 +#define PINMUX_SLEW_OFFSET 0x10 +#define PINMUX_INPUT_OFFSET 0x20 +#define PINMUX_SELECT_OFFSET 0x30 + +#define PINMUX_SELECT_REGISTER(base, reg_offset) \ + (base + PINMUX_SELECT_OFFSET + (reg_offset << 2)) + +/* + * A little decyphering of what is going on here: + * + * Each pinmux register rperesents a bank of 16 pins, 2 bits per pin for a total + * of four possible settings per pin. + * + * The first argument to the macro is name of the uint32_t's that is being used + * to contain the bit patterns for all the configuration registers. The pin + * number divided by 16 selects the correct register bank based on the pin + * number. + * + * The pin number % 16 * 2 selects the position within the register bank for the + * bits controlling the pin. + * + * All but the lower two bits of the config values are masked off to ensure + * that we don't inadvertently affect other pins in the register bank. + */ +#define PIN_CONFIG(A, _pin, _func) \ + (A[((_pin) / 16)] |= ((0x3 & (_func)) << (((_pin) % 16) * 2))) + +static inline int _quark_mcu_set_mux(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 + */ + volatile uint32_t *mux_register = (uint32_t *)(base + 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 0; +}