/* pinmux_board_arduino_due.c - Arduino Due pinmux driver */ /* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #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);