295 lines
6.5 KiB
C
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);
|