From 05cbf0b20b67a2d203375ae40fc4d6b4c04505bf Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Tue, 15 Mar 2016 15:43:38 -0300 Subject: [PATCH] pinmux_dev: Add the pinmux_dev driver for Atmel SAM3X This introduces the pinmux_dev driver for the Atmel SAM3X. This driver implements what used to be the pinmux driver API, which applications could use to modify the function of pins during runtime. That functionality is now protected under the CONFIG_PINMUX_DEV option, which should only be set during the early enabling of a new board, as there is risk of damage to the board when misused. Change-Id: I3aa00505d2771b53c41fe687c3e5230e804756be Signed-off-by: Vinicius Costa Gomes --- drivers/pinmux/Kconfig | 2 + drivers/pinmux/Makefile | 5 + drivers/pinmux/dev/Kconfig | 41 ++++++ drivers/pinmux/dev/Makefile | 3 + drivers/pinmux/dev/pinmux_dev_atmel_sam3x.c | 133 ++++++++++++++++++++ 5 files changed, 184 insertions(+) create mode 100644 drivers/pinmux/dev/Kconfig create mode 100644 drivers/pinmux/dev/Makefile create mode 100644 drivers/pinmux/dev/pinmux_dev_atmel_sam3x.c diff --git a/drivers/pinmux/Kconfig b/drivers/pinmux/Kconfig index 943644320e4..c2b489fe12c 100644 --- a/drivers/pinmux/Kconfig +++ b/drivers/pinmux/Kconfig @@ -25,6 +25,8 @@ menuconfig PINMUX if PINMUX +source "drivers/pinmux/dev/Kconfig" + config PINMUX_BASE hex "Base Address" depends on PINMUX diff --git a/drivers/pinmux/Makefile b/drivers/pinmux/Makefile index 3e3bf5f8482..a40d160efca 100644 --- a/drivers/pinmux/Makefile +++ b/drivers/pinmux/Makefile @@ -1,5 +1,6 @@ ccflags-y +=-I$(srctree)/drivers +# Board initialization obj-$(CONFIG_PINMUX_K64) += frdm_k64f/pinmux_k64.o frdm_k64f/pinmux_board_frdm_k64f.o obj-$(CONFIG_PINMUX_STM32) += pinmux_stm32.o obj-$(CONFIG_BOARD_ARDUINO_101) += quark_mcu/pinmux_board_arduino_101.o @@ -7,3 +8,7 @@ obj-$(CONFIG_BOARD_ARDUINO_DUE) += sam3x/pinmux_board_arduino_due.o obj-$(CONFIG_BOARD_GALILEO) += galileo/pinmux_board_galileo.o galileo/pinmux_galileo.o obj-$(CONFIG_BOARD_QUARK_D2000_CRB) += quark_mcu/pinmux_board_quark_d2000_crb.o obj-$(CONFIG_BOARD_QUARK_SE_DEVBOARD) += quark_mcu/pinmux_board_quark_se_dev.o + +# "runtime" pinmux +obj-$(CONFIG_PINMUX_DEV) += dev/ + diff --git a/drivers/pinmux/dev/Kconfig b/drivers/pinmux/dev/Kconfig new file mode 100644 index 00000000000..29d6c38392d --- /dev/null +++ b/drivers/pinmux/dev/Kconfig @@ -0,0 +1,41 @@ +# Kconfig - Pinmux Dev configuration options + +# +# 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. +# + +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_DEV_NAME + string "Configure pinmux for early board testing" + depends on PINMUX + default "pmux_dev" + help + The name of the pinmux dev driver. + +config PINMUX_DEV_ATMEL_SAM3X + bool "Enable pinmux dev driver for Atmel SAM3X boards" + depends on PINMUX_DEV && SOC_ATMEL_SAM3X8E + help + Enables the pinmux dev driver for boards based on the + Atmel SAM3X family of microcontrollers. + default n diff --git a/drivers/pinmux/dev/Makefile b/drivers/pinmux/dev/Makefile new file mode 100644 index 00000000000..035fa38c9bd --- /dev/null +++ b/drivers/pinmux/dev/Makefile @@ -0,0 +1,3 @@ +ccflags-$(CONFIG_PINMUX_DEV) +=-I$(srctree)/drivers + +obj-$(CONFIG_PINMUX_DEV_ATMEL_SAM3X) += pinmux_dev_atmel_sam3x.o diff --git a/drivers/pinmux/dev/pinmux_dev_atmel_sam3x.c b/drivers/pinmux/dev/pinmux_dev_atmel_sam3x.c new file mode 100644 index 00000000000..082ba2dff94 --- /dev/null +++ b/drivers/pinmux/dev/pinmux_dev_atmel_sam3x.c @@ -0,0 +1,133 @@ +/* + * 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. + */ +#include +#include + +#include +#include +#include +#include +#include + +static volatile struct __pio *_get_port(uint32_t pin) +{ + uint32_t port_num = pin / 32; + + switch (port_num) { + case 0: + return __PIOA; + case 1: + return __PIOB; + case 2: + return __PIOC; + case 3: + return __PIOD; + default: + /* return null if pin is outside range */ + return NULL; + } +} + +static int pinmux_set(struct device *dev, uint32_t pin, uint32_t func) +{ + volatile struct __pio *port = _get_port(pin); + uint32_t tmp; + + ARG_UNUSED(dev); + + if (!port) { + return -EINVAL; + } + + tmp = port->absr; + if (func) { + tmp |= (1 << (pin % 32)); + } else { + tmp &= ~(1 << (pin % 32)); + } + port->absr = tmp; + + return 0; +} + +static int pinmux_get(struct device *dev, uint32_t pin, uint32_t *func) +{ + volatile struct __pio *port = _get_port(pin); + + ARG_UNUSED(dev); + + if (!port) { + return -EINVAL; + } + + *func = (port->absr & (1 << (pin % 32))) ? 1 : 0; + + return 0; +} + +static int pinmux_pullup(struct device *dev, uint32_t pin, uint8_t func) +{ + volatile struct __pio *port = _get_port(pin); + + ARG_UNUSED(dev); + + if (!port) { + return -EINVAL; + } + + if (func) { + port->puer = (1 << (pin % 32)); + } else { + port->pudr = (1 << (pin % 32)); + } + + return 0; +} +static int pinmux_input(struct device *dev, uint32_t pin, uint8_t func) +{ + volatile struct __pio *port = _get_port(pin); + + ARG_UNUSED(dev); + + if (!port) { + return -EINVAL; + } + + if (func) { + port->odr = (1 << (pin % 32)); + } else { + port->oer = (1 << (pin % 32)); + } + + return 0; +} + +static struct pinmux_driver_api api_funcs = { + .set = pinmux_set, + .get = pinmux_get, + .pullup = pinmux_pullup, + .input = pinmux_input +}; + +static int pinmux_dev_init(struct device *port) +{ + port->driver_api = &api_funcs; + + return 0; +} + +DEVICE_INIT(pmux_dev, CONFIG_PINMUX_DEV_NAME, &pinmux_dev_init, NULL, NULL, + PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);