This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2fde85162cd7413760ecf6087c263792496c0054 Author: Daniel P. Carvalho <[email protected]> AuthorDate: Sat Oct 3 13:44:55 2026 -0300 arch/mips/pic32mz: add PIC32MZ-W1 (WFI32E01) support. Add the PIC32MZ-W1 family, used in Microchip's WFI32E01 Wi-Fi modules. W1 shares the MIPS32 M-Class core and much of the peripheral IP with PIC32MZ EC/EF, but its SFR map, IRQ vectors, PPS registers and configuration words are laid out differently, so these are new files selected by CONFIG_ARCH_CHIP_PIC32MZW1: - hardware/pic32mzw1_*.h, irq_pic32mzw1.h: memory map, PPS, IRQ vectors and configuration words, from the PIC32MZ-W_DFP (Apache-2.0). - pic32mz_wfi32_pwrclk.c: W1 does not set up its PLLs from the configuration words. Software starts the 40 MHz crystal oscillator, runs SYSCLK at 200 MHz from the system PLL, starts the Ethernet/Wi-Fi PLL and switches the regulator from MLDO to buck mode using the factory trim values (on B0 silicon). Facts not found in the data sheet or DFP are marked [EX] in comments; they come from Microchip's WFI32 Ethernet/Wi-Fi bridge example firmware. - pic32mz_head.S, pic32mz_config.h: emit the W1 configuration words (DEVCFG0/1/2/4, FBCFG0, FCPN0, FSIGN0). - W1 differences in shared code: PREFEN only accepts 0/1, PB6DIV clocks the CPU and is left alone, UART1/2, SPI1/2 and I2C2 are clocked from PBCLK3 and the timers from PBCLK1 (data sheet Table 11-1), I2C1 and I2C2 are not contiguous in the SFR map, UART1 and SPI1 can use their dedicated (non-PPS) pins. New Kconfig options: PIC32MZ_W1_PMU_MLDO (keep the regulator in its power-on MLDO mode), PIC32MZ_W1_FLASH_WAITSTATES (default 5, the value used by Microchip's example at 200 MHz) and PIC32MZ_W1_BOOTTRACE (polled early boot trace on UART1, a bring-up aid). Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Daniel P. Carvalho <[email protected]> --- arch/mips/include/pic32mz/chip.h | 41 + arch/mips/include/pic32mz/irq.h | 2 + arch/mips/include/pic32mz/irq_pic32mzw1.h | 247 ++++++ arch/mips/src/pic32mz/Kconfig | 47 ++ arch/mips/src/pic32mz/Make.defs | 4 + arch/mips/src/pic32mz/hardware/pic32mz_features.h | 2 + arch/mips/src/pic32mz/hardware/pic32mz_i2c.h | 10 +- arch/mips/src/pic32mz/hardware/pic32mz_ioport.h | 12 + arch/mips/src/pic32mz/hardware/pic32mz_memorymap.h | 2 + arch/mips/src/pic32mz/hardware/pic32mz_osc.h | 66 +- arch/mips/src/pic32mz/hardware/pic32mz_pps.h | 55 ++ .../mips/src/pic32mz/hardware/pic32mzw1_features.h | 215 ++++++ .../src/pic32mz/hardware/pic32mzw1_memorymap.h | 175 +++++ arch/mips/src/pic32mz/hardware/pic32mzw1_pmuclk.h | 204 +++++ arch/mips/src/pic32mz/hardware/pic32mzw1_pps.h | 191 +++++ arch/mips/src/pic32mz/pic32mz_config.h | 156 ++++ arch/mips/src/pic32mz/pic32mz_head.S | 36 + arch/mips/src/pic32mz/pic32mz_i2c.c | 34 +- arch/mips/src/pic32mz/pic32mz_lowconsole.c | 30 +- arch/mips/src/pic32mz/pic32mz_lowinit.c | 115 +++ arch/mips/src/pic32mz/pic32mz_serial.c | 3 + arch/mips/src/pic32mz/pic32mz_spi.c | 27 +- arch/mips/src/pic32mz/pic32mz_timer.c | 16 +- arch/mips/src/pic32mz/pic32mz_timerisr.c | 8 +- arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.c | 853 +++++++++++++++++++++ arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.h | 72 ++ 26 files changed, 2584 insertions(+), 39 deletions(-) diff --git a/arch/mips/include/pic32mz/chip.h b/arch/mips/include/pic32mz/chip.h index 5fdb9cd71bc..51f06da4ed5 100644 --- a/arch/mips/include/pic32mz/chip.h +++ b/arch/mips/include/pic32mz/chip.h @@ -215,6 +215,47 @@ # define CHIP_NJTAG 1 /* Has JTAG */ # define CHIP_NTRACE 1 /* Has trace capability */ +/* WFI32E01 modules (e.g. WFI32E01PE on the Microchip EV49N51A) are + * PIC32MZ-W1 family members: MIPS32 M-Class core with integrated + * Wi-Fi, a much smaller pin count than EC/EF, and a reorganized SFR map + * (see hardware/pic32mzw1_memorymap.h). Counts below were derived from + * the Microchip PIC32MZ-W_DFP (WFI32E01 variant). + */ + +#elif defined(CONFIG_ARCH_CHIP_WFI32E01) +# undef CHIP_PIC32MZEC /* Not PIC32MZEC family */ +# undef CHIP_PIC32MZEF /* Not PIC32MZEF family */ +# define CHIP_PIC32MZW1 1 /* PIC32MZ-W1 family */ +# define CHIP_BOOTFLASH_KB 0 /* No separate boot FLASH region */ +# define CHIP_PROGFLASH_KB 1024 /* 1024Kb program FLASH */ +# define CHIP_DATAMEM_KB 256 /* 256Kb data memory (shared with Wi-Fi fw) */ +# define CHIP_NTIMERS 7 /* T1-T7 (no T8/T9) */ +# define CHIP_NIC 4 /* 4 input capture */ +# define CHIP_NOC 4 /* 4 output compare */ +# define CHIP_NUARTS 2 /* UART1-UART2 usable; UART3 is a non-contiguous + * low-power/debug UART not yet wired up + * (see pic32mzw1_memorymap.h) */ +# define CHIP_UARTFIFOD 8 /* 8 level deep UART FIFOs */ +# define CHIP_NSPI 2 /* 2 SPI/I2S interfaces */ +# define CHIP_NCAN 1 /* 1 CAN interface */ +# define CHIP_NCRTYPO 1 /* Has crypto support */ +# define CHIP_RNG 1 /* 1 Random number generator */ +# define CHIP_NDMACH 8 /* 8 programmable DMA channels */ +# define CHIP_NUSBDMACHAN 0 /* No dedicated USB DMA channels */ +# define CHIP_NADC10 24 /* 24 ADC channels */ +# define CHIP_NCM 0 /* No analog comparators */ +# define CHIP_USBHSOTG 1 /* 1 USB 2.0 OTG */ +# define CHIP_NI2C 2 /* 2 I2C interfaces */ +# define CHIP_NPMP 0 /* No parallel master port */ +# define CHIP_NEBI 0 /* No external bus interface */ +# define CHIP_NSQI 1 /* 1 Serial quad interface (external flash) */ +# define CHIP_NRTCC 1 /* Has RTCC */ +# define CHIP_NETHERNET 1 /* 1 Ethernet MAC */ +# define CHIP_NPORTS 10 /* GPIO letter index space (only A-C, K populated) */ +# define CHIP_NJTAG 1 /* Has JTAG */ +# define CHIP_NTRACE 0 /* No trace capability */ +# define CHIP_WIFI11N 1 /* Integrated 802.11n Wi-Fi subsystem */ + #else # error "Unrecognized PIC32MZ device" #endif diff --git a/arch/mips/include/pic32mz/irq.h b/arch/mips/include/pic32mz/irq.h index e6a8493d0a8..51a4f582747 100644 --- a/arch/mips/include/pic32mz/irq.h +++ b/arch/mips/include/pic32mz/irq.h @@ -38,6 +38,8 @@ # include <arch/pic32mz/irq_pic32mzxxxec.h> #elif defined(CHIP_PIC32MZEF) # include <arch/pic32mz/irq_pic32mzxxxef.h> +#elif defined(CHIP_PIC32MZW1) +# include <arch/pic32mz/irq_pic32mzw1.h> #else # error "Unknown PIC32MZ family" #endif diff --git a/arch/mips/include/pic32mz/irq_pic32mzw1.h b/arch/mips/include/pic32mz/irq_pic32mzw1.h new file mode 100644 index 00000000000..213fe6c8a75 --- /dev/null +++ b/arch/mips/include/pic32mz/irq_pic32mzw1.h @@ -0,0 +1,247 @@ +/**************************************************************************** + * arch/mips/include/pic32mz/irq_pic32mzw1.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, only indirectly + * through nuttx/irq.h + * + * PIC32MZ-W1's interrupt vector assignment is NOT a renumbered/truncated + * version of EC/EF's - it is a different, non-contiguous table (plenty of + * reserved/unimplemented vector numbers interspersed), transcribed here + * verbatim from the Microchip PIC32MZ-W_DFP (Apache-2.0), + * atdf/WFI32E01.atdf <interrupts> list. Do not assume any EC/EF vector + * number carries over. + */ + +#ifndef __ARCH_MIPS_INCLUDE_PIC32MZ_IRQ_PIC32MZW1_H +#define __ARCH_MIPS_INCLUDE_PIC32MZ_IRQ_PIC32MZW1_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Interrupt vector numbers. These should be used to attach to interrupts + * and to change interrupt priorities. + */ + +#define PIC32MZ_IRQ_CT 0 /* Vector: 0, Core Timer Interrupt */ +#define PIC32MZ_IRQ_CS0 1 /* Vector: 1, Core Software Interrupt 0 */ +#define PIC32MZ_IRQ_CS1 2 /* Vector: 2, Core Software Interrupt 1 */ +#define PIC32MZ_IRQ_INT0 3 /* Vector: 3, External Interrupt 0 */ +#define PIC32MZ_IRQ_T1 4 /* Vector: 4, Timer 1 */ +#define PIC32MZ_IRQ_ICE1 5 /* Vector: 5, Input Capture 1 Error */ +#define PIC32MZ_IRQ_IC1 6 /* Vector: 6, Input Capture 1 */ +#define PIC32MZ_IRQ_OC1 7 /* Vector: 7, Output Compare 1 */ +#define PIC32MZ_IRQ_INT1 8 /* Vector: 8, External Interrupt 1 */ +#define PIC32MZ_IRQ_T2 9 /* Vector: 9, Timer 2 */ + +#define PIC32MZ_IRQ_ICE2 10 /* Vector: 10, Input Capture 2 Error */ +#define PIC32MZ_IRQ_IC2 11 /* Vector: 11, Input Capture 2 */ +#define PIC32MZ_IRQ_OC2 12 /* Vector: 12, Output Compare 2 */ +#define PIC32MZ_IRQ_INT2 13 /* Vector: 13, External Interrupt 2 */ +#define PIC32MZ_IRQ_T3 14 /* Vector: 14, Timer 3 */ +#define PIC32MZ_IRQ_ICE3 15 /* Vector: 15, Input Capture 3 Error */ +#define PIC32MZ_IRQ_IC3 16 /* Vector: 16, Input Capture 3 */ +#define PIC32MZ_IRQ_OC3 17 /* Vector: 17, Output Compare 3 */ +#define PIC32MZ_IRQ_INT3 18 /* Vector: 18, External Interrupt 3 */ +#define PIC32MZ_IRQ_T4 19 /* Vector: 19, Timer 4 */ + +#define PIC32MZ_IRQ_ICE4 20 /* Vector: 20, Input Capture 4 Error */ +#define PIC32MZ_IRQ_IC4 21 /* Vector: 21, Input Capture 4 */ +#define PIC32MZ_IRQ_OC4 22 /* Vector: 22, Output Compare 4 */ +#define PIC32MZ_IRQ_INT4 23 /* Vector: 23, External Interrupt 4 */ +#define PIC32MZ_IRQ_T5 24 /* Vector: 24, Timer 5 */ + +/* Vectors 25-29 reserved/unimplemented */ + +#define PIC32MZ_IRQ_FCE 30 /* Vector: 30, Flash Control Event */ +#define PIC32MZ_IRQ_PREF 31 /* Vector: 31, Prefetch Module */ +#define PIC32MZ_IRQ_PFWCRC 32 /* Vector: 32, Prefetch Module CRC */ +#define PIC32MZ_IRQ_RTCC 33 /* Vector: 33, Real-Time Clock and Calendar */ +#define PIC32MZ_IRQ_USB 34 /* Vector: 34, USB */ + +#define PIC32MZ_IRQ_SPI1F 35 /* Vector: 35, SPI1 Fault */ +#define PIC32MZ_IRQ_SPI1RX 36 /* Vector: 36, SPI1 Receive Done */ +#define PIC32MZ_IRQ_SPI1TX 37 /* Vector: 37, SPI1 Transfer Done */ +#define PIC32MZ_IRQ_U1E 38 /* Vector: 38, UART1 Fault */ +#define PIC32MZ_IRQ_U1RX 39 /* Vector: 39, UART1 Receive Done */ +#define PIC32MZ_IRQ_U1TX 40 /* Vector: 40, UART1 Transfer Done */ +#define PIC32MZ_IRQ_I2C1COL 41 /* Vector: 41, I2C1 Bus Collision Event */ +#define PIC32MZ_IRQ_I2C1S 42 /* Vector: 42, I2C1 Slave Event */ +#define PIC32MZ_IRQ_I2C1M 43 /* Vector: 43, I2C1 Master Event */ +#define PIC32MZ_IRQ_CNA 44 /* Vector: 44, PORTA Change Notice */ +#define PIC32MZ_IRQ_CNB 45 /* Vector: 45, PORTB Change Notice */ +#define PIC32MZ_IRQ_CNC 46 /* Vector: 46, PORTC Change Notice */ +#define PIC32MZ_IRQ_CNK 47 /* Vector: 47, PORTK Change Notice */ + +/* Vectors 48-52 reserved/unimplemented */ + +#define PIC32MZ_IRQ_SPI2F 53 /* Vector: 53, SPI2 Fault */ +#define PIC32MZ_IRQ_SPI2RX 54 /* Vector: 54, SPI2 Receive Done */ +#define PIC32MZ_IRQ_SPI2TX 55 /* Vector: 55, SPI2 Transfer Done */ +#define PIC32MZ_IRQ_U2E 56 /* Vector: 56, UART2 Fault */ +#define PIC32MZ_IRQ_U2RX 57 /* Vector: 57, UART2 Receive Done */ +#define PIC32MZ_IRQ_U2TX 58 /* Vector: 58, UART2 Transfer Done */ +#define PIC32MZ_IRQ_I2C2COL 59 /* Vector: 59, I2C2 Bus Collision Event */ +#define PIC32MZ_IRQ_I2C2S 60 /* Vector: 60, I2C2 Slave Event */ +#define PIC32MZ_IRQ_I2C2M 61 /* Vector: 61, I2C2 Master Event */ +#define PIC32MZ_IRQ_U3E 62 /* Vector: 62, UART3 Fault (not yet supported, see pic32mzw1_memorymap.h) */ +#define PIC32MZ_IRQ_U3RX 63 /* Vector: 63, UART3 Receive Done (not yet supported) */ +#define PIC32MZ_IRQ_U3TX 64 /* Vector: 64, UART3 Transfer Done (not yet supported) */ + +/* Vectors 65-67 reserved/unimplemented */ + +#define PIC32MZ_IRQ_DMA0 68 /* Vector: 68, DMA Channel 0 */ +#define PIC32MZ_IRQ_DMA1 69 /* Vector: 69, DMA Channel 1 */ +#define PIC32MZ_IRQ_DMA2 70 /* Vector: 70, DMA Channel 2 */ +#define PIC32MZ_IRQ_DMA3 71 /* Vector: 71, DMA Channel 3 */ +#define PIC32MZ_IRQ_DMA4 72 /* Vector: 72, DMA Channel 4 */ +#define PIC32MZ_IRQ_DMA5 73 /* Vector: 73, DMA Channel 5 */ +#define PIC32MZ_IRQ_DMA6 74 /* Vector: 74, DMA Channel 6 */ +#define PIC32MZ_IRQ_DMA7 75 /* Vector: 75, DMA Channel 7 */ +#define PIC32MZ_IRQ_T6 76 /* Vector: 76, Timer 6 */ + +/* Vectors 77-79 reserved/unimplemented */ + +#define PIC32MZ_IRQ_T7 80 /* Vector: 80, Timer 7 */ + +/* Vectors 81-82 reserved/unimplemented */ + +#define PIC32MZ_IRQ_RFSMC 83 /* Vector: 83, Wi-Fi SMC */ +#define PIC32MZ_IRQ_RFMAC 84 /* Vector: 84, Wi-Fi MAC */ +#define PIC32MZ_IRQ_CTR1EVENT 85 /* Vector: 85, CTR1 Event */ +#define PIC32MZ_IRQ_RFTM0 86 /* Vector: 86, Wi-Fi Timer 0 */ +#define PIC32MZ_IRQ_RFTM1 87 /* Vector: 87, Wi-Fi Timer 1 */ +#define PIC32MZ_IRQ_RFTM2 88 /* Vector: 88, Wi-Fi Timer 2 */ +#define PIC32MZ_IRQ_RFTM3 89 /* Vector: 89, Wi-Fi Timer 3 */ +#define PIC32MZ_IRQ_CTR1TRG 90 /* Vector: 90, CTR1 Trigger */ +#define PIC32MZ_IRQ_RFWCOE 91 /* Vector: 91, Wi-Fi Wake-up/Coexistence */ +#define PIC32MZ_IRQ_ADC 92 /* Vector: 92, ADC */ + +/* Vector 93 reserved/unimplemented */ + +#define PIC32MZ_IRQ_ADCDC1 94 /* Vector: 94, ADC Digital Comparator 1 */ +#define PIC32MZ_IRQ_ADCDC2 95 /* Vector: 95, ADC Digital Comparator 2 */ +#define PIC32MZ_IRQ_ADCDF1 96 /* Vector: 96, ADC Digital Filter 1 */ +#define PIC32MZ_IRQ_ADCDF2 97 /* Vector: 97, ADC Digital Filter 2 */ + +/* Vectors 98-99 reserved/unimplemented */ + +#define PIC32MZ_IRQ_ADCFAULT 100 /* Vector: 100, ADC Fault */ +#define PIC32MZ_IRQ_ADCEOS 101 /* Vector: 101, ADC End of Scan */ +#define PIC32MZ_IRQ_ADCARDY 102 /* Vector: 102, ADC Analog-to-Digital Ready */ +#define PIC32MZ_IRQ_ADCURDY 103 /* Vector: 103, ADC Digital Filter Ready */ +#define PIC32MZ_IRQ_ADCDMA 104 /* Vector: 104, ADC DMA */ + +/* Vector 105 reserved/unimplemented */ + +#define PIC32MZ_IRQ_ADCDATA0 106 /* Vector: 106, ADC Data 0 */ +#define PIC32MZ_IRQ_ADCDATA1 107 /* Vector: 107, ADC Data 1 */ +#define PIC32MZ_IRQ_ADCDATA2 108 /* Vector: 108, ADC Data 2 */ +#define PIC32MZ_IRQ_ADCDATA3 109 /* Vector: 109, ADC Data 3 */ +#define PIC32MZ_IRQ_ADCDATA4 110 /* Vector: 110, ADC Data 4 */ +#define PIC32MZ_IRQ_ADCDATA5 111 /* Vector: 111, ADC Data 5 */ +#define PIC32MZ_IRQ_ADCDATA6 112 /* Vector: 112, ADC Data 6 */ +#define PIC32MZ_IRQ_ADCDATA7 113 /* Vector: 113, ADC Data 7 */ +#define PIC32MZ_IRQ_ADCDATA8 114 /* Vector: 114, ADC Data 8 */ +#define PIC32MZ_IRQ_ADCDATA9 115 /* Vector: 115, ADC Data 9 */ + +#define PIC32MZ_IRQ_ADCDATA10 116 /* Vector: 116, ADC Data 10 */ +#define PIC32MZ_IRQ_ADCDATA11 117 /* Vector: 117, ADC Data 11 */ +#define PIC32MZ_IRQ_ADCDATA12 118 /* Vector: 118, ADC Data 12 */ +#define PIC32MZ_IRQ_ADCDATA13 119 /* Vector: 119, ADC Data 13 */ +#define PIC32MZ_IRQ_ADCDATA14 120 /* Vector: 120, ADC Data 14 */ +#define PIC32MZ_IRQ_ADCDATA15 121 /* Vector: 121, ADC Data 15 */ +#define PIC32MZ_IRQ_ADCDATA16 122 /* Vector: 122, ADC Data 16 */ +#define PIC32MZ_IRQ_ADCDATA17 123 /* Vector: 123, ADC Data 17 */ +#define PIC32MZ_IRQ_ADCDATA18 124 /* Vector: 124, ADC Data 18 */ +#define PIC32MZ_IRQ_ADCDATA19 125 /* Vector: 125, ADC Data 19 */ + +#define PIC32MZ_IRQ_ADCDATA20 126 /* Vector: 126, ADC Data 20 */ +#define PIC32MZ_IRQ_ADCDATA21 127 /* Vector: 127, ADC Data 21 */ +#define PIC32MZ_IRQ_ADCDATA22 128 /* Vector: 128, ADC Data 22 */ +#define PIC32MZ_IRQ_ADCDATA23 129 /* Vector: 129, ADC Data 23 */ + +/* Vectors 130-141 reserved/unimplemented */ + +#define PIC32MZ_IRQ_CAN1 142 /* Vector: 142, CAN1 */ +#define PIC32MZ_IRQ_CAN2RX 143 /* Vector: 143, CAN2 RX (CAN2 not present on WFI32E01) */ +#define PIC32MZ_IRQ_CAN2TX 144 /* Vector: 144, CAN2 TX (CAN2 not present on WFI32E01) */ +#define PIC32MZ_IRQ_CAN2MISC 145 /* Vector: 145, CAN2 Misc (CAN2 not present on WFI32E01) */ + +/* Vectors 146-149 reserved/unimplemented */ + +#define PIC32MZ_IRQ_SQI1 150 /* Vector: 150, SQI1 */ + +/* Vector 151 reserved/unimplemented */ + +#define PIC32MZ_IRQ_PTG0STEP 152 /* Vector: 152, PTG0 Step */ +#define PIC32MZ_IRQ_PTG0WDT 153 /* Vector: 153, PTG0 Watchdog */ +#define PIC32MZ_IRQ_PTG0TRG0 154 /* Vector: 154, PTG0 Trigger 0 */ +#define PIC32MZ_IRQ_PTG0TRG1 155 /* Vector: 155, PTG0 Trigger 1 */ +#define PIC32MZ_IRQ_PTG0TRG2 156 /* Vector: 156, PTG0 Trigger 2 */ +#define PIC32MZ_IRQ_PTG0TRG3 157 /* Vector: 157, PTG0 Trigger 3 */ + +/* Vectors 158-161 reserved/unimplemented */ + +#define PIC32MZ_IRQ_CORECOUNT 162 /* Vector: 162, Core Performance Counter */ +#define PIC32MZ_IRQ_COREFDC 163 /* Vector: 163, Core Fast Debug Channel */ +#define PIC32MZ_IRQ_CRYPTO 164 /* Vector: 164, Crypto Engine */ +#define PIC32MZ_IRQ_ETH 165 /* Vector: 165, Ethernet MAC */ +#define PIC32MZ_IRQ_CRYPTO1 166 /* Vector: 166, Crypto Engine 1 */ +#define PIC32MZ_IRQ_CRYPTO1F 167 /* Vector: 167, Crypto Engine 1 Fault */ +#define PIC32MZ_IRQ_CVDEVENT 168 /* Vector: 168, Capacitive Voltage Divider Event */ + +#define NR_IRQS 169 + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_MIPS_INCLUDE_PIC32MZ_IRQ_PIC32MZW1_H */ diff --git a/arch/mips/src/pic32mz/Kconfig b/arch/mips/src/pic32mz/Kconfig index f3d55358cf1..57b17ef86fe 100644 --- a/arch/mips/src/pic32mz/Kconfig +++ b/arch/mips/src/pic32mz/Kconfig @@ -48,6 +48,14 @@ config ARCH_CHIP_PIC32MZ2048EFM Microchip PIC32MZ2048EFH with Crypto Engine (MIPS32 M5150) such as the PIC32MZ2048EFM144-I/PH used in the PIC32MZ EF STARTER KIT +config ARCH_CHIP_WFI32E01 + bool "WFI32E01" + select ARCH_CHIP_PIC32MZW1 + ---help--- + Microchip WFI32E01 (PIC32MZ-W1 family, MIPS32 M-Class core with + integrated 802.11n Wi-Fi), as found in the WFI32E01PC/PE/UC/UE + modules. + endchoice config ARCH_CHIP_PIC32MZEC @@ -64,6 +72,13 @@ config ARCH_CHIP_PIC32MZEF select MIPS32_HAVE_ICACHE select MIPS32_HAVE_DCACHE +config ARCH_CHIP_PIC32MZW1 + bool + default n + select ARCH_MIPS_MICROAPTIV + select MIPS32_HAVE_ICACHE + select MIPS32_HAVE_DCACHE + config PIC32MZ_MVEC bool default n @@ -84,6 +99,38 @@ config PIC32MZ_T1 bool default y +config PIC32MZ_W1_PMU_MLDO + bool "PIC32MZ-W1: keep the PMU in its power-on MLDO mode" + default n + depends on ARCH_CHIP_PIC32MZW1 + ---help--- + Skip the regulator reconfiguration (MLDO -> buck on B0 silicon, + MLDO trim update on A1/G) and leave the PMU in the MLDO mode it + powers up in with factory-calibrated settings (DS70005425 36.1). + Less efficient, but uses only documented behaviour. + +config PIC32MZ_W1_FLASH_WAITSTATES + int "PIC32MZ-W1: program flash wait states" + default 5 + range 0 7 + depends on ARCH_CHIP_PIC32MZW1 + ---help--- + Value written to PRECON.PFMWS. DS70005425 gives no + SYSCLK-to-wait-state table for PIC32MZ-W1; the default of 5 at + 200 MHz SYSCLK is the value used by Microchip's + WFI32_Ethernet_Wi-Fi_Bridge_OOB example. The reset value, 7, is + the most conservative choice. + +config PIC32MZ_W1_BOOTTRACE + bool "PIC32MZ-W1 early boot trace on UART1" + default n + depends on ARCH_CHIP_PIC32MZW1 && PIC32MZ_UART1 + ---help--- + Bring-up aid. Right after reset, run UART1 from the internal FRC + (independent of the PLLs) at ~115200 8N1 and emit one character + per PMU/clock bring-up step, so a hang can be located without a + debugger. The normal console takes over afterwards. + menu "PIC32MZ Peripheral Support" config PIC32MZ_WDT diff --git a/arch/mips/src/pic32mz/Make.defs b/arch/mips/src/pic32mz/Make.defs index b3af91a8bf7..44e89094ef4 100644 --- a/arch/mips/src/pic32mz/Make.defs +++ b/arch/mips/src/pic32mz/Make.defs @@ -63,6 +63,10 @@ CHIP_CSRCS += pic32mz_lowconsole.c pic32mz_serial.c # Configuration-dependent PIC32MZ files +ifeq ($(CONFIG_ARCH_CHIP_WFI32E01),y) +CHIP_CSRCS += pic32mz_wfi32_pwrclk.c +endif + ifeq ($(CONFIG_PIC32MZ_GPIOIRQ),y) CHIP_CSRCS += pic32mz_gpioirq.c endif diff --git a/arch/mips/src/pic32mz/hardware/pic32mz_features.h b/arch/mips/src/pic32mz/hardware/pic32mz_features.h index ca1bae9992c..a085f2f7fee 100644 --- a/arch/mips/src/pic32mz/hardware/pic32mz_features.h +++ b/arch/mips/src/pic32mz/hardware/pic32mz_features.h @@ -33,6 +33,8 @@ # include "hardware/pic32mzec_features.h" #elif defined(CONFIG_ARCH_CHIP_PIC32MZEF) # include "hardware/pic32mzef_features.h" +#elif defined(CONFIG_ARCH_CHIP_PIC32MZW1) +# include "hardware/pic32mzw1_features.h" #else # error Unknown PIC32MZ family #endif diff --git a/arch/mips/src/pic32mz/hardware/pic32mz_i2c.h b/arch/mips/src/pic32mz/hardware/pic32mz_i2c.h index 2e638ad8c69..145fc6b428e 100644 --- a/arch/mips/src/pic32mz/hardware/pic32mz_i2c.h +++ b/arch/mips/src/pic32mz/hardware/pic32mz_i2c.h @@ -83,12 +83,20 @@ /* I2C Peripheral Addresses *************************************************/ -#define PIC32MZ_I2Cn_K1BASE(n) (PIC32MZ_I2C_K1BASE+PIC32MZ_I2Cn_OFFSET(n)) +/* On PIC32MZ EC/EF the I2C modules are 0x200 apart, starting at + * PIC32MZ_I2C_K1BASE. On PIC32MZ-W1 they are not contiguous (I2C1 is on + * peripheral bus 2, I2C2 on bus 3) and the chip memory map defines + * PIC32MZ_I2Cn_K1BASE for each module instead. + */ + +#ifdef PIC32MZ_I2C_K1BASE +# define PIC32MZ_I2Cn_K1BASE(n) (PIC32MZ_I2C_K1BASE+PIC32MZ_I2Cn_OFFSET(n)) # define PIC32MZ_I2C1_K1BASE (PIC32MZ_I2C_K1BASE+PIC32MZ_I2C1_OFFSET) # define PIC32MZ_I2C2_K1BASE (PIC32MZ_I2C_K1BASE+PIC32MZ_I2C2_OFFSET) # define PIC32MZ_I2C3_K1BASE (PIC32MZ_I2C_K1BASE+PIC32MZ_I2C3_OFFSET) # define PIC32MZ_I2C4_K1BASE (PIC32MZ_I2C_K1BASE+PIC32MZ_I2C4_OFFSET) # define PIC32MZ_I2C5_K1BASE (PIC32MZ_I2C_K1BASE+PIC32MZ_I2C5_OFFSET) +#endif /* I2C Register Addresses ***************************************************/ diff --git a/arch/mips/src/pic32mz/hardware/pic32mz_ioport.h b/arch/mips/src/pic32mz/hardware/pic32mz_ioport.h index 842f851ba33..029ddaa9c38 100644 --- a/arch/mips/src/pic32mz/hardware/pic32mz_ioport.h +++ b/arch/mips/src/pic32mz/hardware/pic32mz_ioport.h @@ -60,7 +60,19 @@ # define PIC32MZ_IOPORTG_OFFSET 0x0600 # define PIC32MZ_IOPORTH_OFFSET 0x0700 # define PIC32MZ_IOPORTJ_OFFSET 0x0800 + +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +/* The PIC32MZ-W1 family only implements PORTA, PORTB, PORTC and PORTK. + * PORTK is not the 10th 0x100 block as on EC/EF parts; it follows PORTC + * at offset 0x300. The PORTD-PORTJ offsets above are therefore + * unimplemented placeholders on this family (other peripherals live + * there) and must never be referenced. + */ + +# define PIC32MZ_IOPORTK_OFFSET 0x0300 +#else # define PIC32MZ_IOPORTK_OFFSET 0x0900 +#endif /* Register Offsets *********************************************************/ diff --git a/arch/mips/src/pic32mz/hardware/pic32mz_memorymap.h b/arch/mips/src/pic32mz/hardware/pic32mz_memorymap.h index e61801aea3b..5e7b4472880 100644 --- a/arch/mips/src/pic32mz/hardware/pic32mz_memorymap.h +++ b/arch/mips/src/pic32mz/hardware/pic32mz_memorymap.h @@ -33,6 +33,8 @@ # include "hardware/pic32mzec_memorymap.h" #elif defined(CONFIG_ARCH_CHIP_PIC32MZEF) # include "hardware/pic32mzef_memorymap.h" +#elif defined(CONFIG_ARCH_CHIP_PIC32MZW1) +# include "hardware/pic32mzw1_memorymap.h" #else # error "Unknown PIC32MZ family" #endif diff --git a/arch/mips/src/pic32mz/hardware/pic32mz_osc.h b/arch/mips/src/pic32mz/hardware/pic32mz_osc.h index d3c2f7b880e..d5ca32ce279 100644 --- a/arch/mips/src/pic32mz/hardware/pic32mz_osc.h +++ b/arch/mips/src/pic32mz/hardware/pic32mz_osc.h @@ -40,26 +40,60 @@ #define PIC32MZ_OSCCON_OFFSET 0x0000 /* Oscillator control register offset */ #define PIC32MZ_OSCTUN_OFFSET 0x0010 /* FRC tuning register offset */ #define PIC32MZ_SPLLCON_OFFSET 0x0020 /* System PLL control register */ -#define PIC32MZ_REFO1CON_OFFSET 0x0080 /* Reference oscillator control register 1 */ -#define PIC32MZ_REFO1TRIM_OFFSET 0x00a0 /* Reference oscillator trim register 1 */ -#define PIC32MZ_REFO2CON_OFFSET 0x00b0 /* Reference oscillator control register 2 */ -#define PIC32MZ_REFO2TRIM_OFFSET 0x00c0 /* Reference oscillator trim register 2 */ -#define PIC32MZ_REFO3CON_OFFSET 0x00d0 /* Reference oscillator control register 3 */ -#define PIC32MZ_REFO3TRIM_OFFSET 0x00e0 /* Reference oscillator trim register 3 */ -#define PIC32MZ_REFO4CON_OFFSET 0x00f0 /* Reference oscillator control register 4 */ -#define PIC32MZ_REFO4TRIM_OFFSET 0x0100 /* Reference oscillator trim register 4 */ -#define PIC32MZ_PB1DIV_OFFSET 0x0100 /* Peripheral bus 1 clock divisor control register */ -#define PIC32MZ_PB2DIV_OFFSET 0x0110 /* Peripheral bus 2 clock divisor control register */ -#define PIC32MZ_PB3DIV_OFFSET 0x0120 /* Peripheral bus 3 clock divisor control register */ -#define PIC32MZ_PB4DIV_OFFSET 0x0130 /* Peripheral bus 4 clock divisor control register */ -#define PIC32MZ_PB5DIV_OFFSET 0x0140 /* Peripheral bus 5 clock divisor control register */ -#define PIC32MZ_PB6DIV_OFFSET 0x0150 /* Peripheral bus 6 clock divisor control register */ -#define PIC32MZ_PB7DIV_OFFSET 0x0160 /* Peripheral bus 7 clock divisor control register */ -#define PIC32MZ_PB8DIV_OFFSET 0x0170 /* Peripheral bus 8 clock divisor control register */ + +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +/* On PIC32MZ-W1, everything from REFO1CON onward is shifted +0x20 + * relative to EC/EF (confirmed against the real WFI32E01 SFR + * addresses). W1 also only implements PB1DIV-PB6DIV (no PB7/PB8). + */ + +# define PIC32MZ_REFO1CON_OFFSET 0x00a0 +# define PIC32MZ_REFO1TRIM_OFFSET 0x00b0 +# define PIC32MZ_REFO2CON_OFFSET 0x00c0 +# define PIC32MZ_REFO2TRIM_OFFSET 0x00d0 +# define PIC32MZ_REFO3CON_OFFSET 0x00e0 +# define PIC32MZ_REFO3TRIM_OFFSET 0x00f0 +# define PIC32MZ_REFO4CON_OFFSET 0x0100 +# define PIC32MZ_REFO4TRIM_OFFSET 0x0110 +# define PIC32MZ_PB1DIV_OFFSET 0x0120 +# define PIC32MZ_PB2DIV_OFFSET 0x0130 +# define PIC32MZ_PB3DIV_OFFSET 0x0140 +# define PIC32MZ_PB4DIV_OFFSET 0x0150 +# define PIC32MZ_PB5DIV_OFFSET 0x0160 +# define PIC32MZ_PB6DIV_OFFSET 0x0170 + +/* W1 has no PB7/PB8; these are unused placeholders so that the + * unconditional PIC32MZ_PB7DIV/PB8DIV address macros below still + * compile (gated off at the board.h level via BOARD_PBCLKn_ENABLE). + */ + +# define PIC32MZ_PB7DIV_OFFSET 0x0170 +# define PIC32MZ_PB8DIV_OFFSET 0x0170 +#else +# define PIC32MZ_REFO1CON_OFFSET 0x0080 /* Reference oscillator control register 1 */ +# define PIC32MZ_REFO1TRIM_OFFSET 0x00a0 /* Reference oscillator trim register 1 */ +# define PIC32MZ_REFO2CON_OFFSET 0x00b0 /* Reference oscillator control register 2 */ +# define PIC32MZ_REFO2TRIM_OFFSET 0x00c0 /* Reference oscillator trim register 2 */ +# define PIC32MZ_REFO3CON_OFFSET 0x00d0 /* Reference oscillator control register 3 */ +# define PIC32MZ_REFO3TRIM_OFFSET 0x00e0 /* Reference oscillator trim register 3 */ +# define PIC32MZ_REFO4CON_OFFSET 0x00f0 /* Reference oscillator control register 4 */ +# define PIC32MZ_REFO4TRIM_OFFSET 0x0100 /* Reference oscillator trim register 4 */ +# define PIC32MZ_PB1DIV_OFFSET 0x0100 /* Peripheral bus 1 clock divisor control register */ +# define PIC32MZ_PB2DIV_OFFSET 0x0110 /* Peripheral bus 2 clock divisor control register */ +# define PIC32MZ_PB3DIV_OFFSET 0x0120 /* Peripheral bus 3 clock divisor control register */ +# define PIC32MZ_PB4DIV_OFFSET 0x0130 /* Peripheral bus 4 clock divisor control register */ +# define PIC32MZ_PB5DIV_OFFSET 0x0140 /* Peripheral bus 5 clock divisor control register */ +# define PIC32MZ_PB6DIV_OFFSET 0x0150 /* Peripheral bus 6 clock divisor control register */ +# define PIC32MZ_PB7DIV_OFFSET 0x0160 /* Peripheral bus 7 clock divisor control register */ +# define PIC32MZ_PB8DIV_OFFSET 0x0170 /* Peripheral bus 8 clock divisor control register */ +#endif /* Register Addresses *******************************************************/ #define PIC32MZ_OSCCON (PIC32MZ_OSC_K1BASE+PIC32MZ_OSCCON_OFFSET) +#define PIC32MZ_OSCCONCLR (PIC32MZ_OSCCON+4) +#define PIC32MZ_OSCCONSET (PIC32MZ_OSCCON+8) +#define PIC32MZ_OSCCONINV (PIC32MZ_OSCCON+12) #define PIC32MZ_OSCTUN (PIC32MZ_OSC_K1BASE+PIC32MZ_OSCTUN_OFFSET) #define PIC32MZ_SPLLCON (PIC32MZ_OSC_K1BASE+PIC32MZ_SPLLCON_OFFSET) diff --git a/arch/mips/src/pic32mz/hardware/pic32mz_pps.h b/arch/mips/src/pic32mz/hardware/pic32mz_pps.h index 816bcaa75da..1e11aca941d 100644 --- a/arch/mips/src/pic32mz/hardware/pic32mz_pps.h +++ b/arch/mips/src/pic32mz/hardware/pic32mz_pps.h @@ -37,6 +37,8 @@ # include "hardware/pic32mzec_pps.h" #elif defined(CONFIG_ARCH_CHIP_PIC32MZEF) # include "hardware/pic32mzef_pps.h" +#elif defined(CONFIG_ARCH_CHIP_PIC32MZW1) +# include "hardware/pic32mzw1_pps.h" #else # error Unknown PIC32MZ family #endif @@ -88,6 +90,58 @@ * NOTE: This is written in the same odd macro forms as above for the same * reason. */ +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +/* W1 only bonds out PORTA/PORTB/PORTK (see hardware/pic32mzw1_pps.h) - + * RPC/D/E/F/G pin macros referenced by the EC/EF version of this macro + * below do not exist for this chip. + */ + +#define __PPS_OUTPUT_REGADDR_TO_GPIO(a,b) ((uint32_t)( \ + ((b) == PIC32MZ_RPA0R) ? (GPIO_PORTA | GPIO_PIN0) : \ + ((b) == PIC32MZ_RPA1R) ? (GPIO_PORTA | GPIO_PIN1) : \ + ((b) == PIC32MZ_RPA2R) ? (GPIO_PORTA | GPIO_PIN2) : \ + ((b) == PIC32MZ_RPA3R) ? (GPIO_PORTA | GPIO_PIN3) : \ + ((b) == PIC32MZ_RPA4R) ? (GPIO_PORTA | GPIO_PIN4) : \ + ((b) == PIC32MZ_RPA5R) ? (GPIO_PORTA | GPIO_PIN5) : \ + ((b) == PIC32MZ_RPA10R) ? (GPIO_PORTA | GPIO_PIN10) : \ + ((b) == PIC32MZ_RPA11R) ? (GPIO_PORTA | GPIO_PIN11) : \ + ((b) == PIC32MZ_RPA12R) ? (GPIO_PORTA | GPIO_PIN12) : \ + ((b) == PIC32MZ_RPA13R) ? (GPIO_PORTA | GPIO_PIN13) : \ + ((b) == PIC32MZ_RPA14R) ? (GPIO_PORTA | GPIO_PIN14) : \ + ((b) == PIC32MZ_RPA15R) ? (GPIO_PORTA | GPIO_PIN15) : \ + ((b) == PIC32MZ_RPB0R) ? (GPIO_PORTB | GPIO_PIN0) : \ + ((b) == PIC32MZ_RPB1R) ? (GPIO_PORTB | GPIO_PIN1) : \ + ((b) == PIC32MZ_RPB2R) ? (GPIO_PORTB | GPIO_PIN2) : \ + ((b) == PIC32MZ_RPB3R) ? (GPIO_PORTB | GPIO_PIN3) : \ + ((b) == PIC32MZ_RPB4R) ? (GPIO_PORTB | GPIO_PIN4) : \ + ((b) == PIC32MZ_RPB5R) ? (GPIO_PORTB | GPIO_PIN5) : \ + ((b) == PIC32MZ_RPB6R) ? (GPIO_PORTB | GPIO_PIN6) : \ + ((b) == PIC32MZ_RPB7R) ? (GPIO_PORTB | GPIO_PIN7) : \ + ((b) == PIC32MZ_RPB8R) ? (GPIO_PORTB | GPIO_PIN8) : \ + ((b) == PIC32MZ_RPB9R) ? (GPIO_PORTB | GPIO_PIN9) : \ + ((b) == PIC32MZ_RPB10R) ? (GPIO_PORTB | GPIO_PIN10) : \ + ((b) == PIC32MZ_RPB11R) ? (GPIO_PORTB | GPIO_PIN11) : \ + ((b) == PIC32MZ_RPB12R) ? (GPIO_PORTB | GPIO_PIN12) : \ + ((b) == PIC32MZ_RPB13R) ? (GPIO_PORTB | GPIO_PIN13) : \ + ((b) == PIC32MZ_RPB14R) ? (GPIO_PORTB | GPIO_PIN14) : \ + ((b) == PIC32MZ_RPK0R) ? (GPIO_PORTK | GPIO_PIN0) : \ + ((b) == PIC32MZ_RPK1R) ? (GPIO_PORTK | GPIO_PIN1) : \ + ((b) == PIC32MZ_RPK2R) ? (GPIO_PORTK | GPIO_PIN2) : \ + ((b) == PIC32MZ_RPK3R) ? (GPIO_PORTK | GPIO_PIN3) : \ + ((b) == PIC32MZ_RPK4R) ? (GPIO_PORTK | GPIO_PIN4) : \ + ((b) == PIC32MZ_RPK5R) ? (GPIO_PORTK | GPIO_PIN5) : \ + ((b) == PIC32MZ_RPK6R) ? (GPIO_PORTK | GPIO_PIN6) : \ + ((b) == PIC32MZ_RPK7R) ? (GPIO_PORTK | GPIO_PIN7) : \ + ((b) == PIC32MZ_RPK8R) ? (GPIO_PORTK | GPIO_PIN8) : \ + ((b) == PIC32MZ_RPK9R) ? (GPIO_PORTK | GPIO_PIN9) : \ + ((b) == PIC32MZ_RPK10R) ? (GPIO_PORTK | GPIO_PIN10) : \ + ((b) == PIC32MZ_RPK11R) ? (GPIO_PORTK | GPIO_PIN11) : \ + ((b) == PIC32MZ_RPK12R) ? (GPIO_PORTK | GPIO_PIN12) : \ + ((b) == PIC32MZ_RPK13R) ? (GPIO_PORTK | GPIO_PIN13) : \ + ((b) == PIC32MZ_RPK14R) ? (GPIO_PORTK | GPIO_PIN14) : \ + 0 \ + )) +#else #define __PPS_OUTPUT_REGADDR_TO_GPIO(a,b) ((uint32_t)( \ ((b) == PIC32MZ_RPA14R) ? (GPIO_PORTA | GPIO_PIN14) : \ ((b) == PIC32MZ_RPA15R) ? (GPIO_PORTA | GPIO_PIN15) : \ @@ -144,6 +198,7 @@ ((b) == PIC32MZ_RPG9R) ? (GPIO_PORTG | GPIO_PIN9) : \ 0 \ )) +#endif /* CONFIG_ARCH_CHIP_PIC32MZW1 */ #define PPS_OUTPUT_REGADDR_TO_GPIO(a) __PPS_OUTPUT_REGADDR_TO_GPIO(a) /**************************************************************************** diff --git a/arch/mips/src/pic32mz/hardware/pic32mzw1_features.h b/arch/mips/src/pic32mz/hardware/pic32mzw1_features.h new file mode 100644 index 00000000000..1e249f12619 --- /dev/null +++ b/arch/mips/src/pic32mz/hardware/pic32mzw1_features.h @@ -0,0 +1,215 @@ +/**************************************************************************** + * arch/mips/src/pic32mz/hardware/pic32mzw1_features.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* PIC32MZ-W1 does NOT use the classic PIC32MZ EC/EF DEVCFG0-3 fuse model. + * Its boot-flash configuration words (FUSERID, DEVCFG4, DEVCFG2, DEVCFG1, + * DEVCFG0, FBCFG0, FCPN0, FSIGN0 - note there is no DEVCFG3) are copied + * into runtime registers at reset (DEVCFG0 -> CFGCON0, DEVCFG1 -> CFGCON1, + * DEVCFG2 -> CFGCON2, DEVCFG4 -> CFGCON4, FBCFG0 -> BCFG0; DS70005425 + * Table 6-2 note 1). Note that the data sheet numbers the boot-flash words + * differently (BFDEVCFG0..5); the names here follow the DFP. + * + * The words themselves are emitted by pic32mz_head.S from the values + * composed in pic32mz_config.h. Register addresses and field layouts are + * from the Microchip PIC32MZ-W_DFP (Apache-2.0), proc/pwfi32e01.h and + * xc32/WFI32E01/configuration.data, cross-checked with DS70005425 chapters + * 6 and 38. + */ + +#ifndef __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_FEATURES_H +#define __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_FEATURES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include "hardware/pic32mz_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets (SFR PIC32MZ_CONFIG_K1BASE) *****************************/ + +#define PIC32MZ_CFGCON0_OFFSET 0x0000 +#define PIC32MZ_CFGCON1_OFFSET 0x0010 +#define PIC32MZ_CFGCON2_OFFSET 0x0020 +#define PIC32MZ_CFGCON3_OFFSET 0x0030 +#define PIC32MZ_DEVID_OFFSET 0x0060 +#define PIC32MZ_SYSKEY_OFFSET 0x0080 +#define PIC32MZ_PMD1_OFFSET 0x0090 +#define PIC32MZ_PMD2_OFFSET 0x00a0 +#define PIC32MZ_PMD3_OFFSET 0x00b0 + +/* Register Addresses *******************************************************/ + +#define PIC32MZ_CFGCON0 (PIC32MZ_CONFIG_K1BASE + PIC32MZ_CFGCON0_OFFSET) +#define PIC32MZ_CFGCON1 (PIC32MZ_CONFIG_K1BASE + PIC32MZ_CFGCON1_OFFSET) +#define PIC32MZ_CFGCON2 (PIC32MZ_CONFIG_K1BASE + PIC32MZ_CFGCON2_OFFSET) +#define PIC32MZ_CFGCON3 (PIC32MZ_CONFIG_K1BASE + PIC32MZ_CFGCON3_OFFSET) +#define PIC32MZ_DEVID (PIC32MZ_CONFIG_K1BASE + PIC32MZ_DEVID_OFFSET) +#define PIC32MZ_SYSKEY (PIC32MZ_CONFIG_K1BASE + PIC32MZ_SYSKEY_OFFSET) +#define PIC32MZ_PMD1 (PIC32MZ_CONFIG_K1BASE + PIC32MZ_PMD1_OFFSET) +#define PIC32MZ_PMD2 (PIC32MZ_CONFIG_K1BASE + PIC32MZ_PMD2_OFFSET) +#define PIC32MZ_PMD3 (PIC32MZ_CONFIG_K1BASE + PIC32MZ_PMD3_OFFSET) + +/* CFGCON0 bitfields (identical layout to DEVCFG0) **************************/ + +#define CFGCON0_TDOEN (1 << 0) +#define CFGCON0_TROEN (1 << 2) +#define CFGCON0_JTAGEN (1 << 3) +#define CFGCON0_USBSSEN (1 << 8) +#define CFGCON0_PMULOCK (1 << 10) +#define CFGCON0_PGLOCK (1 << 11) +#define CFGCON0_PMDLOCK (1 << 12) +#define CFGCON0_IOLOCK (1 << 13) +#define CFGCON0_CANFDDIV_SHIFT (20) +#define CFGCON0_CANFDDIV_MASK (3 << CFGCON0_CANFDDIV_SHIFT) +#define CFGCON0_UPLLHWMD (1 << 24) +#define CFGCON0_SPLLHWMD (1 << 25) +#define CFGCON0_BTPLLHWMD (1 << 26) +#define CFGCON0_ETHPLLHWMD (1 << 27) + +/* DEVID bitfields (Device identification register) *************************/ + +#define DEVID_PARTNUM_SHIFT (20) +#define DEVID_PARTNUM_MASK (0xff << DEVID_PARTNUM_SHIFT) +#define DEVID_VER_SHIFT (28) +#define DEVID_VER_MASK (0xf << DEVID_VER_SHIFT) + +/* Known WFI32E01/PIC32MZW1 silicon revisions (DEVID bits 20-27). The + * data sheet (DS70005425P Reg 38-7) only documents DEVID[27:0] as a whole; + * these values and their A1/B0/G meaning come from Microchip's + * WFI32_Ethernet_Wi-Fi_Bridge_OOB example firmware, which uses them to + * select the PMU/clock bring-up sequence (see pic32mz_wfi32_pwrclk.c). + */ + +#define DEVID_PARTNUM_PIC32MZW1_A1 0x8c +#define DEVID_PARTNUM_PIC32MZW1_B0 0xa4 +#define DEVID_PARTNUM_PIC32MZW1_G 0xa6 + +/* SYSKEY unlock/lock sequence (standard across the whole PIC32 family) */ + +#define UNLOCK_SYSKEY_0 (0xaa996655ul) +#define UNLOCK_SYSKEY_1 (0x556699aaul) +#define LOCK_SYSKEY (0x33333333ul) + +/* Boot-flash configuration words *******************************************/ + +/* Primary copy at 0xbfc55f88; offsets from the start of the block. (An + * alternate copy lives at 0xbfc55e88; programming tools write it with DFP + * defaults, so NuttX does not emit it.) + */ + +#define W1CFG_FUSERID_OFFSET 0x00 +#define W1CFG_DEVCFG4_OFFSET 0x04 +#define W1CFG_DEVCFG2_OFFSET 0x08 +#define W1CFG_DEVCFG1_OFFSET 0x0c +#define W1CFG_DEVCFG0_OFFSET 0x10 +#define W1CFG_FBCFG0_OFFSET 0x14 +#define W1CFG_FCPN0_OFFSET 0x34 +#define W1CFG_FSIGN0_OFFSET 0x54 + +/* FUSERID */ + +#define FUSERID_USERID_SHIFT (0) /* Bits 0-15 */ +#define FUSERID_USERID_MASK (0xffff << FUSERID_USERID_SHIFT) + +/* DEVCFG4 (-> CFGCON4) */ + +#define DEVCFG4_SOSCCFG_SHIFT (0) /* Bits 0-7: SOSC configuration */ +#define DEVCFG4_VBZPBOREN (1 << 19) /* VBAT zero-power BOR enable */ +#define DEVCFG4_DSZPBOREN (1 << 20) /* Deep Sleep zero-power BOR enable */ +#define DEVCFG4_DSWDTPS_SHIFT (21) /* Bits 21-25: DSWDT postscaler */ +#define DEVCFG4_DSWDTOSC (1 << 26) /* DSWDT clock: 1 = LPRC */ +#define DEVCFG4_DSWDTEN (1 << 27) /* Deep Sleep WDT enable */ +#define DEVCFG4_DSEN (1 << 28) /* Deep Sleep enable */ +#define DEVCFG4_SOSCEN (1 << 30) /* SOSC enable */ + +/* DEVCFG2 (-> CFGCON2) */ + +#define DEVCFG2_DMTINTV_SHIFT (3) /* Bits 3-5: DMT window interval */ +#define DEVCFG2_POSCMOD_SHIFT (8) /* Bits 8-9: POSC mode */ +# define DEVCFG2_POSCMOD_HS (2 << DEVCFG2_POSCMOD_SHIFT) +# define DEVCFG2_POSCMOD_OFF (3 << DEVCFG2_POSCMOD_SHIFT) +#define DEVCFG2_WDTRMCS_SHIFT (10) /* Bits 10-11: WDT run-mode clock */ +#define DEVCFG2_SOSCSEL (1 << 12) /* SOSC: 1 = crystal */ +#define DEVCFG2_WAKE2SPD (1 << 13) /* Wake to speed */ +#define DEVCFG2_CKSWEN (1 << 14) /* Software clock switching */ +#define DEVCFG2_FSCMEN (1 << 15) /* Fail-safe clock monitor */ +#define DEVCFG2_WDTPS_SHIFT (16) /* Bits 16-20: WDT postscaler */ +#define DEVCFG2_WDTSPGM (1 << 21) /* WDT stop during flash prog. */ +#define DEVCFG2_WINDIS (1 << 22) /* WDT window disable */ +#define DEVCFG2_WDTEN (1 << 23) /* WDT enable */ +#define DEVCFG2_WDTWINSZ_SHIFT (24) /* Bits 24-25: WDT window size */ +#define DEVCFG2_DMTCNT_SHIFT (26) /* Bits 26-30: DMT count */ + +/* DMT (deadman timer) enable */ + +#define DEVCFG2_DMTEN (1u << 31) + +/* DEVCFG1 (-> CFGCON1) */ + +#define DEVCFG1_DEBUG_SHIFT (0) /* Bits 0-1: background debugger */ +# define DEVCFG1_DEBUG_ENABLED (0 << DEVCFG1_DEBUG_SHIFT) +# define DEVCFG1_DEBUG_DISABLED (3 << DEVCFG1_DEBUG_SHIFT) +#define DEVCFG1_ICESEL_SHIFT (3) /* Bits 3-4: ICE/debug channel */ +# define DEVCFG1_ICESEL_PGX4 (0 << DEVCFG1_ICESEL_SHIFT) +# define DEVCFG1_ICESEL_PGX2 (2 << DEVCFG1_ICESEL_SHIFT) +# define DEVCFG1_ICESEL_PGX1 (3 << DEVCFG1_ICESEL_SHIFT) +#define DEVCFG1_TRCEN (1 << 5) /* CPU trace enable */ +#define DEVCFG1_FMIIEN (1 << 8) /* Ethernet: 1 = MII, 0 = RMII */ +#define DEVCFG1_ETHEXEREF (1 << 9) /* PHY ref clock on exclusive pin */ +#define DEVCFG1_CLASSBDIS (1 << 10) /* Class B features disabled */ +#define DEVCFG1_USBIDIO (1 << 11) /* USBID pin owned by port */ +#define DEVCFG1_VBUSIO (1 << 12) /* VBUSON pin owned by port */ +#define DEVCFG1_HSSPIEN (1 << 13) /* SPI1 on dedicated pins */ +#define DEVCFG1_SMCLR (1 << 14) /* MCLR: legacy mode */ +#define DEVCFG1_HSUARTEN (1 << 15) /* UART1 on dedicated pins */ + +/* DEVCFG0 (-> CFGCON0): same layout as the CFGCON0 bits below, plus */ + +#define DEVCFG0_TDOEN (1 << 0) +#define DEVCFG0_JTAGEN (1 << 3) +#define DEVCFG0_PCM (1 << 23) /* Prefetch I/D always cacheable */ +#define DEVCFG0_FECCCON_SHIFT (28) /* Bits 28-29: flash ECC control */ + +/* FBCFG0 (-> BCFG0) */ + +#define FBCFG0_BUHSWEN (1 << 0) /* Buck mode switching control */ +#define FBCFG0_PCSCMODE (1 << 1) /* Must be 0 (DS Reg 38-10) */ +#define FBCFG0_BOOTISA (1 << 3) /* 1 = MIPS32, 0 = microMIPS */ + +/* BINFOVALID must be programmed to 0 (DS70005425 Reg 38-10) */ + +#define FBCFG0_BINFOVALID (1u << 31) + +/* FCPN0: CP, bit 28. FSIGN0: SIGN, bit 31. Emitted with the values found + * on factory-programmed parts (0xffffffff and 0x7fffffff). + */ + +#define W1CFG_FCPN0_VALUE 0xffffffff +#define W1CFG_FSIGN0_VALUE 0x7fffffff + +#endif /* __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_FEATURES_H */ diff --git a/arch/mips/src/pic32mz/hardware/pic32mzw1_memorymap.h b/arch/mips/src/pic32mz/hardware/pic32mzw1_memorymap.h new file mode 100644 index 00000000000..3c4a2e12626 --- /dev/null +++ b/arch/mips/src/pic32mz/hardware/pic32mzw1_memorymap.h @@ -0,0 +1,175 @@ +/**************************************************************************** + * arch/mips/src/pic32mz/hardware/pic32mzw1_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* The PIC32MZ-W1 / WFI32Exx family (used in the WFI32E01 modules) shares + * the MIPS32 M-Class core and much of the peripheral IP found in the + * PIC32MZ-EC/EF families, but the SFR layout was substantially reorganized + * to make room for the integrated Wi-Fi subsystem, crypto engine, and RNG. + * Do not assume offsets from pic32mzef_memorymap.h apply here. + * + * Offsets below were derived from the Microchip PIC32MZ-W_DFP device + * family pack (Apache-2.0 licensed), specifically the WFI32E01 processor + * header (proc/pwfi32e01.h) and WFI32E01.atdf, cross-checked against the + * PIC32MZ W1 family datasheet. + */ + +#ifndef __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_MEMORYMAP_H +#define __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include "mips32-memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Physical Memory Map ******************************************************/ + +/* Memory Regions */ + +#define PIC32MZ_DATAMEM_PBASE 0x00000000 /* Size depends on CHIP_DATAMEM_KB */ +#define PIC32MZ_PROGFLASH_PBASE 0x10000000 /* Size depends on CHIP_PROGFLASH_KB - + * NOTE: this differs from EC/EF's + * 0x1d000000; verified against both + * the DFP's ATDF memory-segment list + * and Microchip's own WFI32E01 + * reference linker script + * (kseg0_program_mem at KSEG0 + * 0x90000000). */ +#define PIC32MZ_SFR_PBASE 0x1f800000 /* Special function registers */ +#define PIC32MZ_BOOTFLASH_PBASE 0x1fc00000 /* Size depends on CHIP_BOOTFLASH_KB */ +#define PIC32MZ_SQIMEM_PBASE 0x30000000 /* External memory via SQI (e.g. SPI flash) */ + +/* Boot FLASH */ + +#define PIC32MZ_LOWERBOOT_PBASE 0x1fc00000 /* Lower boot alias */ +#define PIC32MZ_BOOTCFG_PBASE 0x1fc55e88 /* Configuration space (altConfig) */ + +/* Virtual Memory Map *******************************************************/ + +#define PIC32MZ_DATAMEM_K0BASE (KSEG0_BASE + PIC32MZ_DATAMEM_PBASE) +#define PIC32MZ_PROGFLASH_K0BASE (KSEG0_BASE + PIC32MZ_PROGFLASH_PBASE) +#define PIC32MZ_SFR_K0BASE (KSEG0_BASE + PIC32MZ_SFR_PBASE) +#define PIC32MZ_BOOTFLASH_K0BASE (KSEG0_BASE + PIC32MZ_BOOTFLASH_PBASE) +#define PIC32MZ_SQIMEM_K0BASE (KSEG0_BASE + PIC32MZ_SQIMEM_PBASE) + +#define PIC32MZ_DATAMEM_K1BASE (KSEG1_BASE + PIC32MZ_DATAMEM_PBASE) +#define PIC32MZ_PROGFLASH_K1BASE (KSEG1_BASE + PIC32MZ_PROGFLASH_PBASE) +#define PIC32MZ_SFR_K1BASE (KSEG1_BASE + PIC32MZ_SFR_PBASE) +#define PIC32MZ_BOOTFLASH_K1BASE (KSEG1_BASE + PIC32MZ_BOOTFLASH_PBASE) +#define PIC32MZ_SQIMEM_K1BASE (KSEG1_BASE + PIC32MZ_SQIMEM_PBASE) + +#define PIC32MZ_LOWERBOOT_K0BASE (KSEG0_BASE + PIC32MZ_LOWERBOOT_PBASE) +#define PIC32MZ_BOOTCFG_K0BASE (KSEG0_BASE + PIC32MZ_BOOTCFG_PBASE) +#define PIC32MZ_LOWERBOOT_K1BASE (KSEG1_BASE + PIC32MZ_LOWERBOOT_PBASE) +#define PIC32MZ_BOOTCFG_K1BASE (KSEG1_BASE + PIC32MZ_BOOTCFG_PBASE) + +/* Register Base Addresses ************************************************** + * + * Unlike the EC/EF families, PIC32MZ-W1 peripherals are not laid out in + * one contiguous, cleanly-spaced table. The blocks below are grouped by + * the "near"/"far" SFR regions used by the silicon (periph_pb1..pb4, + * periph_indep_a/b in the ATDF), each holding a handful of unrelated + * peripherals. + */ + +/* "Near" SFR region: system config, oscillator, timers, interrupt + * controller, DMA, prefetch cache. + */ + +#define PIC32MZ_CONFIG_K1BASE (PIC32MZ_SFR_K1BASE + 0x00000000) /* CFGCONx, SYSKEY, PMDx */ +#define PIC32MZ_WDT_K1BASE (PIC32MZ_SFR_K1BASE + 0x00000800) /* Watchdog Timer */ +#define PIC32MZ_DMT_K1BASE (PIC32MZ_SFR_K1BASE + 0x00000a00) /* Deadman Timer */ +#define PIC32MZ_OSC_K1BASE (PIC32MZ_SFR_K1BASE + 0x00001200) /* Oscillator, RCON, RSWRST */ +#define PIC32MZ_UART3_REAL_K1BASE (PIC32MZ_SFR_K1BASE + 0x00001600) /* UART3 (low-power/debug UART). + * NOTE: named _REAL_ to avoid + * colliding with (and being + * silently shadowed by) the + * generic, WRONG + * PIC32MZ_UART3_K1BASE that + * hardware/pic32mz_uart.h + * computes generically as + * UART_K1BASE+0x400 - see + * note above. Not wired up + * to any driver yet. */ +#define PIC32MZ_PPS_K1BASE (PIC32MZ_SFR_K1BASE + 0x00001800) /* Peripheral Pin Select */ +#define PIC32MZ_TIMER_K1BASE (PIC32MZ_SFR_K1BASE + 0x00002000) /* Timer1-Timer7 (0x200 each) */ + +#define PIC32MZ_INT_K1BASE (PIC32MZ_SFR_K1BASE + 0x00010000) /* Interrupt Controller */ +#define PIC32MZ_DMA_K1BASE (PIC32MZ_SFR_K1BASE + 0x00011000) /* DMA */ +#define PIC32MZ_PREFETCH_K1BASE (PIC32MZ_SFR_K1BASE + 0x00012400) /* Prefetch cache controller */ + +/* periph_pb2: GPIO ports, ADC, I2C1, CAN1, CAN-FD aux, CVD + * + * NOTE: I2C1 and I2C2 are NOT a contiguous pair on this family (I2C1 + * lives here in pb2, I2C2 lives in pb3 below), unlike EC/EF where + * PIC32MZ_I2C_K1BASE + n*0x200 reaches every instance. There is no + * PIC32MZ_I2C_K1BASE here; hardware/pic32mz_i2c.h uses the per-instance + * bases below. + */ + +#define PIC32MZ_IOPORT_K1BASE (PIC32MZ_SFR_K1BASE + 0x00020000) /* PORTA-C, PORTK (0x100 each) */ +#define PIC32MZ_I2C1_K1BASE (PIC32MZ_SFR_K1BASE + 0x00020400) /* I2C1 */ +#define PIC32MZ_ADC1_K1BASE (PIC32MZ_SFR_K1BASE + 0x00021000) /* ADC1 */ +#define PIC32MZ_CAN1_K1BASE (PIC32MZ_SFR_K1BASE + 0x00022000) /* CAN1 */ +#define PIC32MZ_CFD2_K1BASE (PIC32MZ_SFR_K1BASE + 0x00023000) /* CAN-FD auxiliary block */ +#define PIC32MZ_CVD_K1BASE (PIC32MZ_SFR_K1BASE + 0x00024000) /* Capacitive voltage divider */ + +/* periph_pb3: I2C2, UART1, UART2, SPI1, SPI2, input capture, output + * compare, Ethernet MAC, USB OTG. + * + * UART1/UART2 and SPI1/SPI2 ARE contiguous 0x200-apart pairs here, so + * PIC32MZ_UART_K1BASE/PIC32MZ_SPI_K1BASE (base of instance 1) work with + * the existing generic hardware/pic32mz_uart.h and pic32mz_spi.h offset + * tables for instances 1-2. UART3 (see PIC32MZ_UART3_K1BASE above) is a + * separate, non-contiguous low-power UART and is NOT reachable through + * that generic table. + */ + +#define PIC32MZ_I2C2_K1BASE (PIC32MZ_SFR_K1BASE + 0x00040400) /* I2C2 */ +#define PIC32MZ_UART_K1BASE (PIC32MZ_SFR_K1BASE + 0x00040600) /* UART1 (base), UART2 at +0x200 */ +#define PIC32MZ_SPI_K1BASE (PIC32MZ_SFR_K1BASE + 0x00040c00) /* SPI1 (base), SPI2 at +0x200 */ +#define PIC32MZ_IC_K1BASE (PIC32MZ_SFR_K1BASE + 0x00041000) /* IC1-IC9 */ +#define PIC32MZ_OC_K1BASE (PIC32MZ_SFR_K1BASE + 0x00042000) /* OC1-OC9 */ +#define PIC32MZ_ETH_K1BASE (PIC32MZ_SFR_K1BASE + 0x00043000) /* Ethernet MAC */ +#define PIC32MZ_USB_K1BASE (PIC32MZ_SFR_K1BASE + 0x00044000) /* USB OTG */ + +/* periph_pb4: RTCC */ + +#define PIC32MZ_RTCC_K1BASE (PIC32MZ_SFR_K1BASE + 0x00070000) /* RTCC */ + +/* periph_indep_a: SQI (external QSPI flash), crypto, RNG */ + +#define PIC32MZ_SQI1_K1BASE (PIC32MZ_SFR_K1BASE + 0x000e1000) /* SQI1 controller */ +#define PIC32MZ_CRYPTO_K1BASE (PIC32MZ_SFR_K1BASE + 0x000e4000) /* Crypto engine */ +#define PIC32MZ_RNG_K1BASE (PIC32MZ_SFR_K1BASE + 0x000e5000) /* RNG */ + +/* periph_indep_b: public-key crypto accelerator */ + +#define PIC32MZ_PKE_K1BASE (PIC32MZ_SFR_K1BASE + 0x00120000) /* Public key engine */ + +#endif /* __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_MEMORYMAP_H */ diff --git a/arch/mips/src/pic32mz/hardware/pic32mzw1_pmuclk.h b/arch/mips/src/pic32mz/hardware/pic32mzw1_pmuclk.h new file mode 100644 index 00000000000..51ed0582e50 --- /dev/null +++ b/arch/mips/src/pic32mz/hardware/pic32mzw1_pmuclk.h @@ -0,0 +1,204 @@ +/**************************************************************************** + * arch/mips/src/pic32mz/hardware/pic32mzw1_pmuclk.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* PIC32MZ-W1 PMU (buck/MLDO regulator) and clock-generation registers that + * have no PIC32MZ EC/EF equivalent. + * + * Every definition below is tagged with where it comes from: + * + * [DS] PIC32MZ W1 and WFI32E01 Family Data Sheet, DS70005425P. + * [DFP] Microchip PIC32MZ-W_DFP 1.12.356 (Apache-2.0), + * include/proc/pwfi32e01.h. + * [EX] Not in [DS] or [DFP]. Observed in Microchip's + * WFI32_Ethernet_Wi-Fi_Bridge_OOB example firmware (pmu_init.c, + * plib_clk.c). Only the hardware facts (addresses, bit positions, + * values) are used here; no code was copied. + */ + +#ifndef __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_PMUCLK_H +#define __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_PMUCLK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include "hardware/pic32mz_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* PMU controller registers [DS Table 35-2, DFP] ****************************/ + +#define PIC32MZ_PMUSPICTRL (PIC32MZ_SFR_K1BASE + 0x00013e00) /* [DFP] */ +#define PIC32MZ_PMUSPISTAT (PIC32MZ_SFR_K1BASE + 0x00013e04) /* [DFP] */ +#define PIC32MZ_PMUCLKCTRL (PIC32MZ_SFR_K1BASE + 0x00013e08) +#define PIC32MZ_PMUMODECTRL1 (PIC32MZ_SFR_K1BASE + 0x00013e0c) +#define PIC32MZ_PMUMODECTRL2 (PIC32MZ_SFR_K1BASE + 0x00013e10) +#define PIC32MZ_PMUOVERCTRL (PIC32MZ_SFR_K1BASE + 0x00013e1c) +#define PIC32MZ_PMUCMODE (PIC32MZ_SFR_K1BASE + 0x00013e20) + +/* PMUSPICTRL: memory-mapped access to the regulator's internal registers + * [DFP _PMUSPICTRL_*]. + */ + +#define PMUSPICTRL_WDATA_SHIFT (0) /* Bits 0-15: SPIWDATA */ +#define PMUSPICTRL_WDATA_MASK (0xffff << PMUSPICTRL_WDATA_SHIFT) +#define PMUSPICTRL_ADDR_SHIFT (16) /* Bits 16-23: SPIADDR */ +#define PMUSPICTRL_ADDR_MASK (0xff << PMUSPICTRL_ADDR_SHIFT) +#define PMUSPICTRL_CMD (1 << 24) /* Bit 24: CMD, 1 = read [EX] */ + +/* PMUSPISTAT [DFP _PMUSPISTAT_*] */ + +#define PMUSPISTAT_SPIERR (1 << 0) /* Bit 0: SPIERR */ +#define PMUSPISTAT_SPIRDY (1 << 7) /* Bit 7: SPIRDY */ +#define PMUSPISTAT_RDATA_SHIFT (16) /* Bits 16-31: SPIRDATA */ +#define PMUSPISTAT_RDATA_MASK (0xffffu << PMUSPISTAT_RDATA_SHIFT) + +/* PMUCLKCTRL: field layout [DFP _PMUCLKCTRL_*]. The source-select + * encodings are not documented; the example uses SPISRC=2 and BUCKSRC=1 + * [EX]. + */ + +#define PMUCLKCTRL_SPICLKDIV(n) ((uint32_t)(n) << 0) /* Bits 0-5 */ +#define PMUCLKCTRL_SPISRC(n) ((uint32_t)(n) << 6) /* Bits 6-7 */ +#define PMUCLKCTRL_BUCKCLKDIV(n) ((uint32_t)(n) << 8) /* Bits 8-13 */ +#define PMUCLKCTRL_BUCKSRC(n) ((uint32_t)(n) << 14) /* Bits 14-15 */ +#define PMUCLKCTRL_BACWD (1 << 16) +#define PMUCLKCTRL_WLDOOFF (1 << 30) /* [DS Reg 35-1] */ +#define PMUCLKCTRL_WCMRET (1u << 31) /* [DS Reg 35-1] */ + +/* PMUMODECTRL1/2, PMUOVERCTRL and PMUCMODE share this layout. Enable and + * mode bits: [DS Reg 35-2..35-4]. VREGn trim fields: [DFP + * _PMUMODECTRL1_VREGnCTRL_*] only (the data sheet marks them as + * unimplemented). + */ + +#define PMUMODE_VREG4_SHIFT (0) +#define PMUMODE_VREG3_SHIFT (8) +#define PMUMODE_VREG2_SHIFT (16) +#define PMUMODE_VREG1_SHIFT (24) +#define PMUMODE_VREG_MASK (0x1f) +#define PMUMODE_VREGALL_MASK (0x1f1f1f1f) +#define PMUMODE_BUCKMODE (1 << 29) /* 1 = PWM, 0 = PSM */ +#define PMUMODE_MLDOEN (1 << 30) +#define PMUMODE_BUCKEN (1u << 31) + +#define PMUOVERCTRL_PHWC (1 << 22) /* [DS Reg 35-3] */ +#define PMUOVERCTRL_OVEREN (1 << 23) /* [DS Reg 35-3] */ + +/* Regulator-internal registers reached through PMUSPICTRL [EX] */ + +#define PMU_BUCKCFG1 0x14 +#define PMU_BUCKCFG2 0x15 +#define PMU_BUCKCFG3 0x16 +#define PMU_MLDOCFG1 0x17 +#define PMU_MLDOCFG2 0x18 + +/* Factory trim words in the boot-flash configuration space [EX]. The data + * sheet only says that "calibrated values from the NVRFLASH area" must be + * used (DS Table 35-2, note 2); it does not give their location. An + * erased (0xffffffff) or zero word means "not calibrated". + */ + +#define PIC32MZ_OTP_BUCKCFG1 (PIC32MZ_BOOTFLASH_K1BASE + 0x56fe8) +#define PIC32MZ_OTP_BUCKCFG2 (PIC32MZ_BOOTFLASH_K1BASE + 0x56fec) +#define PIC32MZ_OTP_BUCKCFG3 (PIC32MZ_BOOTFLASH_K1BASE + 0x56ff0) +#define PIC32MZ_OTP_MLDOCFG1 (PIC32MZ_BOOTFLASH_K1BASE + 0x56ff4) +#define PIC32MZ_OTP_MLDOCFG2 (PIC32MZ_BOOTFLASH_K1BASE + 0x56ff8) +#define PIC32MZ_OTP_VREGTRIM (PIC32MZ_BOOTFLASH_K1BASE + 0x56ffc) + +/* Reset control [DFP RCON, pWFI32E01.S] */ + +#define PIC32MZ_RCON (PIC32MZ_SFR_K1BASE + 0x00001260) +#define PIC32MZ_RCONCLR (PIC32MZ_SFR_K1BASE + 0x00001264) + +#define RCON_POR (1 << 0) /* Bit 0: power-on reset */ +#define RCON_BOR (1 << 1) /* Bit 1: brown-out reset */ + +/* Additional PLLs and clock status (OSC block) *****************************/ + +#define PIC32MZ_UPLLCON (PIC32MZ_OSC_K1BASE + 0x0030) /* [DS 11-4] */ +#define PIC32MZ_BTPLLCON (PIC32MZ_OSC_K1BASE + 0x0040) /* [DS 11-5] */ +#define PIC32MZ_EWPLLCON (PIC32MZ_OSC_K1BASE + 0x0050) /* [DS 11-6] */ +#define PIC32MZ_CLKSTAT (PIC32MZ_OSC_K1BASE + 0x0190) /* [DS 11-11] */ + +/* xPLLCON common field layout (SPLLCON, UPLLCON, BTPLLCON, EWPLLCON) + * [DS Reg 11-3..11-6]. + */ + +#define PLLCON_BSWSEL(n) ((uint32_t)(n) << 0) /* Bits 0-2 */ +#define PLLCON_PWDN (1 << 3) +#define PLLCON_POSTDIV1(n) ((uint32_t)(n) << 4) /* Bits 4-9 */ +#define PLLCON_FLOCK (1 << 10) +#define PLLCON_RST (1 << 11) +#define PLLCON_FBDIV(n) ((uint32_t)(n) << 12) /* Bits 12-21 */ +#define PLLCON_REFDIV(n) ((uint32_t)(n) << 22) /* Bits 22-27 */ +#define PLLCON_CLKOUTEN (1 << 28) /* BT/EWPLL only */ +#define PLLCON_ICLK_FRC (1 << 30) /* 0 = POSC input */ +#define PLLCON_BYP (1u << 31) + +/* CLKSTAT [DS Reg 11-11] */ + +#define CLKSTAT_FRCRDY (1 << 0) +#define CLKSTAT_SPLLRDY (1 << 1) +#define CLKSTAT_POSCRDY (1 << 2) +#define CLKSTAT_UPLLRDY (1 << 3) +#define CLKSTAT_ETHPLLRDY (1 << 7) + +/* CFGCON2: POSCMOD, bits 8-9 [DS Reg 38-3] */ + +#define CFGCON2_POSCMOD_SHIFT (8) +#define CFGCON2_POSCMOD_MASK (3 << CFGCON2_POSCMOD_SHIFT) +#define CFGCON2_POSCMOD_HS (0 << CFGCON2_POSCMOD_SHIFT) +#define CFGCON2_POSCMOD_OFF (3 << CFGCON2_POSCMOD_SHIFT) + +/* CFGCON3: PLL second post-dividers [DS Table 38-1, DFP _CFGCON3_*] */ + +#define CFGCON3_ETHPLLPOSTDIV2(n) ((uint32_t)(n) << 0) /* Bits 0-5 */ +#define CFGCON3_SPLLPOSTDIV2(n) ((uint32_t)(n) << 6) /* Bits 6-11 */ +#define CFGCON3_BTPLLPOSTDIV2(n) ((uint32_t)(n) << 12) /* Bits 12-15 */ + +/* RF/analog serial bridge [EX]. Not in [DS] or [DFP]. Bit-banged with + * 8-bit address + 16-bit data words, MSB first; its registers configure + * the 40 MHz crystal oscillator's analog front end, which the example + * programs before relying on POSC. + */ + +#define PIC32MZ_RFSPICTL (PIC32MZ_SFR_K1BASE + 0x000c8028) + +#define RFSPICTL_SCK (1 << 0) +#define RFSPICTL_CS (1 << 1) /* Idle (deasserted) level */ +#define RFSPICTL_SDO_SHIFT (2) +#define RFSPICTL_RESET (1 << 5) +#define RFSPICTL_EN (1u << 31) + +/* PLL lock status [EX]. Not in [DS] or [DFP]; CLKSTAT is the documented + * alternative but the example's exact polling is kept until verified on + * hardware. + */ + +#define PIC32MZ_PLLDBG (PIC32MZ_SFR_K1BASE + 0x000000e0) + +#endif /* __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_PMUCLK_H */ diff --git a/arch/mips/src/pic32mz/hardware/pic32mzw1_pps.h b/arch/mips/src/pic32mz/hardware/pic32mzw1_pps.h new file mode 100644 index 00000000000..186e1d03634 --- /dev/null +++ b/arch/mips/src/pic32mz/hardware/pic32mzw1_pps.h @@ -0,0 +1,191 @@ +/**************************************************************************** + * arch/mips/src/pic32mz/hardware/pic32mzw1_pps.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* Peripheral Pin Select for PIC32MZ-W1/WFI32E01. + * + * Register addresses below come from the Microchip PIC32MZ-W_DFP + * (Apache-2.0), proc/pwfi32e01.h. The actual input/output function-select + * VALUES (which 4-bit or 5-bit code picks which signal) are NOT in that + * header - they were transcribed from the public PIC32MZ W1 and WFI32E01 + * Family Data Sheet (DS70005425), Section 13.4, Table 13-2 (input) and + * Table 13-3 (output). + * + * This chip only implements PORTA, PORTB, PORTC and PORTK (see + * hardware/pic32mz_ioport.h). + * + * Only the handful of functions needed for UART1/UART2 (the console/ + * debug UARTs) are defined so far - IC/OC/SPI/CAN/Ethernet PPS routing + * is not yet covered. Add groups following the same pattern as they are + * needed. + * + * NOTE: UART1 also has dedicated, non-PPS pins (U1RX=RA8, U1TX=RA9). A + * board using those (e.g. ev49n51a) leaves BOARD_U1RX_PPS/ + * BOARD_U1TX_PPS undefined so that no PPS routing is programmed. + */ + +#ifndef __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_PPS_H +#define __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_PPS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "pic32mz_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* PPS Register Addresses (input selectors) *********************************/ + +#define PIC32MZ_INT1R (PIC32MZ_PPS_K1BASE + 0x0004) +#define PIC32MZ_INT2R (PIC32MZ_PPS_K1BASE + 0x0008) +#define PIC32MZ_INT3R (PIC32MZ_PPS_K1BASE + 0x000c) +#define PIC32MZ_INT4R (PIC32MZ_PPS_K1BASE + 0x0010) +#define PIC32MZ_U1RXR (PIC32MZ_PPS_K1BASE + 0x006c) +#define PIC32MZ_U1CTSR (PIC32MZ_PPS_K1BASE + 0x0070) +#define PIC32MZ_U2RXR (PIC32MZ_PPS_K1BASE + 0x0074) +#define PIC32MZ_U2CTSR (PIC32MZ_PPS_K1BASE + 0x0078) +#define PIC32MZ_SDI1R (PIC32MZ_PPS_K1BASE + 0x0098) +#define PIC32MZ_SDI2R (PIC32MZ_PPS_K1BASE + 0x00a4) + +/* PPS Register Addresses (output selectors, RPnR) - PORTA/PORTB/PORTK + * pins only. + */ + +#define PIC32MZ_RPA0R (PIC32MZ_PPS_K1BASE + 0x0200) +#define PIC32MZ_RPA1R (PIC32MZ_PPS_K1BASE + 0x0204) +#define PIC32MZ_RPA2R (PIC32MZ_PPS_K1BASE + 0x0208) +#define PIC32MZ_RPA3R (PIC32MZ_PPS_K1BASE + 0x020c) +#define PIC32MZ_RPA4R (PIC32MZ_PPS_K1BASE + 0x0210) +#define PIC32MZ_RPA5R (PIC32MZ_PPS_K1BASE + 0x0214) +#define PIC32MZ_RPA10R (PIC32MZ_PPS_K1BASE + 0x0228) +#define PIC32MZ_RPA11R (PIC32MZ_PPS_K1BASE + 0x022c) +#define PIC32MZ_RPA12R (PIC32MZ_PPS_K1BASE + 0x0230) +#define PIC32MZ_RPA13R (PIC32MZ_PPS_K1BASE + 0x0234) +#define PIC32MZ_RPA14R (PIC32MZ_PPS_K1BASE + 0x0238) +#define PIC32MZ_RPA15R (PIC32MZ_PPS_K1BASE + 0x023c) + +#define PIC32MZ_RPB0R (PIC32MZ_PPS_K1BASE + 0x0240) +#define PIC32MZ_RPB1R (PIC32MZ_PPS_K1BASE + 0x0244) +#define PIC32MZ_RPB2R (PIC32MZ_PPS_K1BASE + 0x0248) +#define PIC32MZ_RPB3R (PIC32MZ_PPS_K1BASE + 0x024c) +#define PIC32MZ_RPB4R (PIC32MZ_PPS_K1BASE + 0x0250) +#define PIC32MZ_RPB5R (PIC32MZ_PPS_K1BASE + 0x0254) +#define PIC32MZ_RPB6R (PIC32MZ_PPS_K1BASE + 0x0258) +#define PIC32MZ_RPB7R (PIC32MZ_PPS_K1BASE + 0x025c) +#define PIC32MZ_RPB8R (PIC32MZ_PPS_K1BASE + 0x0260) +#define PIC32MZ_RPB9R (PIC32MZ_PPS_K1BASE + 0x0264) +#define PIC32MZ_RPB10R (PIC32MZ_PPS_K1BASE + 0x0268) +#define PIC32MZ_RPB11R (PIC32MZ_PPS_K1BASE + 0x026c) +#define PIC32MZ_RPB12R (PIC32MZ_PPS_K1BASE + 0x0270) +#define PIC32MZ_RPB13R (PIC32MZ_PPS_K1BASE + 0x0274) +#define PIC32MZ_RPB14R (PIC32MZ_PPS_K1BASE + 0x0278) + +#define PIC32MZ_RPK0R (PIC32MZ_PPS_K1BASE + 0x02c0) +#define PIC32MZ_RPK1R (PIC32MZ_PPS_K1BASE + 0x02c4) +#define PIC32MZ_RPK2R (PIC32MZ_PPS_K1BASE + 0x02c8) +#define PIC32MZ_RPK3R (PIC32MZ_PPS_K1BASE + 0x02cc) +#define PIC32MZ_RPK4R (PIC32MZ_PPS_K1BASE + 0x02d0) +#define PIC32MZ_RPK5R (PIC32MZ_PPS_K1BASE + 0x02d4) +#define PIC32MZ_RPK6R (PIC32MZ_PPS_K1BASE + 0x02d8) +#define PIC32MZ_RPK7R (PIC32MZ_PPS_K1BASE + 0x02dc) +#define PIC32MZ_RPK8R (PIC32MZ_PPS_K1BASE + 0x02e0) +#define PIC32MZ_RPK9R (PIC32MZ_PPS_K1BASE + 0x02e4) +#define PIC32MZ_RPK10R (PIC32MZ_PPS_K1BASE + 0x02e8) +#define PIC32MZ_RPK11R (PIC32MZ_PPS_K1BASE + 0x02ec) +#define PIC32MZ_RPK12R (PIC32MZ_PPS_K1BASE + 0x02f0) +#define PIC32MZ_RPK13R (PIC32MZ_PPS_K1BASE + 0x02f4) +#define PIC32MZ_RPK14R (PIC32MZ_PPS_K1BASE + 0x02f8) + +/* Input Pin Selection (Datasheet Table 13-2) ******************************* + * + * U1RX shares the same 4-bit group as INT2/T3CK/T7CK/IC1/U2CTSn/C1RX/ + * ECRS/ERXD2/SS1/OCFB (restricted here to the A/B/K pins this chip has). + */ + +#define U1RXR_RPA2 0 +#define U1RXR_RPA10 1 +#define U1RXR_RPA14 2 +#define U1RXR_RPB2 3 +#define U1RXR_RPB6 4 +#define U1RXR_RPB10 5 +#define U1RXR_RPB14 6 +#define U1RXR_RPK2 11 +#define U1RXR_RPK6 12 +#define U1RXR_RPK10 12 /* NOTE: datasheet lists 1100 twice + * (RPK6 and RPK10) - transcribed + * as printed; verify against + * silicon/errata before relying + * on RPK10 specifically. */ +#define U1RXR_RPK14 13 + +/* U2RX shares the same 4-bit group as INT3/T2CK/T6CK/IC3/U1CTS/SDI2/ + * ERXD3/OCFC. + */ + +#define U2RXR_RPA1 0 +#define U2RXR_RPA5 1 +#define U2RXR_RPA13 2 +#define U2RXR_RPB1 3 +#define U2RXR_RPB5 4 +#define U2RXR_RPB9 5 +#define U2RXR_RPB13 6 +#define U2RXR_RPK1 11 +#define U2RXR_RPK5 12 +#define U2RXR_RPK9 12 /* NOTE: datasheet duplicate, see + * U1RXR_RPK10 above. */ +#define U2RXR_RPK13 13 + +/* Output Pin Selection (Datasheet Table 13-3) ****************************** + * + * U1TX is value 1 on the RPA0/RPA4/RPA12/RPB0/RPB4/RPB8/RPB12/RPK0/RPK4/ + * RPK8/RPK12 output group. + */ + +#define U1TX_RPA0R 1, PIC32MZ_RPA0R +#define U1TX_RPA4R 1, PIC32MZ_RPA4R +#define U1TX_RPA12R 1, PIC32MZ_RPA12R +#define U1TX_RPB0R 1, PIC32MZ_RPB0R +#define U1TX_RPB4R 1, PIC32MZ_RPB4R +#define U1TX_RPB8R 1, PIC32MZ_RPB8R +#define U1TX_RPB12R 1, PIC32MZ_RPB12R +#define U1TX_RPK0R 1, PIC32MZ_RPK0R +#define U1TX_RPK4R 1, PIC32MZ_RPK4R +#define U1TX_RPK8R 1, PIC32MZ_RPK8R +#define U1TX_RPK12R 1, PIC32MZ_RPK12R + +/* U2TX is value 2 on the RPA3/RPA11/RPA15/RPB3/RPB7/RPB11/RPK3/RPK7/RPK11 + * output group. + */ + +#define U2TX_RPA3R 2, PIC32MZ_RPA3R +#define U2TX_RPA11R 2, PIC32MZ_RPA11R +#define U2TX_RPA15R 2, PIC32MZ_RPA15R +#define U2TX_RPB3R 2, PIC32MZ_RPB3R +#define U2TX_RPB7R 2, PIC32MZ_RPB7R +#define U2TX_RPB11R 2, PIC32MZ_RPB11R +#define U2TX_RPK3R 2, PIC32MZ_RPK3R +#define U2TX_RPK7R 2, PIC32MZ_RPK7R +#define U2TX_RPK11R 2, PIC32MZ_RPK11R + +#endif /* __ARCH_MIPS_SRC_PIC32MZ_HARDWARE_PIC32MZW1_PPS_H */ diff --git a/arch/mips/src/pic32mz/pic32mz_config.h b/arch/mips/src/pic32mz/pic32mz_config.h index 4d22179738f..1efdad07c77 100644 --- a/arch/mips/src/pic32mz/pic32mz_config.h +++ b/arch/mips/src/pic32mz/pic32mz_config.h @@ -264,6 +264,13 @@ /* Device Configuration *****************************************************/ +/* PIC32MZ-W1 does not use the classic EC/EF DEVCFG0-3 layout (see + * hardware/pic32mzw1_features.h); its words are composed in the #else + * branch at the end of this block. + */ + +#ifndef CONFIG_ARCH_CHIP_PIC32MZW1 + /* DEVCFG3 */ /* Configurable settings */ @@ -595,6 +602,155 @@ #define CONFIG_PIC32MZ_DBGPER DEVCFG0_DBGPER_ALL #define CONFIG_PIC32MZ_EJTAGBEN DEVCFG0_EJTAG_NORMAL +#else /* CONFIG_ARCH_CHIP_PIC32MZW1 */ + +/* PIC32MZ-W1 boot-flash configuration words, emitted by pic32mz_head.S. + * Field layouts: hardware/pic32mzw1_features.h. Values that NuttX relies + * on are fixed; the rest follow the existing PIC32MZ Kconfig options. + * Everything else matches factory-programmed parts. + * + * Only '|' and '<<' are used: the result must be usable by the assembler. + */ + +/* FUSERID */ + +#define W1CFG_FUSERID (CONFIG_PIC32MZ_USERID & 0xffff) + +/* DEVCFG4: VBAT/Deep Sleep zero-power BOR on, DSWDT clocked by LPRC */ + +#define W1CFG_DEVCFG4 (DEVCFG4_VBZPBOREN | DEVCFG4_DSZPBOREN | \ + DEVCFG4_DSWDTOSC) + +/* DEVCFG2. CKSWEN is required: pic32mz_wfi32_pwrclk.c switches SYSCLK in + * software. DMT stays off; POSC in HS mode (40 MHz crystal). + */ + +#ifdef CONFIG_PIC32MZ_WDTENABLE +#if BOARD_WD_PRESCALER == 1 +# define W1CFG_WDTPS 0 +#elif BOARD_WD_PRESCALER == 2 +# define W1CFG_WDTPS 1 +#elif BOARD_WD_PRESCALER == 4 +# define W1CFG_WDTPS 2 +#elif BOARD_WD_PRESCALER == 8 +# define W1CFG_WDTPS 3 +#elif BOARD_WD_PRESCALER == 16 +# define W1CFG_WDTPS 4 +#elif BOARD_WD_PRESCALER == 32 +# define W1CFG_WDTPS 5 +#elif BOARD_WD_PRESCALER == 64 +# define W1CFG_WDTPS 6 +#elif BOARD_WD_PRESCALER == 128 +# define W1CFG_WDTPS 7 +#elif BOARD_WD_PRESCALER == 256 +# define W1CFG_WDTPS 8 +#elif BOARD_WD_PRESCALER == 512 +# define W1CFG_WDTPS 9 +#elif BOARD_WD_PRESCALER == 1024 +# define W1CFG_WDTPS 10 +#elif BOARD_WD_PRESCALER == 2048 +# define W1CFG_WDTPS 11 +#elif BOARD_WD_PRESCALER == 4096 +# define W1CFG_WDTPS 12 +#elif BOARD_WD_PRESCALER == 8192 +# define W1CFG_WDTPS 13 +#elif BOARD_WD_PRESCALER == 16384 +# define W1CFG_WDTPS 14 +#elif BOARD_WD_PRESCALER == 32768 +# define W1CFG_WDTPS 15 +#elif BOARD_WD_PRESCALER == 65536 +# define W1CFG_WDTPS 16 +#elif BOARD_WD_PRESCALER == 131072 +# define W1CFG_WDTPS 17 +#elif BOARD_WD_PRESCALER == 262144 +# define W1CFG_WDTPS 18 +#elif BOARD_WD_PRESCALER == 524288 +# define W1CFG_WDTPS 19 +#elif BOARD_WD_PRESCALER == 1048576 +# define W1CFG_WDTPS 20 +#else +# error "Unsupported BOARD_WD_PRESCALER" +#endif +# define W1CFG_WDTEN DEVCFG2_WDTEN +#else +# define W1CFG_WDTPS 0 +# define W1CFG_WDTEN 0 +#endif + +#define W1CFG_DEVCFG2 ((6 << DEVCFG2_DMTINTV_SHIFT) | \ + DEVCFG2_POSCMOD_HS | \ + (3 << DEVCFG2_WDTRMCS_SHIFT) | \ + DEVCFG2_SOSCSEL | DEVCFG2_WAKE2SPD | \ + DEVCFG2_CKSWEN | DEVCFG2_FSCMEN | \ + (W1CFG_WDTPS << DEVCFG2_WDTPS_SHIFT) | \ + DEVCFG2_WDTSPGM | DEVCFG2_WINDIS | \ + W1CFG_WDTEN | \ + (3 << DEVCFG2_WDTWINSZ_SHIFT) | \ + (0x17 << DEVCFG2_DMTCNT_SHIFT)) + +/* DEVCFG1. UART1 and SPI1 use their dedicated (non-PPS) pins unless the + * board routes them through PPS (BOARD_U1RX_PPS/BOARD_SDI1_PPS defined). + * Ethernet in RMII mode with the reference clock on ETH_CLK_OUT. + */ + +#ifdef CONFIG_PIC32MZ_DEBUGGER_ENABLE +# define W1CFG_DEBUG DEVCFG1_DEBUG_ENABLED +#else +# define W1CFG_DEBUG DEVCFG1_DEBUG_DISABLED +#endif + +#ifdef CONFIG_PIC32MZ_ICESEL_CH2 +# define W1CFG_ICESEL DEVCFG1_ICESEL_PGX2 +#else +# define W1CFG_ICESEL DEVCFG1_ICESEL_PGX1 +#endif + +#ifdef CONFIG_PIC32MZ_TRACE_ENABLE +# define W1CFG_TRCEN DEVCFG1_TRCEN +#else +# define W1CFG_TRCEN 0 +#endif + +#ifdef BOARD_U1RX_PPS +# define W1CFG_HSUARTEN 0 +#else +# define W1CFG_HSUARTEN DEVCFG1_HSUARTEN +#endif + +#ifdef BOARD_SDI1_PPS +# define W1CFG_HSSPIEN 0 +#else +# define W1CFG_HSSPIEN DEVCFG1_HSSPIEN +#endif + +#define W1CFG_DEVCFG1 (W1CFG_DEBUG | W1CFG_ICESEL | W1CFG_TRCEN | \ + DEVCFG1_CLASSBDIS | DEVCFG1_USBIDIO | \ + DEVCFG1_VBUSIO | W1CFG_HSSPIEN | \ + DEVCFG1_SMCLR | W1CFG_HSUARTEN) + +/* DEVCFG0. PMU/PMD/peripheral-pin/configuration locks off and all PLLs + * under software control (pic32mz_wfi32_pwrclk.c programs them). + */ + +#ifdef CONFIG_PIC32MZ_JTAG_ENABLE +# define W1CFG_JTAGEN DEVCFG0_JTAGEN +#else +# define W1CFG_JTAGEN 0 +#endif + +#define W1CFG_DEVCFG0 (DEVCFG0_TDOEN | W1CFG_JTAGEN | \ + DEVCFG0_PCM | \ + (CONFIG_PIC32MZ_ECC_OPTION << \ + DEVCFG0_FECCCON_SHIFT)) + +/* FBCFG0: boot and exception code are MIPS32 (pic32mz_head.S); + * BINFOVALID, PCSCMODE and BUHSWEN cleared. + */ + +#define W1CFG_FBCFG0 FBCFG0_BOOTISA + +#endif /* CONFIG_ARCH_CHIP_PIC32MZW1 */ + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/arch/mips/src/pic32mz/pic32mz_head.S b/arch/mips/src/pic32mz/pic32mz_head.S index f96b812d630..46409a0199d 100644 --- a/arch/mips/src/pic32mz/pic32mz_head.S +++ b/arch/mips/src/pic32mz/pic32mz_head.S @@ -178,7 +178,9 @@ .global __reset .global __start .global halt +#ifndef CONFIG_ARCH_CHIP_PIC32MZW1 .global devcfg +#endif #if CONFIG_ARCH_INTERRUPTSTACK > 3 .global g_intstackalloc .global g_intstacktop @@ -833,8 +835,12 @@ halt: /**************************************************************************** * Device Configuration + * + * NOTE: PIC32MZ-W1 uses a different set of words at different addresses + * (see hardware/pic32mzw1_features.h); it is handled by the #else branch. ****************************************************************************/ +#ifndef CONFIG_ARCH_CHIP_PIC32MZW1 .section .devcfg, "a" .type devcfg, object devcfg: @@ -920,6 +926,36 @@ adevcfg0: CONFIG_PIC32MZ_EJTAGBEN | DEVCFG0_RW0 .size adevcfg, .-adevcfg +#else /* CONFIG_ARCH_CHIP_PIC32MZW1 */ + +/* Primary copy at 0xbfc55f88, FCPN0 at 0xbfc55fbc, FSIGN0 at 0xbfc55fdc. + * Each block goes to its own linker region: the addresses in between are + * not implemented and must not appear in the image. + */ + + .section .devcfg, "a" + .type devcfg, object +devcfg: + .long W1CFG_FUSERID + .long W1CFG_DEVCFG4 + .long W1CFG_DEVCFG2 + .long W1CFG_DEVCFG1 + .long W1CFG_DEVCFG0 + .long W1CFG_FBCFG0 + .size devcfg, .-devcfg + + .section .devcfg_cp, "a" + .long W1CFG_FCPN0_VALUE + + .section .devcfg_sign, "a" + .long W1CFG_FSIGN0_VALUE + +/* No alternate copy (0xbfc55e88) is emitted: MPLAB IPE does not program + * it from the image but writes the DFP default values there itself, and + * does not verify it (checked on hardware). + */ + +#endif /* CONFIG_ARCH_CHIP_PIC32MZW1 */ /**************************************************************************** * Public Data diff --git a/arch/mips/src/pic32mz/pic32mz_i2c.c b/arch/mips/src/pic32mz/pic32mz_i2c.c index 9ccd034e63f..600c0e89231 100644 --- a/arch/mips/src/pic32mz/pic32mz_i2c.c +++ b/arch/mips/src/pic32mz/pic32mz_i2c.c @@ -29,6 +29,7 @@ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> +#include <inttypes.h> #include <stdint.h> #include <stdbool.h> #include <assert.h> @@ -58,6 +59,21 @@ /* Configuration ************************************************************/ +/* Peripheral bus clocks feeding the I2C baud rate generators. All I2C + * modules are on PBCLK2 on PIC32MZ EC/EF. On PIC32MZ-W1, I2C1 is on + * PBCLK2 and I2C2 on PBCLK3 (DS70005425 Table 11-1). + */ + +#define I2C1_PBCLK BOARD_PBCLK2 +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +# define I2C2_PBCLK BOARD_PBCLK3 +#else +# define I2C2_PBCLK BOARD_PBCLK2 +#endif +#define I2C3_PBCLK BOARD_PBCLK2 +#define I2C4_PBCLK BOARD_PBCLK2 +#define I2C5_PBCLK BOARD_PBCLK2 + /* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. * Instead CPU-intensive polling will be used. */ @@ -166,6 +182,7 @@ struct pic32mz_trace_s struct pic32mz_i2c_config_s { uint32_t base; /* I2C base address */ + uint32_t pbclk; /* Peripheral bus clock frequency (Hz) */ uint32_t scl_pin; /* GPIO configuration for SCL as SCL */ uint32_t sda_pin; /* GPIO configuration for SDA as SDA */ uint8_t mode; /* Master or Slave mode */ @@ -323,6 +340,7 @@ static const struct i2c_ops_s pic32mz_i2c_ops = static const struct pic32mz_i2c_config_s pic32mz_i2c1_config = { .base = PIC32MZ_I2C1_K1BASE, + .pbclk = I2C1_PBCLK, .scl_pin = GPIO_I2C1_SCL, .sda_pin = GPIO_I2C1_SDA, #ifndef CONFIG_I2C_POLLED @@ -355,6 +373,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c1_priv = static const struct pic32mz_i2c_config_s pic32mz_i2c2_config = { .base = PIC32MZ_I2C2_K1BASE, + .pbclk = I2C2_PBCLK, .scl_pin = GPIO_I2C2_SCL, .sda_pin = GPIO_I2C2_SDA, #ifndef CONFIG_I2C_POLLED @@ -387,6 +406,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c2_priv = static const struct pic32mz_i2c_config_s pic32mz_i2c3_config = { .base = PIC32MZ_I2C3_K1BASE, + .pbclk = I2C3_PBCLK, .scl_pin = GPIO_I2C3_SCL, .sda_pin = GPIO_I2C3_SDA, #ifndef CONFIG_I2C_POLLED @@ -419,6 +439,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c3_priv = static const struct pic32mz_i2c_config_s pic32mz_i2c4_config = { .base = PIC32MZ_I2C4_K1BASE, + .pbclk = I2C4_PBCLK, .scl_pin = GPIO_I2C4_SCL, .sda_pin = GPIO_I2C4_SDA, #ifndef CONFIG_I2C_POLLED @@ -451,6 +472,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c4_priv = static const struct pic32mz_i2c_config_s pic32mz_i2c5_config = { .base = PIC32MZ_I2C5_K1BASE, + .pbclk = I2C5_PBCLK, .scl_pin = GPIO_I2C5_SCL, .sda_pin = GPIO_I2C5_SDA, #ifndef CONFIG_I2C_POLLED @@ -825,7 +847,8 @@ pic32mz_i2c_sem_waitidle(struct pic32mz_i2c_priv_s *priv) /* If we get here then a timeout occurred with the bus still in idle */ - i2cinfo("Timeout with I2CxCON: %04x I2CxSTAT: %04x\n", con, stat); + i2cinfo("Timeout with I2CxCON: %04" PRIx32 " I2CxSTAT: %04" PRIx32 "\n", + con, stat); } /**************************************************************************** @@ -1254,10 +1277,10 @@ pic32mz_i2c_setbaudrate(struct pic32mz_i2c_priv_s *priv, if (frequency != priv->frequency) { - /* BOARD_PBCLK and frequency are both given in Hz. */ + /* pbclk and frequency are both given in Hz. */ - baudrate = (uint32_t)(((BOARD_PBCLK2 / (2 * frequency)) - - (BOARD_PBCLK2 / 10000000) - 2)); + baudrate = (uint32_t)(((priv->config->pbclk / (2 * frequency)) - + (priv->config->pbclk / 10000000) - 2)); /* Values of 0x0 and 0x1 are prohibited. */ @@ -1598,7 +1621,8 @@ static int pic32mz_i2c_transfer(struct i2c_master_s *dev, status = pic32mz_i2c_getstatus(priv); ret = -ETIMEDOUT; - i2cerr("ERROR: Timed out: CON: 0x%04x status: 0x%04x\n", + i2cerr("ERROR: Timed out: CON: 0x%04" PRIx32 " status: 0x%04" PRIx32 + "\n", pic32mz_i2c_getreg(priv, PIC32MZ_I2C_CON_OFFSET), status); } else diff --git a/arch/mips/src/pic32mz/pic32mz_lowconsole.c b/arch/mips/src/pic32mz/pic32mz_lowconsole.c index 44a9eed7d58..2a796b1fb03 100644 --- a/arch/mips/src/pic32mz/pic32mz_lowconsole.c +++ b/arch/mips/src/pic32mz/pic32mz_lowconsole.c @@ -86,6 +86,14 @@ # endif #endif +/* Peripheral bus clock feeding the UART baud rate generators */ + +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +# define UART_PBCLK BOARD_PBCLK3 +#else +# define UART_PBCLK BOARD_PBCLK2 +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -145,11 +153,14 @@ static inline uint32_t pic32mz_getreg(uintptr_t uart_base, * Configure the UART baud rate. * * With BRGH=0 - * BAUD = PBCLK2 / 16 / (BRG+1) - * BRG = PBCLK2 / 16 / BAUD - 1 + * BAUD = PBCLK / 16 / (BRG+1) + * BRG = PBCLK / 16 / BAUD - 1 * With BRGH=1 - * BAUD = PBCLK2 / 4 / (BRG+1) - * BRG = PBCLK2 / 4 / BAUD - 1 + * BAUD = PBCLK / 4 / (BRG+1) + * BRG = PBCLK / 4 / BAUD - 1 + * + * PBCLK is PBCLK2 on PIC32MZ EC/EF. On PIC32MZ-W1, UART1 and UART2 are + * clocked from PBCLK3 (DS70005425 Figure 24-1). * * ****************************************************************************/ @@ -166,7 +177,7 @@ static void pic32mz_uartsetbaud(uintptr_t uart_base, uint32_t baudrate) * Subject to BRG <= 65536. */ - tmp = BOARD_PBCLK2 / baudrate; + tmp = UART_PBCLK / baudrate; /* Try BRGH=1 first. This will select the 4x divisor and will produce the * larger BRG divisor, given all other things equal. @@ -323,11 +334,18 @@ void pic32mz_consoleinit(void) */ #ifdef CONFIG_PIC32MZ_UART1 - /* Configure UART1 RX (input) and TX (output) pins */ + /* Configure UART1 RX (input) and TX (output) pins. Boards that use + * UART1's dedicated, non-PPS pins (PIC32MZ-W1 RA8/RA9) leave + * BOARD_U1RX_PPS/BOARD_U1TX_PPS undefined. + */ +#if defined(BOARD_U1RX_PPS) && defined(BOARD_U1TX_PPS) putreg32(BOARD_U1RX_PPS, PIC32MZ_U1RXR); putreg32(PPS_OUTPUT_REGVAL(BOARD_U1TX_PPS), PPS_OUTPUT_REGADDR(BOARD_U1TX_PPS)); +#elif !defined(CONFIG_ARCH_CHIP_PIC32MZW1) +# error "BOARD_U1RX_PPS and BOARD_U1TX_PPS must be defined in board.h" +#endif #ifdef CONFIG_UART1_OFLOWCONTROL /* Configure the UART1 CTS input pin */ diff --git a/arch/mips/src/pic32mz/pic32mz_lowinit.c b/arch/mips/src/pic32mz/pic32mz_lowinit.c index 3e0c3263605..f3557998294 100644 --- a/arch/mips/src/pic32mz/pic32mz_lowinit.c +++ b/arch/mips/src/pic32mz/pic32mz_lowinit.c @@ -42,6 +42,11 @@ #include "pic32mz_lowconsole.h" #include "pic32mz_lowinit.h" +#ifdef CONFIG_ARCH_CHIP_WFI32E01 +# include "hardware/pic32mzw1_pmuclk.h" +# include "pic32mz_wfi32_pwrclk.h" +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -178,6 +183,18 @@ static inline void pic32mz_prefetch(void) { +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 + /* PIC32MZ-W1 differs from EC/EF here (DS70005425 Reg 9-1): PREFEN only + * accepts 00 (off) and 01 (cacheable regions), and the data sheet gives + * no SYSCLK-to-PFMWS table. The wait-state count comes from Kconfig; + * its default (5 at 200 MHz) is the value used by Microchip's OOB + * example [EX]. + */ + + modifyreg32(PIC32MZ_PRECON, PRECON_PREFEN_MASK | PRECON_PFMWS_MASK, + (1 << PRECON_PREFEN_SHIFT) | + PRECON_PFMWS(CONFIG_PIC32MZ_W1_FLASH_WAITSTATES)); +#else unsigned int nwaits; uint32_t regval; @@ -216,6 +233,7 @@ static inline void pic32mz_prefetch(void) */ putreg32(regval, PIC32MZ_PRECON); +#endif } /**************************************************************************** @@ -305,12 +323,28 @@ static inline void pic32mz_pbclk(void) * Peripherals: */ +#if defined(CONFIG_ARCH_CHIP_PIC32MZW1) && !defined(BOARD_PBCLK6_ENABLE) + /* On PIC32MZ-W1, PBCLK6 clocks the CPU and cannot be turned off + * (DS70005425 Reg 11-9 note 2). Writing 0 here (divide-by-1, "off") + * hangs the CPU (verified on hardware), so leave the reset divider. + */ + +#else #ifdef BOARD_PBCLK6_ENABLE regval = (PBDIV_ON | PBDIV(BOARD_PB6DIV)); #else regval = 0; #endif putreg32(regval, PIC32MZ_PB6DIV); +#endif + +#ifndef CONFIG_ARCH_CHIP_PIC32MZW1 + /* PIC32MZ-W1 has no PB7/PB8 bus (CPU clocking and EBI are not + * independently divided on this family); PIC32MZ_PB7DIV/PB8DIV are + * unimplemented placeholders that alias PB6DIV's real address on this + * chip (see hardware/pic32mz_osc.h), so they must never be written + * here. + */ /* PBCLK7 * Peripherals: CPU, Deadman timer @@ -333,6 +367,7 @@ static inline void pic32mz_pbclk(void) regval = 0; #endif putreg32(regval, PIC32MZ_PB8DIV); +#endif /* !CONFIG_ARCH_CHIP_PIC32MZW1 */ } /**************************************************************************** @@ -347,6 +382,22 @@ static inline void pic32mz_pbclk(void) static inline void pic32mz_adcdisable(void) { +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 + /* Only PORTA, PORTB and PORTK physically exist on this family; + * CHIP_NPORTS is kept at 10 for compatibility with the shared + * GPIO_PORTx letter-index encoding (see hardware/pic32mz_ioport.h), + * so the generic per-letter loop below cannot be used as-is here - + * PORTC-PORTJ's "addresses" are not real IOPORT registers on this + * chip and must not be written. + */ + + putreg32(0xffffffff, PIC32MZ_IOPORTA_K1BASE + + PIC32MZ_IOPORT_ANSELCLR_OFFSET); + putreg32(0xffffffff, PIC32MZ_IOPORTB_K1BASE + + PIC32MZ_IOPORT_ANSELCLR_OFFSET); + putreg32(0xffffffff, PIC32MZ_IOPORTK_K1BASE + + PIC32MZ_IOPORT_ANSELCLR_OFFSET); +#else putreg32(0xffffffff, PIC32MZ_IOPORTA_K1BASE + PIC32MZ_IOPORT_ANSELCLR_OFFSET); #if CHIP_NPORTS > 1 @@ -381,6 +432,7 @@ static inline void pic32mz_adcdisable(void) putreg32(0xffffffff, PIC32MZ_IOPORTJ_K1BASE + PIC32MZ_IOPORT_ANSELCLR_OFFSET); #endif +#endif /* CONFIG_ARCH_CHIP_PIC32MZW1 */ } /**************************************************************************** @@ -400,22 +452,75 @@ static inline void pic32mz_adcdisable(void) void pic32mz_lowinit(void) { +#ifdef CONFIG_ARCH_CHIP_WFI32E01 + /* On PIC32MZ-W1, the system PLL and Wi-Fi coprocessor PMU are NOT + * configured by DEVCFG fuses (unlike EC/EF) and must be brought up by + * software before anything else, including flash wait-state + * calculations, which depend on the final CPU clock. + */ + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + pic32mz_wfi32_trace_init(); + pic32mz_wfi32_trace('\r'); + pic32mz_wfi32_trace('\n'); + pic32mz_wfi32_trace('R'); + pic32mz_wfi32_trace_hex(getreg32(PIC32MZ_RCON)); + pic32mz_wfi32_trace(' '); + pic32mz_wfi32_trace('A'); +#endif + + pic32mz_wfi32_pmu_initialize(); + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + /* Clear the reset cause only after the PMU set-up has looked at it, so + * that the next boot trace shows what caused that reset. + */ + + putreg32(0xffffffff, PIC32MZ_RCONCLR); +#endif + + pic32mz_wfi32_clk_initialize(); +#endif + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + pic32mz_wfi32_trace('B'); +#endif + /* Initialize FLASH wait states */ pic32mz_prefetch(); +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + pic32mz_wfi32_trace('F'); +#endif + /* Configure peripheral clocking */ pic32mz_pbclk(); +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + pic32mz_wfi32_trace('P'); +#endif + /* Init IO pins (Disable all ADC circuits) */ pic32mz_adcdisable(); +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + pic32mz_wfi32_trace('D'); + pic32mz_wfi32_trace('\r'); + pic32mz_wfi32_trace('\n'); + pic32mz_wfi32_trace_end(); +#endif + /* Initialize a console (probably a serial console) */ pic32mz_consoleinit(); +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + mips_lowputc('c'); +#endif + /* Perform early serial initialization (so that we will have debug output * available as soon as possible). */ @@ -424,7 +529,17 @@ void pic32mz_lowinit(void) mips_earlyserialinit(); #endif +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + mips_lowputc('e'); +#endif + /* Perform board-level initialization */ pic32mz_boardinitialize(); + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE + mips_lowputc('b'); + mips_lowputc('\r'); + mips_lowputc('\n'); +#endif } diff --git a/arch/mips/src/pic32mz/pic32mz_serial.c b/arch/mips/src/pic32mz/pic32mz_serial.c index 867a8e22ba5..502f2683c74 100644 --- a/arch/mips/src/pic32mz/pic32mz_serial.c +++ b/arch/mips/src/pic32mz/pic32mz_serial.c @@ -357,6 +357,9 @@ static struct up_dev_s g_uart1priv = #ifdef CONFIG_PIC32MZ_UART_BREAKS .brk = false, # ifdef CONFIG_PIC32MZ_SERIALBRK_BSDCOMPAT +# ifndef BOARD_U1TX_PPS +# error "BSD-compatible breaks require a PPS-routed UART1 TX pin" +# endif .tx_gpio = PPS_OUTPUT_REGADDR_TO_GPIO(BOARD_U1TX_PPS) | GPIO_OUTPUT | GPIO_VALUE_ZERO, .tx_pps_reg = PPS_OUTPUT_REGADDR(BOARD_U1TX_PPS), diff --git a/arch/mips/src/pic32mz/pic32mz_spi.c b/arch/mips/src/pic32mz/pic32mz_spi.c index 2c3deea91d5..ba9ac0021ce 100644 --- a/arch/mips/src/pic32mz/pic32mz_spi.c +++ b/arch/mips/src/pic32mz/pic32mz_spi.c @@ -52,9 +52,15 @@ * Pre-processor Definitions ****************************************************************************/ -/* All SPI peripherals are clocked by PBCLK2 */ +/* Peripheral bus clock feeding the SPI baud rate generators: PBCLK2 on + * PIC32MZ EC/EF, PBCLK3 on PIC32MZ-W1 (DS70005425 Table 11-1). + */ -#define BOARD_PBCLOCK BOARD_PBCLK2 +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +# define BOARD_PBCLOCK BOARD_PBCLK3 +#else +# define BOARD_PBCLOCK BOARD_PBCLK2 +#endif #ifdef CONFIG_PIC32MZ_SPI_DMA @@ -120,7 +126,8 @@ struct pic32mz_config_s #endif uint8_t sdipps; /* SDI peripheral pin selection */ uint8_t sdopps; /* SDO peripheral pin selection */ - uintptr_t sdoreg; /* SDO peripheral pin configuration register */ + uintptr_t sdoreg; /* SDO peripheral pin configuration register + * (0: dedicated pins, no PPS) */ }; /* This structure describes the state of the SPI driver */ @@ -274,9 +281,11 @@ static const struct pic32mz_config_s g_spi1config = .rxirq = PIC32MZ_IRQ_SPI1RX, .txirq = PIC32MZ_IRQ_SPI1TX, #endif +#if defined(BOARD_SDI1_PPS) || !defined(CONFIG_ARCH_CHIP_PIC32MZW1) .sdipps = BOARD_SDI1_PPS, .sdopps = PPS_OUTPUT_REGVAL(BOARD_SDO1_PPS), .sdoreg = PPS_OUTPUT_REGADDR(BOARD_SDO1_PPS) +#endif }; static struct pic32mz_dev_s g_spi1dev = @@ -2023,11 +2032,17 @@ struct spi_dev_s *pic32mz_spibus_initialize(int port) regval = spi_getreg(priv, PIC32MZ_SPI_BUF_OFFSET); /* Configure SPI SDI (input) and SDO (output) pins. SS (output) pins are - * managed as GPIOs; CLK (output) pins are not selectable. + * managed as GPIOs; CLK (output) pins are not selectable. On PIC32MZ-W1, + * SPI1 may instead use its dedicated pins (DEVCFG1.HSSPIEN), which do not + * go through PPS. */ - spi_putaddr(priv, regaddr, (uint32_t)priv->config->sdipps); - spi_putaddr(priv, priv->config->sdoreg, (uint32_t)priv->config->sdopps); + if (priv->config->sdoreg != 0) + { + spi_putaddr(priv, regaddr, (uint32_t)priv->config->sdipps); + spi_putaddr(priv, priv->config->sdoreg, + (uint32_t)priv->config->sdopps); + } #ifdef CONFIG_PIC32MZ_SPI_DMA /* Allocate the RX and TX DMA channels, configuration will be done later. */ diff --git a/arch/mips/src/pic32mz/pic32mz_timer.c b/arch/mips/src/pic32mz/pic32mz_timer.c index 73524467432..8ea0f039352 100644 --- a/arch/mips/src/pic32mz/pic32mz_timer.c +++ b/arch/mips/src/pic32mz/pic32mz_timer.c @@ -82,6 +82,16 @@ # undef CONFIG_PIC32MZ_T9 #endif +/* Peripheral bus clock feeding the timers: PBCLK3 on PIC32MZ EC/EF, + * PBCLK1 on PIC32MZ-W1 (DS70005425 Figure 16-1). + */ + +#ifdef CONFIG_ARCH_CHIP_PIC32MZW1 +# define TIMER_PBCLK BOARD_PBCLK1 +#else +# define TIMER_PBCLK BOARD_PBCLK3 +#endif + /* Prescale values */ #define PIC32MZ_TIMER_PRESCALE_1_1 0 @@ -934,11 +944,11 @@ static uint32_t pic32mz_timer_getfreq(struct pic32mz_timer_dev_s *dev) if (prescale == PIC32MZ_TIMER_PRESCALE_1_256) { - freq = BOARD_PBCLK3 / (1 << (prescale + 1)); + freq = TIMER_PBCLK / (1 << (prescale + 1)); } else { - freq = BOARD_PBCLK3 / (1 << prescale); + freq = TIMER_PBCLK / (1 << prescale); } return freq; @@ -969,7 +979,7 @@ static bool pic32mz_timer_setfreq(struct pic32mz_timer_dev_s *dev, return 0; } - prescale = BOARD_PBCLK3 / freq; + prescale = TIMER_PBCLK / freq; tmrinfo("Prescale value calculated %d\n", prescale); diff --git a/arch/mips/src/pic32mz/pic32mz_timerisr.c b/arch/mips/src/pic32mz/pic32mz_timerisr.c index 08ea92e9eba..9441e048438 100644 --- a/arch/mips/src/pic32mz/pic32mz_timerisr.c +++ b/arch/mips/src/pic32mz/pic32mz_timerisr.c @@ -46,13 +46,17 @@ /* Timer Setup **************************************************************/ /* Timer 1 is a type A timer. Setting the TCS bit in the timer control - * register will select the SOSC as the clock source. Otherwise, PBCLK3 - * is the clock source. + * register will select the SOSC as the clock source. Otherwise, the + * peripheral bus clock is the clock source: PBCLK3 on PIC32MZ EC/EF, + * PBCLK1 on PIC32MZ-W1 (DS70005425 Figure 15-1). */ #ifdef CONFIG_PIC32MZ_T1_SOSC # define TIMER1_SRC_FREQ BOARD_SOSC_FREQ # define TIMER1_CON_TCS TIMER_CON_TCS +#elif defined(CONFIG_ARCH_CHIP_PIC32MZW1) +# define TIMER1_SRC_FREQ BOARD_PBCLK1 +# define TIMER1_CON_TCS (0) #else # define TIMER1_SRC_FREQ BOARD_PBCLK3 # define TIMER1_CON_TCS (0) diff --git a/arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.c b/arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.c new file mode 100644 index 00000000000..8b52e264ec4 --- /dev/null +++ b/arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.c @@ -0,0 +1,853 @@ +/**************************************************************************** + * arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* PIC32MZ-W1 (WFI32E01) regulator and clock bring-up. + * + * Unlike PIC32MZ EC/EF, the W1 family does not configure its PLLs from the + * configuration words: software must start the primary oscillator, program + * the PLLs and switch SYSCLK itself. + * + * Sources are tagged the same way as hardware/pic32mzw1_pmuclk.h: + * + * [DS] PIC32MZ W1 and WFI32E01 Family Data Sheet, DS70005425P. + * [DFP] Microchip PIC32MZ-W_DFP 1.12.356 (Apache-2.0). + * [EX] Not in [DS] or [DFP]; observed in Microchip's + * WFI32_Ethernet_Wi-Fi_Bridge_OOB example firmware (pmu_init.c, + * plib_clk.c). Only hardware facts (register addresses, values + * and the order the hardware needs them in) were taken from it; + * the code below is an independent implementation. + * + * Sections whose values or ordering come from [EX] are marked "[EX]" in + * their comments. Everything else is derived from [DS]/[DFP]. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#ifdef CONFIG_ARCH_CHIP_WFI32E01 + +#include <stdint.h> +#include <stdbool.h> +#include <sys/param.h> + +#include "mips_internal.h" +#include "hardware/pic32mz_memorymap.h" +#include "hardware/pic32mz_osc.h" +#include "hardware/pic32mz_uart.h" +#include "hardware/pic32mzw1_features.h" +#include "hardware/pic32mzw1_pmuclk.h" +#include "pic32mz_wfi32_pwrclk.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Busy-wait delays use the CP0 Count register, which ticks at SYSCLK/2. + * The rate is assumed to be the final 100 MHz; before the switch to the + * PLL the CPU runs slower, so delays only ever get longer, never shorter. + */ + +#define WFI32_COUNT_PER_US 100 + +/* SPLL: 40 MHz POSC / 5 * 150 / 6 = 200 MHz SYSCLK. These are the values + * the data sheet recommends for a 200 MHz system clock [DS Reg 11-3]. + */ + +#define WFI32_SPLLCON \ + (PLLCON_REFDIV(5) | PLLCON_FBDIV(150) | PLLCON_POSTDIV1(6) | \ + PLLCON_BSWSEL(1)) + +/* EWPLL: 40 MHz POSC / 4 * 160 = 1600 MHz VCO; / 32 = 50 MHz RMII + * reference on ETH_CLK_OUT, / 10 (CFGCON3.ETHPLLPOSTDIV2) = 160 MHz for + * Wi-Fi. Field layout [DS Reg 11-6]; the field values, and starting it + * with RST and PWDN set, are [EX]. + */ + +#define WFI32_EWPLLCON \ + (PLLCON_CLKOUTEN | PLLCON_REFDIV(4) | PLLCON_FBDIV(160) | \ + PLLCON_RST | PLLCON_POSTDIV1(32) | PLLCON_PWDN | PLLCON_BSWSEL(2)) + +#define WFI32_CFGCON3 CFGCON3_ETHPLLPOSTDIV2(10) /* [EX] */ + +/* PMU interface clocks: SPI = source 2 / 5, buck = source 1 / 8, BACWD + * cleared (field layout [DFP], values [EX]). + */ + +#define WFI32_PMUCLKCTRL \ + (PMUCLKCTRL_SPICLKDIV(5) | PMUCLKCTRL_SPISRC(2) | \ + PMUCLKCTRL_BUCKCLKDIV(8) | PMUCLKCTRL_BUCKSRC(1)) + +/* Fallback regulator settings when the factory trim word is blank [EX] */ + +#define WFI32_DEF_BUCKCFG1 0x5480 +#define WFI32_DEF_BUCKCFG2 0x8c28 +#define WFI32_DEF_BUCKCFG3 0x00c8 +#define WFI32_DEF_MLDOCFG1 0x0287 +#define WFI32_DEF_MLDOCFG2 0x0280 +#define WFI32_DEF_VREGTRIM 0x16161616 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Silicon variants that need different bring-up [EX: DEVID values] */ + +enum wfi32_silicon_e +{ + WFI32_SILICON_UNKNOWN = 0, + WFI32_SILICON_A1, + WFI32_SILICON_B0, + WFI32_SILICON_G +}; + +struct wfi32_rfreg_s +{ + uint8_t addr; + uint16_t data; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Crystal oscillator analog setup written over the RF serial bridge before + * POSC is enabled. Two variants, selected by silicon revision [EX]. + */ + +static const struct wfi32_rfreg_s g_xosc_cfg_a[] = +{ + { 0x85, 0x00f2 }, + { 0x84, 0x0001 }, + { 0x1e, 0x0510 }, + { 0x82, 0x6000 }, +}; + +static const struct wfi32_rfreg_s g_xosc_cfg_b[] = +{ + { 0x85, 0x00f0 }, + { 0x84, 0x0001 }, + { 0x1e, 0x0510 }, + { 0x82, 0x6400 }, +}; + +static const struct wfi32_rfreg_s g_xosc_cfg_a1[] = +{ + { 0x85, 0x00f0 }, + { 0x84, 0x0001 }, + { 0x1e, 0x0510 }, + { 0x82, 0x6000 }, +}; + +/* Applied once SYSCLK runs from the PLL: disables an input Schmitt trigger + * in the oscillator for better noise immunity [EX]. + */ + +static const struct wfi32_rfreg_s g_xosc_post_a = +{ + 0x85, 0x00f4 +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE +/* UART1 baud clock = FRC (CLK_SEL = 10b, DS Reg 24-1), BRGH = 1: + * 8 MHz / 4 / (16 + 1) = 117647 baud (+2.1% from 115200). + */ + +# define UART_MODE_CLKSEL_MASK (3 << 17) +# define UART_MODE_CLKSEL_FRC (2 << 17) +# define WFI32_TRACE_BRG 16 +# define TRACE(c) pic32mz_wfi32_trace(c) +# define TRACEREG(c, a) \ + do \ + { \ + pic32mz_wfi32_trace(' '); \ + pic32mz_wfi32_trace(c); \ + pic32mz_wfi32_trace('='); \ + pic32mz_wfi32_trace_hex(getreg32(a)); \ + } \ + while (0) +#else +# define TRACE(c) +# define TRACEREG(c, a) +#endif + +static inline uint32_t wfi32_cp0_count(void) +{ + uint32_t count; + + __asm__ __volatile__("mfc0 %0, $9" : "=r"(count)); + return count; +} + +static void wfi32_udelay(uint32_t usec) +{ + uint32_t start = wfi32_cp0_count(); + + while (wfi32_cp0_count() - start < usec * WFI32_COUNT_PER_US) + { + } +} + +static enum wfi32_silicon_e wfi32_silicon(void) +{ + uint32_t devid = getreg32(PIC32MZ_DEVID); + + switch ((devid & DEVID_PARTNUM_MASK) >> DEVID_PARTNUM_SHIFT) + { + case DEVID_PARTNUM_PIC32MZW1_A1: + return WFI32_SILICON_A1; + + case DEVID_PARTNUM_PIC32MZW1_B0: + return WFI32_SILICON_B0; + + case DEVID_PARTNUM_PIC32MZW1_G: + return WFI32_SILICON_G; + + default: + return WFI32_SILICON_UNKNOWN; + } +} + +static uint32_t wfi32_silicon_ver(void) +{ + return (getreg32(PIC32MZ_DEVID) & DEVID_VER_MASK) >> DEVID_VER_SHIFT; +} + +/* A factory trim word is valid unless blank (all zeros or erased) */ + +static bool wfi32_trim_valid(uint32_t word) +{ + return word != 0 && word != UINT32_MAX; +} + +static uint32_t wfi32_trim(uintptr_t addr, uint32_t fallback) +{ + uint32_t word = getreg32(addr); + + return wfi32_trim_valid(word) ? word : fallback; +} + +/* Pack four 5-bit VREG trims (VREG1 in the top byte) into the + * PMUMODECTRL/PMUOVERCTRL field positions; the trim word already uses the + * same byte layout. + */ + +static uint32_t wfi32_vreg_fields(uint32_t trim) +{ + return trim & PMUMODE_VREGALL_MASK; +} + +/* PMU regulator-internal register access through PMUSPICTRL/PMUSPISTAT + * [DFP fields]. The example waits 5 ms before polling SPIRDY [EX]; 5 us + * (longer while the CPU still runs from the FRC) was verified on B0 + * silicon and avoids adding most of a second to the boot. + */ + +static uint32_t wfi32_pmu_xfer(uint32_t ctrl) +{ + uint32_t status; + + putreg32(ctrl, PIC32MZ_PMUSPICTRL); + wfi32_udelay(5); + + do + { + status = getreg32(PIC32MZ_PMUSPISTAT); + } + while ((status & PMUSPISTAT_SPIRDY) == 0); + + return status; +} + +static uint16_t wfi32_pmu_read(uint8_t reg) +{ + uint32_t status; + + status = wfi32_pmu_xfer(PMUSPICTRL_CMD | + ((uint32_t)reg << PMUSPICTRL_ADDR_SHIFT)); + + return (status & PMUSPISTAT_RDATA_MASK) >> PMUSPISTAT_RDATA_SHIFT; +} + +static void wfi32_pmu_write(uint8_t reg, uint32_t value) +{ + wfi32_pmu_xfer(((uint32_t)reg << PMUSPICTRL_ADDR_SHIFT) | + (value & PMUSPICTRL_WDATA_MASK)); +} + +static void wfi32_pmu_setbits(uint8_t reg, uint16_t bits) +{ + wfi32_pmu_write(reg, wfi32_pmu_read(reg) | bits); +} + +/* RF serial bridge, bit-banged through RFSPICTL [EX: register, framing] */ + +static void wfi32_rfspi_clock(uint32_t lines) +{ + putreg32(RFSPICTL_EN | lines, PIC32MZ_RFSPICTL); + putreg32(RFSPICTL_EN | lines | RFSPICTL_SCK, PIC32MZ_RFSPICTL); +} + +static void wfi32_rfspi_shift(uint32_t value, unsigned int nbits) +{ + while (nbits-- > 0) + { + wfi32_rfspi_clock(((value >> nbits) & 1) << RFSPICTL_SDO_SHIFT); + } +} + +static void wfi32_rfspi_write(const struct wfi32_rfreg_s *reg) +{ + wfi32_rfspi_clock(RFSPICTL_CS); /* Idle cycle, then select */ + wfi32_rfspi_clock(0); + + wfi32_rfspi_shift(reg->addr, 8); + wfi32_rfspi_shift(reg->data, 16); + + putreg32(RFSPICTL_EN | RFSPICTL_CS | RFSPICTL_SCK, PIC32MZ_RFSPICTL); + putreg32(0, PIC32MZ_RFSPICTL); +} + +static void wfi32_rfspi_write_table(const struct wfi32_rfreg_s *tab, + unsigned int n) +{ + while (n-- > 0) + { + wfi32_rfspi_write(tab++); + } +} + +static void wfi32_posc_enable(bool enable) +{ + uint32_t regval = getreg32(PIC32MZ_CFGCON2) & ~CFGCON2_POSCMOD_MASK; + + regval |= enable ? CFGCON2_POSCMOD_HS : CFGCON2_POSCMOD_OFF; + putreg32(regval, PIC32MZ_CFGCON2); +} + +static void wfi32_wait_clkstat(uint32_t bits) +{ + while ((getreg32(PIC32MZ_CLKSTAT) & bits) == 0) + { + } +} + +/* Wait up to timeout_us for a CLKSTAT ready bit; false on timeout. Used + * for clocks the console does not depend on, so a fault there cannot + * hang the boot. + */ + +static bool wfi32_wait_clkstat_timeout(uint32_t bits, uint32_t timeout_us) +{ + uint32_t start = wfi32_cp0_count(); + + while ((getreg32(PIC32MZ_CLKSTAT) & bits) == 0) + { + if (wfi32_cp0_count() - start > timeout_us * WFI32_COUNT_PER_US) + { + return false; + } + } + + return true; +} + +static void wfi32_wait_plldbg(uint32_t bits) +{ + while ((getreg32(PIC32MZ_PLLDBG) & bits) == 0) + { + } +} + +/* Start the system PLL from POSC. SPLLHWMD hands PLL power-down/reset to + * hardware [DS Reg 38-1]; SPLLCON values [DS Reg 11-3]. + */ + +static void wfi32_spll_start(void) +{ + putreg32(WFI32_CFGCON3, PIC32MZ_CFGCON3); + modifyreg32(PIC32MZ_CFGCON0, 0, CFGCON0_SPLLHWMD); + putreg32(WFI32_SPLLCON, PIC32MZ_SPLLCON); +} + +/* Request SYSCLK = SPLL (FRCDIV = 1) and wait for the switch to complete + * [DS Reg 11-1]. + */ + +static void wfi32_sysclk_to_spll(void) +{ + putreg32(OSCCON_NOSC_SPLL, PIC32MZ_OSCCON); + putreg32(OSCCON_OSWEN, PIC32MZ_OSCCONSET); + + while ((getreg32(PIC32MZ_OSCCON) & OSCCON_OSWEN) != 0) + { + } +} + +static void wfi32_pll_powerdown(uintptr_t pllcon) +{ + modifyreg32(pllcon, 0, PLLCON_PWDN); +} + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE +static void wfi32_trace_pmuregs(void) +{ + uint8_t reg; + + for (reg = PMU_BUCKCFG1; reg <= PMU_MLDOCFG2; reg++) + { + pic32mz_wfi32_trace(' '); + pic32mz_wfi32_trace_hex(wfi32_pmu_read(reg)); + } +} + +# define TRACEPMU() wfi32_trace_pmuregs() +#else +# define TRACEPMU() +#endif + +/* B0: switch the regulator from MLDO to buck (PWM in run, PSM in sleep) + * using the hardware auto-switch flow of [DS Table 35-1]. Which internal + * registers to load, the fallback values, the post-switch tweaks for + * untrimmed parts and doing it only after a power-on or brown-out reset + * are [EX]. + */ + +static void wfi32_pmu_b0(void) +{ + uint32_t vreg; + + if ((getreg32(PIC32MZ_RCON) & (RCON_POR | RCON_BOR)) == 0) + { + TRACE('s'); + return; + } + + TRACE('p'); + TRACEREG('1', PIC32MZ_OTP_BUCKCFG1); + TRACEREG('2', PIC32MZ_OTP_BUCKCFG2); + TRACEREG('3', PIC32MZ_OTP_BUCKCFG3); + TRACEREG('4', PIC32MZ_OTP_MLDOCFG1); + TRACEREG('5', PIC32MZ_OTP_MLDOCFG2); + TRACEREG('6', PIC32MZ_OTP_VREGTRIM); + putreg32(WFI32_PMUCLKCTRL, PIC32MZ_PMUCLKCTRL); + + wfi32_pmu_write(PMU_BUCKCFG1, + wfi32_trim(PIC32MZ_OTP_BUCKCFG1, WFI32_DEF_BUCKCFG1)); + wfi32_pmu_write(PMU_BUCKCFG2, + wfi32_trim(PIC32MZ_OTP_BUCKCFG2, WFI32_DEF_BUCKCFG2)); + wfi32_pmu_write(PMU_BUCKCFG3, + wfi32_trim(PIC32MZ_OTP_BUCKCFG3, WFI32_DEF_BUCKCFG3)); + wfi32_pmu_write(PMU_MLDOCFG1, + wfi32_trim(PIC32MZ_OTP_MLDOCFG1, WFI32_DEF_MLDOCFG1)); + wfi32_pmu_write(PMU_MLDOCFG2, + wfi32_trim(PIC32MZ_OTP_MLDOCFG2, WFI32_DEF_MLDOCFG2)); + wfi32_pmu_read(PMU_MLDOCFG2); /* [EX] dummy read-back */ + TRACEPMU(); + + vreg = wfi32_vreg_fields(wfi32_trim(PIC32MZ_OTP_VREGTRIM, + WFI32_DEF_VREGTRIM)); + TRACE('q'); + + /* Run and sleep profiles, then the override that applies the run + * profile; clearing PHWC starts hardware control. + */ + + putreg32(PMUMODE_BUCKEN | PMUMODE_BUCKMODE | vreg, PIC32MZ_PMUMODECTRL1); + putreg32(PMUMODE_BUCKEN | vreg, PIC32MZ_PMUMODECTRL2); + putreg32(PMUMODE_BUCKEN | PMUMODE_BUCKMODE | PMUOVERCTRL_OVEREN | vreg, + PIC32MZ_PMUOVERCTRL); + modifyreg32(PIC32MZ_PMUOVERCTRL, PMUOVERCTRL_PHWC, 0); + + /* Wait until the regulator reports buck/PWM with MLDO off [DS 35-4] */ + + TRACE('w'); + + while ((getreg32(PIC32MZ_PMUCMODE) & + (PMUMODE_BUCKEN | PMUMODE_BUCKMODE | PMUMODE_MLDOEN)) != + (PMUMODE_BUCKEN | PMUMODE_BUCKMODE)) + { + } + + TRACE('x'); + + /* Untrimmed parts: adjust the buck settings after the switch [EX] */ + + if (!wfi32_trim_valid(getreg32(PIC32MZ_OTP_BUCKCFG1))) + { + wfi32_pmu_write(PMU_BUCKCFG1, + wfi32_pmu_read(PMU_BUCKCFG1) & 0xebff); + } + + if (!wfi32_trim_valid(getreg32(PIC32MZ_OTP_BUCKCFG2))) + { + wfi32_pmu_setbits(PMU_BUCKCFG2, 0x0010); + } + + TRACEPMU(); +} + +/* A1/G: stay in MLDO mode, updating its configuration and VREG trims, and + * apply it through the software override flow of [DS Table 35-1]. The + * internal register values are [EX]. + */ + +static void wfi32_pmu_mldo(enum wfi32_silicon_e silicon) +{ + uint32_t otp1 = getreg32(PIC32MZ_OTP_MLDOCFG1); + uint32_t vreg; + uint32_t mldo1; + uint32_t regval; + + vreg = wfi32_vreg_fields(wfi32_trim(PIC32MZ_OTP_VREGTRIM, + WFI32_DEF_VREGTRIM)); + mldo1 = wfi32_pmu_read(PMU_MLDOCFG1); + + if (silicon == WFI32_SILICON_A1) + { + if (mldo1 == 0 && !wfi32_trim_valid(otp1)) + { + mldo1 = 0x0180 | 0x0c07; + } + else + { + mldo1 = otp1 | 0x0c07; + } + + wfi32_pmu_write(PMU_MLDOCFG1, mldo1); + wfi32_pmu_write(PMU_MLDOCFG2, 0); + wfi32_pmu_setbits(PMU_MLDOCFG2, 0x0a80); + wfi32_pmu_setbits(PMU_BUCKCFG1, 0x0004); + } + else + { + uint32_t otp2 = getreg32(PIC32MZ_OTP_MLDOCFG2); + uint32_t mldo2; + + mldo1 |= wfi32_trim_valid(otp1) ? (otp1 | 0x0c07) : 0x0d87; + wfi32_pmu_write(PMU_MLDOCFG1, mldo1); + + wfi32_pmu_read(PMU_MLDOCFG2); /* [EX] read, value unused */ + mldo2 = wfi32_trim_valid(otp2) ? (otp2 & 0x8000) : 0xca80; + wfi32_pmu_write(PMU_MLDOCFG2, mldo2 | 0x0a80); + + if (wfi32_trim_valid(getreg32(PIC32MZ_OTP_BUCKCFG3))) + { + wfi32_pmu_setbits(PMU_BUCKCFG3, 0x00c8); + } + else + { + wfi32_pmu_read(PMU_BUCKCFG3); + wfi32_pmu_write(PMU_BUCKCFG3, 0x00c8); + } + + wfi32_pmu_setbits(PMU_BUCKCFG1, 0x0001); + wfi32_pmu_setbits(PMU_BUCKCFG1, 0x0004); + } + + regval = getreg32(PIC32MZ_PMUOVERCTRL); + regval &= ~(PMUMODE_BUCKEN | PMUMODE_VREGALL_MASK | PMUOVERCTRL_PHWC); + regval |= PMUMODE_MLDOEN | PMUOVERCTRL_OVEREN | vreg; + putreg32(regval, PIC32MZ_PMUOVERCTRL); +} + +/* B0/G clock bring-up [EX: ordering and delays] */ + +static void wfi32_clk_b0g(enum wfi32_silicon_e silicon) +{ + bool cfg_a = (silicon == WFI32_SILICON_G || wfi32_silicon_ver() == 1); + + TRACE('b'); + TRACEREG('O', PIC32MZ_OSCCON); + TRACEREG('P', PIC32MZ_SPLLCON); + TRACEREG('K', PIC32MZ_CLKSTAT); + TRACEREG('W', PIC32MZ_EWPLLCON); + TRACEREG('2', PIC32MZ_CFGCON2); + TRACEREG('3', PIC32MZ_CFGCON3); + + /* Bring up POSC and the SPLL unless SYSCLK already runs from the SPLL + * (e.g. a bootloader did it) [DS Reg 11-1 COSC]. The example tests + * SPLLCON == 0 instead, which never holds on B0 silicon: SPLLCON resets + * to 0xC0000808 there (verified on hardware). + */ + + if ((getreg32(PIC32MZ_OSCCON) & OSCCON_COSC_MASK) != OSCCON_COSC_SPLL) + { + /* Park both PLLs and stop POSC while its analog front end is set + * up over the RF bridge. + */ + + TRACE('S'); + putreg32(PLLCON_PWDN, PIC32MZ_EWPLLCON); + putreg32(PLLCON_PWDN, PIC32MZ_SPLLCON); + wfi32_udelay(300); + + wfi32_posc_enable(false); + wfi32_udelay(300); + + putreg32(RFSPICTL_EN | RFSPICTL_RESET | RFSPICTL_CS, PIC32MZ_RFSPICTL); + putreg32(RFSPICTL_EN | RFSPICTL_CS, PIC32MZ_RFSPICTL); + + if (cfg_a) + { + wfi32_rfspi_write_table(g_xosc_cfg_a, nitems(g_xosc_cfg_a)); + } + else + { + wfi32_rfspi_write_table(g_xosc_cfg_b, nitems(g_xosc_cfg_b)); + } + + TRACE('r'); + wfi32_udelay(200); + wfi32_posc_enable(true); + wfi32_udelay(300); + TRACE('o'); + + wfi32_spll_start(); + TRACE('l'); + wfi32_sysclk_to_spll(); + TRACE('s'); + + if ((getreg32(PIC32MZ_OSCCON) & OSCCON_NOSC_MASK) == OSCCON_NOSC_SPLL) + { + wfi32_wait_clkstat(CLKSTAT_POSCRDY); + } + + TRACE('k'); + + if (cfg_a) + { + wfi32_rfspi_write(&g_xosc_post_a); + } + } + else + { + TRACE('N'); + } + + /* Ethernet/Wi-Fi PLL: load the configuration with the PLL powered down + * and in reset, then power it up and release reset. With + * CFGCON0.ETHPLLHWMD = 0, reset is under software control [DS Reg 11-6, + * 38-1]; the example only clears PWDN, which leaves the PLL in reset + * (verified on hardware: ETHPLLRDY never set). + */ + + putreg32(WFI32_EWPLLCON, PIC32MZ_EWPLLCON); + wfi32_udelay(200); + modifyreg32(PIC32MZ_EWPLLCON, PLLCON_PWDN | PLLCON_RST, 0); + TRACE('e'); + TRACEREG('W', PIC32MZ_EWPLLCON); + TRACEREG('K', PIC32MZ_CLKSTAT); + if (wfi32_wait_clkstat_timeout(CLKSTAT_ETHPLLRDY, 10000)) + { + TRACE('E'); + } + else + { + TRACE('!'); + } + + TRACEREG('K', PIC32MZ_CLKSTAT); + + wfi32_pll_powerdown(PIC32MZ_UPLLCON); + wfi32_pll_powerdown(PIC32MZ_BTPLLCON); +} + +/* A1 clock bring-up [EX: ordering and delays] */ + +static void wfi32_clk_a1(void) +{ + wfi32_posc_enable(false); + wfi32_udelay(200); + + putreg32(RFSPICTL_EN | RFSPICTL_RESET | RFSPICTL_CS, PIC32MZ_RFSPICTL); + wfi32_posc_enable(true); + wfi32_udelay(200); + putreg32(RFSPICTL_EN | RFSPICTL_CS, PIC32MZ_RFSPICTL); + + wfi32_rfspi_write_table(g_xosc_cfg_a1, nitems(g_xosc_cfg_a1)); + wfi32_wait_clkstat(CLKSTAT_POSCRDY); + + wfi32_spll_start(); + wfi32_pll_powerdown(PIC32MZ_UPLLCON); + + /* On A1 the Ethernet/Wi-Fi PLL is left to hardware power control */ + + putreg32(WFI32_EWPLLCON, PIC32MZ_EWPLLCON); + modifyreg32(PIC32MZ_CFGCON0, 0, CFGCON0_ETHPLLHWMD); + wfi32_wait_plldbg(0x4); /* [EX] */ + + wfi32_pll_powerdown(PIC32MZ_BTPLLCON); + putreg32(WFI32_CFGCON3, PIC32MZ_CFGCON3); + + wfi32_sysclk_to_spll(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE +/**************************************************************************** + * Name: pic32mz_wfi32_trace_init / pic32mz_wfi32_trace / + * pic32mz_wfi32_trace_end + * + * Description: + * Bring-up aid: polled UART1 output clocked from the FRC, usable before + * and while the PLLs are reconfigured. trace_end() hands UART1 back to + * the normal console driver (PBCLK3 baud clock). + * + ****************************************************************************/ + +void pic32mz_wfi32_trace_init(void) +{ + putreg32(0, PIC32MZ_UART1_MODE); + putreg32(UART_MODE_CLKSEL_FRC | UART_MODE_BRGH, PIC32MZ_UART1_MODE); + putreg32(WFI32_TRACE_BRG, PIC32MZ_UART1_BRG); + putreg32(UART_STA_UTXEN, PIC32MZ_UART1_STASET); + putreg32(UART_MODE_ON, PIC32MZ_UART1_MODESET); +} + +void pic32mz_wfi32_trace(int ch) +{ + while ((getreg32(PIC32MZ_UART1_STA) & UART_STA_UTXBF) != 0) + { + } + + putreg32((uint32_t)ch, PIC32MZ_UART1_TXREG); + + /* Wait until it is fully on the wire, so a reset right after a marker + * cannot swallow it. + */ + + while ((getreg32(PIC32MZ_UART1_STA) & UART_STA_UTRMT) == 0) + { + } +} + +void pic32mz_wfi32_trace_hex(uint32_t value) +{ + int shift; + + for (shift = 28; shift >= 0; shift -= 4) + { + pic32mz_wfi32_trace("0123456789abcdef"[(value >> shift) & 0xf]); + } +} + +void pic32mz_wfi32_trace_end(void) +{ + while ((getreg32(PIC32MZ_UART1_STA) & UART_STA_UTRMT) == 0) + { + } + + putreg32(UART_MODE_ON, PIC32MZ_UART1_MODECLR); + putreg32(UART_MODE_CLKSEL_MASK, PIC32MZ_UART1_MODECLR); +} +#endif + +/**************************************************************************** + * Name: pic32mz_wfi32_pmu_initialize + ****************************************************************************/ + +void pic32mz_wfi32_pmu_initialize(void) +{ + enum wfi32_silicon_e silicon = wfi32_silicon(); + + TRACE('0' + silicon); + +#ifdef CONFIG_PIC32MZ_W1_PMU_MLDO + UNUSED(silicon); + TRACE('M'); + return; +#endif + + /* The device powers up in MLDO mode using factory-calibrated settings + * [DS 36.1], so an unrecognized revision is safely left as it is. + */ + + switch (silicon) + { + case WFI32_SILICON_B0: + wfi32_pmu_b0(); + break; + + case WFI32_SILICON_A1: + case WFI32_SILICON_G: + wfi32_pmu_mldo(silicon); + break; + + default: + break; + } +} + +/**************************************************************************** + * Name: pic32mz_wfi32_clk_initialize + ****************************************************************************/ + +void pic32mz_wfi32_clk_initialize(void) +{ + enum wfi32_silicon_e silicon = wfi32_silicon(); + + TRACE('C'); + + /* PLL and OSCCON writes need the system unlock sequence [DS Reg 38-9] */ + + putreg32(0, PIC32MZ_SYSKEY); + putreg32(UNLOCK_SYSKEY_0, PIC32MZ_SYSKEY); + putreg32(UNLOCK_SYSKEY_1, PIC32MZ_SYSKEY); + TRACE('u'); + + switch (silicon) + { + case WFI32_SILICON_B0: + case WFI32_SILICON_G: + wfi32_clk_b0g(silicon); + break; + + case WFI32_SILICON_A1: + wfi32_clk_a1(); + break; + + default: + break; + } + + /* PBCLK4 (deep sleep controller, RTCC) = SYSCLK / 10 right away, the + * divisor used by the example [EX] (PBxDIV layout: DS Reg 11-9). + * pic32mz_pbclk() later applies board.h. + */ + + modifyreg32(PIC32MZ_PB4DIV, PBDIV_MASK, PBDIV(10)); + + putreg32(LOCK_SYSKEY, PIC32MZ_SYSKEY); + TRACE('Z'); +} + +#endif /* CONFIG_ARCH_CHIP_WFI32E01 */ diff --git a/arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.h b/arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.h new file mode 100644 index 00000000000..0620da7b766 --- /dev/null +++ b/arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/mips/src/pic32mz/pic32mz_wfi32_pwrclk.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_WFI32_PWRCLK_H +#define __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_WFI32_PWRCLK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> + +#ifdef CONFIG_ARCH_CHIP_WFI32E01 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: pic32mz_wfi32_pmu_initialize + * + * Description: + * Bring the buck/MLDO regulator from its power-on state into its + * run-mode configuration, applying the factory trim when present. + * Must be called before pic32mz_wfi32_clk_initialize(). + * + ****************************************************************************/ + +void pic32mz_wfi32_pmu_initialize(void); + +/**************************************************************************** + * Name: pic32mz_wfi32_clk_initialize + * + * Description: + * Start the 40 MHz primary oscillator, run SYSCLK at 200 MHz from the + * system PLL, start the Ethernet/Wi-Fi PLL and power down the unused + * USB and Bluetooth PLLs. + * + ****************************************************************************/ + +void pic32mz_wfi32_clk_initialize(void); + +#ifdef CONFIG_PIC32MZ_W1_BOOTTRACE +void pic32mz_wfi32_trace_init(void); +void pic32mz_wfi32_trace(int ch); +void pic32mz_wfi32_trace_hex(uint32_t value); +void pic32mz_wfi32_trace_end(void); +#endif + +#endif /* CONFIG_ARCH_CHIP_WFI32E01 */ +#endif /* __ARCH_MIPS_SRC_PIC32MZ_PIC32MZ_WFI32_PWRCLK_H */
