zephyr/boards/arm/arduino_due/pinmux.c
Piotr Mienkowski ee66ee6c34 arch: sam3x: Use ASF library
This patch converts Atmel sam3x MCU series to use register
header files from Atmel Software Framework (ASF) library.
By using ASF different Atmel SAM MCU series can use common
device drivers.

Signed-off-by: Piotr Mienkowski <piotr.mienkowski@gmail.com>
2017-05-19 10:06:48 -04:00

295 lines
6.5 KiB
C

/* pinmux_board_arduino_due.c - Arduino Due pinmux driver */
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <init.h>
#include <kernel.h>
#include <pinmux.h>
#include <soc.h>
#include <sys_io.h>
#include "pinmux/pinmux.h"
/**
* @brief Pinmux driver for Arduino due
*
* The SAM3X8E on Arduino Due has 4 PIO controllers. These controllers
* are responsible for pin muxing, input/output, pull-up, etc.
*
* All PIO controller pins are flatten into sequentially incrementing
* pin numbers:
* Pins 0 - 31 are for PIOA
* Pins 32 - 63 are for PIOB
* Pins 64 - 95 are for PIOC
* Pins 96 - 127 are for PIOD
*
* For all the pin descriptions, refer to the Atmel datasheet, and
* the Arduino Due schematics.
*/
/*
* These is the mapping from the board pins to PIO controllers.
* This mapping is created from the Arduino Due schematics.
* Refer to the official schematics for the actual mapping,
* as the following may not be accurate.
*
* IO_0 : PA8
* IO_1 : PA9
* IO_2 : PB25
* IO_3 : PC28
* IO_4 : PA29
* IO_5 : PC25
* IO_6 : PC24
* IO_7 : PC23
*
* IO_8 : PC22
* IO_9 : PC21
* IO_10 : PA28 and PC29
* IO_11 : PD7
* IO_12 : PD8
* IO_13 : PB27
* SDA1 : PA17
* SCL1 : PA18
*
* IO_14 : PD4
* IO_15 : PD5
* IO_16 : PA13
* IO_17 : PA12
* IO_18 : PA11
* IO_19 : PA10
* IO_20 : PB12
* IO_21 : PB13
*
* A_0 : PA16
* A_1 : PA24
* A_2 : PA23
* A_3 : PA22
* A_4 : PA6
* A_5 : PA4
* A_6 : PA3
* A_7 : PA2
*
* A_8 : PB17
* A_9 : PB18
* A_10 : PB19
* A_11 : PB20
* DAC0 : PB15
* DAC1 : PB16
* CANRX : PA1
* CANTX : PA0
*
* IO_22 : PB26
* IO_23 : PA14
* IO_24 : PA15
* IO_25 : PD0
* IO_26 : PD1
* IO_27 : PD2
* IO_28 : PD3
* IO_29 : PD6
* IO_30 : PD9
* IO_31 : PA7
* IO_32 : PD10
* IO_33 : PC1
* IO_34 : PC2
* IO_35 : PC3
* IO_36 : PC4
* IO_37 : PC5
* IO_38 : PC6
* IO_39 : PC7
* IO_40 : PC8
* IO_41 : PC9
* IO_42 : PA19
* IO_43 : PA20
* IO_44 : PC19
* IO_45 : PC18
* IO_46 : PC17
* IO_47 : PC16
* IO_48 : PC15
* IO_49 : PC14
* IO_50 : PC13
* IO_51 : PC12
*/
#define N_PIOA 0
#define N_PIOB 1
#define N_PIOC 2
#define N_PIOD 3
/*
* This function sets the default for the following:
* - Pin mux (peripheral A or B)
* - Set pin as input or output
* - Enable pull-up for pins
*
* At boot, all pins are outputs with pull-up enabled, and are set to be
* peripheral A (with value 0). So only the peripherals that need to be
* set to B (value 1) will be declared explicitly below.
*
* Note that all pins are set to be controlled by the PIO controllers
* by default. For peripherals to work (e.g. UART), the PIO has to
* be disabled for that pin (e.g. UART to take over those pins).
*/
static void __pinmux_defaults(void)
{
u32_t ab_select[4]; /* A/B selection */
u32_t output_en[4]; /* output enabled */
u32_t pull_up[4]; /* pull-up enabled */
u32_t pio_ctrl[4]; /* PIO enable */
u32_t tmp;
/* Read defaults at boot, as the bootloader may have already
* configured some pins.
*/
ab_select[N_PIOA] = PIOA->PIO_ABSR;
ab_select[N_PIOB] = PIOB->PIO_ABSR;
ab_select[N_PIOC] = PIOC->PIO_ABSR;
ab_select[N_PIOD] = PIOD->PIO_ABSR;
output_en[N_PIOA] = PIOA->PIO_OSR;
output_en[N_PIOB] = PIOB->PIO_OSR;
output_en[N_PIOC] = PIOC->PIO_OSR;
output_en[N_PIOD] = PIOD->PIO_OSR;
pio_ctrl[N_PIOA] = PIOA->PIO_PSR;
pio_ctrl[N_PIOB] = PIOB->PIO_PSR;
pio_ctrl[N_PIOC] = PIOC->PIO_PSR;
pio_ctrl[N_PIOD] = PIOD->PIO_PSR;
/* value 1 means pull-up disabled, so need to invert */
pull_up[N_PIOA] = ~(PIOA->PIO_PUSR);
pull_up[N_PIOB] = ~(PIOB->PIO_PUSR);
pull_up[N_PIOC] = ~(PIOC->PIO_PUSR);
pull_up[N_PIOD] = ~(PIOD->PIO_PUSR);
/*
* Now modify as we wish
*/
/* Make sure JTAG pins are used for JTAG */
pio_ctrl[N_PIOB] &= ~(BIT(28) | BIT(29) | BIT(30) | BIT(31));
/* UART console:
* IO_0: PA8 (RX)
* IO_1: PA9 (TX)
*/
pio_ctrl[N_PIOA] &= ~(BIT(8) | BIT(9));
/* I2C pins on TWI controller #0
*
* SDA1: PA17
* SCL1: PA18
*
* Note that these need external pull-up resistors.
*/
pio_ctrl[N_PIOA] &= ~(BIT(17) | BIT(18));
/* I2C pins on TWI controller #1
*
* IO_20: PB12 (SDA)
* IO_21: PB13 (SCL)
*
* Board already have pull-up resistors.
*/
pio_ctrl[N_PIOB] &= ~(BIT(12) | BIT(13));
/*
* Setup ADC pins.
*
* Note that the ADC is considered extra function
* for the pins (other than A or B). This extra
* pin function is enabled by enabling the ADC
* controller. Therefore, the following code
* only sets these pins as input, with pull-up
* disabled. This does not detach the PIO
* controller from the pins so the peripherals
* won't take over.
*
* A_0 : PA16
* A_1 : PA24
* A_2 : PA23
* A_3 : PA22
* A_4 : PA6
* A_5 : PA4
* A_6 : PA3
* A_7 : PA2
*
* A_8 : PB17
* A_9 : PB18
* A_10: PB19
* A_11: PB20
*/
tmp = BIT(16) | BIT(24) | BIT(23) | BIT(22)
| BIT(6) | BIT(4) | BIT(3) | BIT(2);
pio_ctrl[N_PIOA] |= tmp;
output_en[N_PIOA] &= ~(tmp);
pull_up[N_PIOA] &= ~(tmp);
tmp = BIT(17) | BIT(18) | BIT(19) | BIT(20);
pio_ctrl[N_PIOB] |= tmp;
output_en[N_PIOB] &= ~(tmp);
pull_up[N_PIOB] &= ~(tmp);
/*
* Write modifications back to those registers
*/
PIOA->PIO_ABSR = ab_select[N_PIOA];
PIOB->PIO_ABSR = ab_select[N_PIOB];
PIOC->PIO_ABSR = ab_select[N_PIOC];
PIOD->PIO_ABSR = ab_select[N_PIOD];
/* set output enable */
PIOA->PIO_OER = output_en[N_PIOA];
PIOB->PIO_OER = output_en[N_PIOB];
PIOC->PIO_OER = output_en[N_PIOC];
PIOD->PIO_OER = output_en[N_PIOD];
/* set output disable */
PIOA->PIO_ODR = ~(output_en[N_PIOA]);
PIOB->PIO_ODR = ~(output_en[N_PIOB]);
PIOC->PIO_ODR = ~(output_en[N_PIOC]);
PIOD->PIO_ODR = ~(output_en[N_PIOD]);
/* set PIO enable */
PIOA->PIO_PER = pio_ctrl[N_PIOA];
PIOB->PIO_PER = pio_ctrl[N_PIOB];
PIOC->PIO_PER = pio_ctrl[N_PIOC];
PIOD->PIO_PER = pio_ctrl[N_PIOD];
/* set PIO disable */
PIOA->PIO_PDR = ~(pio_ctrl[N_PIOA]);
PIOB->PIO_PDR = ~(pio_ctrl[N_PIOB]);
PIOC->PIO_PDR = ~(pio_ctrl[N_PIOC]);
PIOD->PIO_PDR = ~(pio_ctrl[N_PIOD]);
/* set pull-up enable */
PIOA->PIO_PUER = pull_up[N_PIOA];
PIOB->PIO_PUER = pull_up[N_PIOB];
PIOC->PIO_PUER = pull_up[N_PIOC];
PIOD->PIO_PUER = pull_up[N_PIOD];
/* set pull-up disable */
PIOA->PIO_PUDR = ~(pull_up[N_PIOA]);
PIOB->PIO_PUDR = ~(pull_up[N_PIOB]);
PIOC->PIO_PUDR = ~(pull_up[N_PIOC]);
PIOD->PIO_PUDR = ~(pull_up[N_PIOD]);
}
static int pinmux_init(struct device *port)
{
ARG_UNUSED(port);
__pinmux_defaults();
return 0;
}
SYS_INIT(pinmux_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);