add: humidity (WIP)
This commit is contained in:
		
							
								
								
									
										220
									
								
								vendor/periph.io/x/periph/host/allwinner/a20.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								vendor/periph.io/x/periph/host/allwinner/a20.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,220 @@
 | 
			
		||||
// Copyright 2018 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// This file contains pin mapping information that is specific to the Allwinner
 | 
			
		||||
// A20 model.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn/pin"
 | 
			
		||||
	"periph.io/x/periph/host/sysfs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// mappingA20 describes the mapping of the A20 processor gpios to their
 | 
			
		||||
// alternate functions.
 | 
			
		||||
//
 | 
			
		||||
// It omits the in & out functions which are available on all gpio.
 | 
			
		||||
//
 | 
			
		||||
// The mapping comes from the datasheet page 241:
 | 
			
		||||
// http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf
 | 
			
		||||
var mappingA20 = map[string][5]pin.Func{
 | 
			
		||||
	"PA0":  {"ERXD3", "SPI1_CS0", "UART2_RTS", "GRXD3"},
 | 
			
		||||
	"PA1":  {"ERXD2", "SPI1_CLK", "UART2_CTS", "GRXD2"},
 | 
			
		||||
	"PA2":  {"ERXD1", "SPI1_MOSI", "UART2_TX", "GRXD1"},
 | 
			
		||||
	"PA3":  {"ERXD0", "SPI1_MISO", "UART2_RX", "GRXD0"},
 | 
			
		||||
	"PA4":  {"ETXD3", "SPI1_CS1", "", "GTXD3"},
 | 
			
		||||
	"PA5":  {"ETXD2", "SPI3_CS0", "", "GTXD2"},
 | 
			
		||||
	"PA6":  {"ETXD1", "SPI3_CLK", "", "GTXD1"},
 | 
			
		||||
	"PA7":  {"ETXD0", "SPI3_MOSI", "", "GTXD0"},
 | 
			
		||||
	"PA8":  {"ERXCK", "SPI3_MISO", "", "CRXCK"},
 | 
			
		||||
	"PA9":  {"ERXERR", "SPI3_CS1", "", "GNULL", "I2S1_MCLK"},
 | 
			
		||||
	"PA10": {"ERXDV", "", "UART1_TX", "GRXCTL"},
 | 
			
		||||
	"PA11": {"EMDC", "", "UART1_RX", "GMDC"},
 | 
			
		||||
	"PA12": {"EMDIO", "UART6_TX", "UART1_RTS", "GMDIO"},
 | 
			
		||||
	"PA13": {"ETXEN", "UART6_RX", "UART1_CTS", "GTXCTL"},
 | 
			
		||||
	"PA14": {"ETXCK", "UART7_TX", "UART1_DTR", "GNULL", "I2S1_SCK"},
 | 
			
		||||
	"PA15": {"ECRS", "UART7_RX", "UART1_DSR", "GTXCK", "I2S1_WS"},
 | 
			
		||||
	"PA16": {"ECOL", "CAN_TX", "UART1_DCD", "GCLKIN", "I2S1_DOUT"},
 | 
			
		||||
	"PA17": {"ETXERR", "CAN_RX", "UART1_RI", "GNULL", "I2S1_DIN"},
 | 
			
		||||
	"PB0":  {"I2C0_SCL"},
 | 
			
		||||
	"PB1":  {"I2C0_SDA"},
 | 
			
		||||
	"PB2":  {"PWM0"},
 | 
			
		||||
	"PB3":  {"IR0_TX", "", "SPDIF_MCLK", "", "STANBYWFI"},
 | 
			
		||||
	"PB4":  {"IR0_RX"},
 | 
			
		||||
	"PB5":  {"I2S0_MCLK", "AC97_MCLK"},
 | 
			
		||||
	"PB6":  {"I2S0_SCK", "AC97_SCK"},
 | 
			
		||||
	"PB7":  {"I2S0_WS", "AC97_SYNC"},
 | 
			
		||||
	"PB8":  {"I2S0_DOUT0", "AC97_DOUT"},
 | 
			
		||||
	"PB9":  {"I2S0_DOUT1"},
 | 
			
		||||
	"PB10": {"I2S0_DOUT2"},
 | 
			
		||||
	"PB11": {"I2S0_DOUT3"},
 | 
			
		||||
	"PB12": {"I2S0_DIN", "AC97_DI", "SPDIF_DI"},
 | 
			
		||||
	"PB13": {"SPI2_CS1", "", "SPDIF_DO"},
 | 
			
		||||
	"PB14": {"SPI2_CS0", "JTAG0_TMS"},
 | 
			
		||||
	"PB15": {"SPI2_CLK", "JTAG0_TCK"},
 | 
			
		||||
	"PB16": {"SPI2_MOSI", "JTAG0_TDO"},
 | 
			
		||||
	"PB17": {"SPI2_MISO", "JTAG0_TDI"},
 | 
			
		||||
	"PB18": {"I2C1_SCL"},
 | 
			
		||||
	"PB19": {"I2C1_SDA"},
 | 
			
		||||
	"PB20": {"I2C2_SCL"},
 | 
			
		||||
	"PB21": {"I2C2_SDA"},
 | 
			
		||||
	"PB22": {"UART0_TX", "IR1_TX"},
 | 
			
		||||
	"PB23": {"UART0_RX", "IR1_RX"},
 | 
			
		||||
	"PC0":  {"NWE#", "SPI0_MOSI"},
 | 
			
		||||
	"PC1":  {"NALE", "SPI0_MISO"},
 | 
			
		||||
	"PC2":  {"NCLE", "SPI0_CLK"},
 | 
			
		||||
	"PC3":  {"NCE1"},
 | 
			
		||||
	"PC4":  {"NCE0"},
 | 
			
		||||
	"PC5":  {"NRE#"},
 | 
			
		||||
	"PC6":  {"NRB0", "SDC2_CMD"},
 | 
			
		||||
	"PC7":  {"NRB1", "SDC2_CLK"},
 | 
			
		||||
	"PC8":  {"NDQ0", "SDC2_D0"},
 | 
			
		||||
	"PC9":  {"NDQ1", "SDC2_D1"},
 | 
			
		||||
	"PC10": {"NDQ2", "SDC2_D2"},
 | 
			
		||||
	"PC11": {"NDQ3", "SDC2_D3"},
 | 
			
		||||
	"PC12": {"NDQ4"},
 | 
			
		||||
	"PC13": {"NDQ5"},
 | 
			
		||||
	"PC14": {"NDQ6"},
 | 
			
		||||
	"PC15": {"NDQ7"},
 | 
			
		||||
	"PC16": {"NWP"},
 | 
			
		||||
	"PC17": {"NCE2"},
 | 
			
		||||
	"PC18": {"NCE3"},
 | 
			
		||||
	"PC19": {"NCE4", "SPI2_CS0", "", "", "PC_EINT12"},
 | 
			
		||||
	"PC20": {"NCE5", "SPI2_CLK", "", "", "PC_EINT13"},
 | 
			
		||||
	"PC21": {"NCE6", "SPI2_MOSI", "", "", "PC_EINT14"},
 | 
			
		||||
	"PC22": {"NCE7", "SPI2_MISO", "", "", "PC_EINT15"},
 | 
			
		||||
	"PC23": {"", "SPI2_CS0"},
 | 
			
		||||
	"PC24": {"NDQS"},
 | 
			
		||||
	"PD0":  {"LCD0_D0", "LVDS0_VP0"},
 | 
			
		||||
	"PD1":  {"LCD0_D1", "LVDS0_VN0"},
 | 
			
		||||
	"PD2":  {"LCD0_D2", "LVDS0_VP1"},
 | 
			
		||||
	"PD3":  {"LCD0_D3", "LVDS0_VN1"},
 | 
			
		||||
	"PD4":  {"LCD0_D4", "LVDS0_VP2"},
 | 
			
		||||
	"PD5":  {"LCD0_D5", "LVDS0_VN2"},
 | 
			
		||||
	"PD6":  {"LCD0_D6", "LVDS0_VPC"},
 | 
			
		||||
	"PD7":  {"LCD0_D7", "LVDS0_VNC"},
 | 
			
		||||
	"PD8":  {"LCD0_D8", "LVDS0_VP3"},
 | 
			
		||||
	"PD9":  {"LCD0_D9", "LVDS0_VN3"},
 | 
			
		||||
	"PD10": {"LCD0_D10", "LVDS1_VP0"},
 | 
			
		||||
	"PD11": {"LCD0_D11", "LVDS1_VN0"},
 | 
			
		||||
	"PD12": {"LCD0_D12", "LVDS1_VP1"},
 | 
			
		||||
	"PD13": {"LCD0_D13", "LVDS1_VN1"},
 | 
			
		||||
	"PD14": {"LCD0_D14", "LVDS1_VP2"},
 | 
			
		||||
	"PD15": {"LCD0_D15", "LVDS1_VN2"},
 | 
			
		||||
	"PD16": {"LCD0_D16", "LVDS1_VPC"},
 | 
			
		||||
	"PD17": {"LCD0_D17", "LVDS1_VNC"},
 | 
			
		||||
	"PD18": {"LCD0_D18", "LVDS1_VP3"},
 | 
			
		||||
	"PD19": {"LCD0_D19", "LVDS1_VN3"},
 | 
			
		||||
	"PD20": {"LCD0_D20", "CSI1_MCLK"},
 | 
			
		||||
	"PD21": {"LCD0_D21", "SMC_VPPEN"},
 | 
			
		||||
	"PD22": {"LCD0_D22", "SMC_VPPPP"},
 | 
			
		||||
	"PD23": {"LCD0_D23", "SMC_DET"},
 | 
			
		||||
	"PD24": {"LCD0_CLK", "SMC_VCCEN"},
 | 
			
		||||
	"PD25": {"LCD0_DE", "SMC_RST"},
 | 
			
		||||
	"PD26": {"LCD0_HSYNC", "SMC_SLK"},
 | 
			
		||||
	"PD27": {"LCD0_VSYNC", "SMC_SDA"},
 | 
			
		||||
	"PE0":  {"TS0_CLK", "CSI0_PCLK"},
 | 
			
		||||
	"PE1":  {"TS0_ERR", "CSI0_MCLK"},
 | 
			
		||||
	"PE2":  {"TS0_SYNC", "CSI0_HSYNC"},
 | 
			
		||||
	"PE3":  {"TS0_DLVD", "CSI0_VSYNC"},
 | 
			
		||||
	"PE4":  {"TS0_D0", "CSI0_D0"},
 | 
			
		||||
	"PE5":  {"TS0_D1", "CSI0_D1"},
 | 
			
		||||
	"PE6":  {"TS0_D2", "CSI0_D2"},
 | 
			
		||||
	"PE7":  {"TS0_D3", "CSI0_D3"},
 | 
			
		||||
	"PE8":  {"TS0_D4", "CSI0_D4"},
 | 
			
		||||
	"PE9":  {"TS0_D5", "CSI0_D5"},
 | 
			
		||||
	"PE10": {"TS0_D6", "CSI0_D6"},
 | 
			
		||||
	"PE11": {"TS0_D7", "CSI0_D7"},
 | 
			
		||||
	"PF0":  {"SDC0_D1", "", "JTAG1_TMS"},
 | 
			
		||||
	"PF1":  {"SDC0_D0", "", "JTAG1_TDI"},
 | 
			
		||||
	"PF2":  {"SDC0_CLK", "", "UART0_TX"},
 | 
			
		||||
	"PF3":  {"SDC0_CMD", "", "JTAG1_TDO"},
 | 
			
		||||
	"PF4":  {"SDC0_D3", "", "UART0_RX"},
 | 
			
		||||
	"PF5":  {"SDC0_D2", "", "JTAG1_TCK"},
 | 
			
		||||
	"PG0":  {"TS1_CLK", "CSI1_PCLK", "SDC1_CMD"},
 | 
			
		||||
	"PG1":  {"TS1_ERR", "CSI1_MCLK", "SDC1_CLK"},
 | 
			
		||||
	"PG2":  {"TS1_SYNC", "CSI1_HSYNC", "SDC1_D0"},
 | 
			
		||||
	"PG3":  {"TS1_DVLD", "CSI1_VSYNC", "SDC1_D1"},
 | 
			
		||||
	"PG4":  {"TS1_D0", "CSI1_D0", "SDC1_D2", "CSI0_D8"},
 | 
			
		||||
	"PG5":  {"TS1_D1", "CSI1_D1", "SDC1_D3", "CSI0_D9"},
 | 
			
		||||
	"PG6":  {"TS1_D2", "CSI1_D2", "UART3_TX", "CSI0_D10"},
 | 
			
		||||
	"PG7":  {"TS1_D3", "CSI1_D3", "UART3_RX", "CSI0_D11"},
 | 
			
		||||
	"PG8":  {"TS1_D4", "CSI1_D4", "UART3_RTS", "CSI0_D12"},
 | 
			
		||||
	"PG9":  {"TS1_D5", "CSI1_D4", "UART3_CTS", "CSI0_D13"},
 | 
			
		||||
	"PG10": {"TS1_D6", "CSI1_D6", "UART4_TX", "CSI0_D14"},
 | 
			
		||||
	"PG11": {"TS1_D7", "CSI1_D7", "UART4_RX", "CSI0_D15"},
 | 
			
		||||
	"PH0":  {"LCD1_D0", "", "UART3_TX", "", "PH_EINT0"},
 | 
			
		||||
	"PH1":  {"LCD1_D1", "", "UART3_RX", "", "PH_EINT1"},
 | 
			
		||||
	"PH2":  {"LCD1_D2", "", "UART3_RTS", "", "PH_EINT2"},
 | 
			
		||||
	"PH3":  {"LCD1_D3", "", "UART3_CTS", "", "PH_EINT3"},
 | 
			
		||||
	"PH4":  {"LCD1_D4", "", "UART4_TX", "", "PH_EINT4"},
 | 
			
		||||
	"PH5":  {"LCD1_D5", "", "UART4_RX", "", "PH_EINT5"},
 | 
			
		||||
	"PH6":  {"LCD1_D6", "", "UART5_TX", "MS_BS", "PH_EINT6"},
 | 
			
		||||
	"PH7":  {"LCD1_D7", "", "UART5_RX", "MS_CLK", "PH_EINT7"},
 | 
			
		||||
	"PH8":  {"LCD1_D8", "ERXD3", "KP_IN0", "MS_D0", "PH_EINT8"},
 | 
			
		||||
	"PH9":  {"LCD1_D9", "ERXD2", "KP_IN1", "MS_D1", "PH_EINT9"},
 | 
			
		||||
	"PH10": {"LCD1_D10", "ERXD1", "KP_IN2", "MS_D2", "PH_EINT10"},
 | 
			
		||||
	"PH11": {"LCD1_D11", "ERXD0", "KP_IN3", "MS_D3", "PH_EINT11"},
 | 
			
		||||
	"PH12": {"LCD1_D12", "", "PS2_SCK1", "", "PH_EINT12"},
 | 
			
		||||
	"PH13": {"LCD1_D13", "", "PS2_SDA1", "SMC_RST", "PH_EINT13"},
 | 
			
		||||
	"PH14": {"LCD1_D14", "ETXD3", "KP_IN4", "SMC_VPPEN", "PH_EINT14"},
 | 
			
		||||
	"PH15": {"LCD1_D15", "ETXD2", "KP_IN5", "SMC_VPPPP", "PH_EINT15"},
 | 
			
		||||
	"PH16": {"LCD1_D16", "ETXD1", "KP_IN6", "SMC_DET", "PH_EINT16"},
 | 
			
		||||
	"PH17": {"LCD1_D17", "ETXD0", "KP_IN7", "SMC_VCCEN", "PH_EINT17"},
 | 
			
		||||
	"PH18": {"LCD1_D18", "ERXCK", "KP_OUT0", "SMC_SLK", "PH_EINT18"},
 | 
			
		||||
	"PH19": {"LCD1_D19", "ERXERR", "KP_OUT1", "SMC_SDA", "PH_EINT19"},
 | 
			
		||||
	"PH20": {"LCD1_D20", "ERXDV", "CAN_TX", "", "PH_EINT20"},
 | 
			
		||||
	"PH21": {"LCD1_D21", "EMDC", "CAN_RX", "", "PH_EINT21"},
 | 
			
		||||
	"PH22": {"LCD1_D22", "EMDIO", "KP_OUT2", "SDC1_CMD", ""},
 | 
			
		||||
	"PH23": {"LCD1_D23", "ETXEN", "KP_OUT3", "SDC1_CLK", ""},
 | 
			
		||||
	"PH24": {"LCD1_CLK", "ETXCK", "KP_OUT4", "SDC1_D0", ""},
 | 
			
		||||
	"PH25": {"LCD1_DE", "ECRS", "KP_OUT5", "SDC1_D1", ""},
 | 
			
		||||
	"PH26": {"LCD1_HSYNC", "ECOL", "KP_OUT6", "SDC1_D2", ""},
 | 
			
		||||
	"PH27": {"LCD1_VSYNC", "ETXERR", "KP_OUT7", "SDC1_D3", ""},
 | 
			
		||||
	"PI0":  {"", "I2C3_SCL"},
 | 
			
		||||
	"PI1":  {"", "I2C3_SDA"},
 | 
			
		||||
	"PI2":  {"", "I2C4_SCL"},
 | 
			
		||||
	"PI3":  {"PWM1", "I2C4_SDA"},
 | 
			
		||||
	"PI4":  {"SDC3_CMD"},
 | 
			
		||||
	"PI5":  {"SDC3_CLK"},
 | 
			
		||||
	"PI6":  {"SDC3_D0"},
 | 
			
		||||
	"PI7":  {"SDC3_D1"},
 | 
			
		||||
	"PI8":  {"SDC3_D2"},
 | 
			
		||||
	"PI9":  {"SDC3_D3"},
 | 
			
		||||
	"PI10": {"SPI0_CS0", "UART5_TX", "", "PI_EINT22"},
 | 
			
		||||
	"PI11": {"SPI0_CLK", "UART5_RX", "", "PI_EINT23"},
 | 
			
		||||
	"PI12": {"SPI0_MOSI", "UART6_TX", "CLK_OUT_A", "PI_EINT24"},
 | 
			
		||||
	"PI13": {"SPI0_MISO", "UART6_RX", "CLK_OUT_B", "PI_EINT25"},
 | 
			
		||||
	"PI14": {"SPI0_CS0", "PS2_SCK1", "TCLKIN0", "PI_EINT26"},
 | 
			
		||||
	"PI15": {"SPI1_CS1", "PS2_SDA1", "TCLKIN1", "PI_EINT27"},
 | 
			
		||||
	"PI16": {"SPI1_CS0", "UART2_RTS", "", "PI_EINT28"},
 | 
			
		||||
	"PI17": {"SPI1_CLK", "UART2_CTS", "", "PI_EINT29"},
 | 
			
		||||
	"PI18": {"SPI1_MOSI", "UART2_TX", "", "PI_EINT30"},
 | 
			
		||||
	"PI19": {"SPI1_MISO", "UART2_RX", "", "PI_EINT31"},
 | 
			
		||||
	"PI20": {"PS2_SCK0", "UART7_TX", "HSCL"},
 | 
			
		||||
	"PI21": {"PS2_SDA0", "UART7_RX", "HSDA"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mapA20Pins uses mappingA20 to actually set the altFunc fields of all gpio
 | 
			
		||||
// and mark them as available.
 | 
			
		||||
//
 | 
			
		||||
// It is called by the generic allwinner processor code if an A20 is detected.
 | 
			
		||||
func mapA20Pins() error {
 | 
			
		||||
	for name, altFuncs := range mappingA20 {
 | 
			
		||||
		pin := cpupins[name]
 | 
			
		||||
		pin.altFunc = altFuncs
 | 
			
		||||
		pin.available = true
 | 
			
		||||
		if strings.Contains(string(altFuncs[4]), "_EINT") ||
 | 
			
		||||
			strings.Contains(string(altFuncs[3]), "_EINT") {
 | 
			
		||||
			pin.supportEdge = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Initializes the sysfs corresponding pin right away.
 | 
			
		||||
		pin.sysfsPin = sysfs.Pins[pin.Number()]
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										174
									
								
								vendor/periph.io/x/periph/host/allwinner/a64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								vendor/periph.io/x/periph/host/allwinner/a64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,174 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// This file contains pin mapping information that is specific to the Allwinner
 | 
			
		||||
// A64 model.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn/pin"
 | 
			
		||||
	"periph.io/x/periph/host/sysfs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A64 specific pins.
 | 
			
		||||
var (
 | 
			
		||||
	X32KFOUT *pin.BasicPin // Clock output of 32Khz crystal
 | 
			
		||||
	KEY_ADC  *pin.BasicPin // 6 bits resolution ADC for key application; can work up to 250Hz conversion rate; reference voltage is 2.0V
 | 
			
		||||
	EAROUTP  *pin.BasicPin // Earpiece amplifier negative differential output
 | 
			
		||||
	EAROUTN  *pin.BasicPin // Earpiece amplifier positive differential output
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	X32KFOUT = &pin.BasicPin{N: "X32KFOUT"}
 | 
			
		||||
	// BUG(maruel): These need to be converted to an analog.PinIO implementation
 | 
			
		||||
	// once analog support is implemented.
 | 
			
		||||
	KEY_ADC = &pin.BasicPin{N: "KEY_ADC"}
 | 
			
		||||
	EAROUTP = &pin.BasicPin{N: "EAROUTP"}
 | 
			
		||||
	EAROUTN = &pin.BasicPin{N: "EAROUTN"}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mappingA64 describes the mapping of the A64 processor gpios to their
 | 
			
		||||
// alternate functions.
 | 
			
		||||
//
 | 
			
		||||
// It omits the in & out functions which are available on all gpio.
 | 
			
		||||
//
 | 
			
		||||
// The mapping comes from the datasheet page 23:
 | 
			
		||||
// http://files.pine64.org/doc/datasheet/pine64/A64_Datasheet_V1.1.pdf
 | 
			
		||||
//
 | 
			
		||||
// - The datasheet uses TWI instead of I2C but it is renamed here for
 | 
			
		||||
//   consistency.
 | 
			
		||||
// - AIF is an audio interface, i.e. to connect to S/PDIF.
 | 
			
		||||
// - RGMII means Reduced gigabit media-independent interface.
 | 
			
		||||
// - SDC means SDCard?
 | 
			
		||||
// - NAND connects to a NAND flash controller.
 | 
			
		||||
// - CSI and CCI are for video capture.
 | 
			
		||||
var mappingA64 = map[string][5]pin.Func{
 | 
			
		||||
	"PB0":  {"UART2_TX", "", "JTAG0_TMS", "", "PB_EINT0"},
 | 
			
		||||
	"PB1":  {"UART2_RX", "", "JTAG0_TCK", "SIM_PWREN", "PB_EINT1"},
 | 
			
		||||
	"PB2":  {"UART2_RTS", "", "JTAG0_TDO", "SIM_VPPEN", "PB_EINT2"},
 | 
			
		||||
	"PB3":  {"UART2_CTS", "I2S0_MCLK", "JTAG0_TDI", "SIM_VPPPP", "PB_EINT3"},
 | 
			
		||||
	"PB4":  {"AIF2_SYNC", "I2S0_WS", "", "SIM_CLK", "PB_EINT4"},
 | 
			
		||||
	"PB5":  {"AIF2_BCLK", "I2S0_SCK", "", "SIM_DATA", "PB_EINT5"},
 | 
			
		||||
	"PB6":  {"AIF2_DOUT", "I2S0_DOUT", "", "SIM_RST", "PB_EINT6"},
 | 
			
		||||
	"PB7":  {"AIF2_DIN", "I2S0_DIN", "", "SIM_DET", "PB_EINT7"},
 | 
			
		||||
	"PB8":  {"", "", "UART0_TX", "", "PB_EINT8"},
 | 
			
		||||
	"PB9":  {"", "", "UART0_RX", "", "PB_EINT9"},
 | 
			
		||||
	"PC0":  {"NAND_WE", "", "SPI0_MOSI"},
 | 
			
		||||
	"PC1":  {"NAND_ALE", "SDC2_DS", "SPI0_MISO"},
 | 
			
		||||
	"PC2":  {"NAND_CLE", "", "SPI0_CLK"},
 | 
			
		||||
	"PC3":  {"NAND_CE1", "", "SPI0_CS0"},
 | 
			
		||||
	"PC4":  {"NAND_CE0"},
 | 
			
		||||
	"PC5":  {"NAND_RE", "SDC2_CLK"},
 | 
			
		||||
	"PC6":  {"NAND_RB0", "SDC2_CMD"},
 | 
			
		||||
	"PC7":  {"NAND_RB1"},
 | 
			
		||||
	"PC8":  {"NAND_DQ0", "SDC2_D0"},
 | 
			
		||||
	"PC9":  {"NAND_DQ1", "SDC2_D1"},
 | 
			
		||||
	"PC10": {"NAND_DQ2", "SDC2_D2"},
 | 
			
		||||
	"PC11": {"NAND_DQ3", "SDC2_D3"},
 | 
			
		||||
	"PC12": {"NAND_DQ4", "SDC2_D4"},
 | 
			
		||||
	"PC13": {"NAND_DQ5", "SDC2_D5"},
 | 
			
		||||
	"PC14": {"NAND_DQ6", "SDC2_D6"},
 | 
			
		||||
	"PC15": {"NAND_DQ7", "SDC2_D7"},
 | 
			
		||||
	"PC16": {"NAND_DQS", "SDC2_RST"},
 | 
			
		||||
	"PD0":  {"LCD_D2", "UART3_TX", "SPI1_CS0", "CCIR_CLK"},
 | 
			
		||||
	"PD1":  {"LCD_D3", "UART3_RX", "SPI1_CLK", "CCIR_DE"},
 | 
			
		||||
	"PD2":  {"LCD_D4", "UART4_TX", "SPI1_MOSI", "CCIR_HSYNC"},
 | 
			
		||||
	"PD3":  {"LCD_D5", "UART4_RX", "SPI1_MISO", "CCIR_VSYNC"},
 | 
			
		||||
	"PD4":  {"LCD_D6", "UART4_RTS", "", "CCIR_D0"},
 | 
			
		||||
	"PD5":  {"LCD_D7", "UART4_CTS", "", "CCIR_D1"},
 | 
			
		||||
	"PD6":  {"LCD_D10", "", "", "CCIR_D2"},
 | 
			
		||||
	"PD7":  {"LCD_D11", "", "", "CCIR_D3"},
 | 
			
		||||
	"PD8":  {"LCD_D12", "", "RGMII_RXD3", "CCIR_D4"},
 | 
			
		||||
	"PD9":  {"LCD_D13", "", "RGMII_RXD2", "CCIR_D5"},
 | 
			
		||||
	"PD10": {"LCD_D14", "", "RGMII_RXD1"},
 | 
			
		||||
	"PD11": {"LCD_D15", "", "RGMII_RXD0"},
 | 
			
		||||
	"PD12": {"LCD_D18", "LVDS_VP0", "RGMII_RXCK"},
 | 
			
		||||
	"PD13": {"LCD_D19", "LVDS_VN0", "RGMII_RXCT"},
 | 
			
		||||
	"PD14": {"LCD_D20", "LVDS_VP1", "RGMII_RXER"},
 | 
			
		||||
	"PD15": {"LCD_D21", "LVDS_VN1", "RGMII_TXD3", "CCIR_D6"},
 | 
			
		||||
	"PD16": {"LCD_D22", "LVDS_VP2", "RGMII_TXD2", "CCIR_D7"},
 | 
			
		||||
	"PD17": {"LCD_D23", "LVDS_VN2", "RGMII_TXD1"},
 | 
			
		||||
	"PD18": {"LCD_CLK", "LVDS_VPC", "RGMII_TXD0"},
 | 
			
		||||
	"PD19": {"LCD_DE", "LVDS_VNC", "RGMII_TXCK"},
 | 
			
		||||
	"PD20": {"LCD_HSYNC", "LVDS_VP3", "RGMII_TXCT"},
 | 
			
		||||
	"PD21": {"LCD_VSYNC", "LVDS_VN3", "RGMII_CLKI"},
 | 
			
		||||
	"PD22": {"PWM0", "", "MDC"},
 | 
			
		||||
	"PD23": {"", "", "MDIO"},
 | 
			
		||||
	"PD24": {""},
 | 
			
		||||
	"PE0":  {"CSI_PCLK", "", "TS_CLK"},
 | 
			
		||||
	"PE1":  {"CSI_MCLK", "", "TS_ERR"},
 | 
			
		||||
	"PE2":  {"CSI_HSYNC", "", "TS_SYNC"},
 | 
			
		||||
	"PE3":  {"CSI_VSYNC", "", "TS_DVLD"},
 | 
			
		||||
	"PE4":  {"CSI_D0", "", "TS_D0"},
 | 
			
		||||
	"PE5":  {"CSI_D1", "", "TS_D1"},
 | 
			
		||||
	"PE6":  {"CSI_D2", "", "TS_D2"},
 | 
			
		||||
	"PE7":  {"CSI_D3", "", "TS_D3"},
 | 
			
		||||
	"PE8":  {"CSI_D4", "", "TS_D4"},
 | 
			
		||||
	"PE9":  {"CSI_D5", "", "TS_D5"},
 | 
			
		||||
	"PE10": {"CSI_D6", "", "TS_D6"},
 | 
			
		||||
	"PE11": {"CSI_D7", "", "TS_D7"},
 | 
			
		||||
	"PE12": {"CSI_SCK"},
 | 
			
		||||
	"PE13": {"CSI_SDA"},
 | 
			
		||||
	"PE14": {"PLL_LOCK_DBG", "I2C2_SCL"},
 | 
			
		||||
	"PE15": {"", "I2C2_SDA"},
 | 
			
		||||
	"PE16": {""},
 | 
			
		||||
	"PE17": {""},
 | 
			
		||||
	"PF0":  {"SDC0_D1", "JTAG1_TMS"},
 | 
			
		||||
	"PF1":  {"SDC0_D0", "JTAG1_TDI"},
 | 
			
		||||
	"PF2":  {"SDC0_CLK", "UART0_TX"},
 | 
			
		||||
	"PF3":  {"SDC0_CMD", "JTAG1_TDO"},
 | 
			
		||||
	"PF4":  {"SDC0_D3", "UART0_RX"},
 | 
			
		||||
	"PF5":  {"SDC0_D2", "JTAG1_TCK"},
 | 
			
		||||
	"PF6":  {""},
 | 
			
		||||
	"PG0":  {"SDC1_CLK", "", "", "", "PG_EINT0"},
 | 
			
		||||
	"PG1":  {"SDC1_CMD", "", "", "", "PG_EINT1"},
 | 
			
		||||
	"PG2":  {"SDC1_D0", "", "", "", "PG_EINT2"},
 | 
			
		||||
	"PG3":  {"SDC1_D1", "", "", "", "PG_EINT3"},
 | 
			
		||||
	"PG4":  {"SDC1_D2", "", "", "", "PG_EINT4"},
 | 
			
		||||
	"PG5":  {"SDC1_D3", "", "", "", "PG_EINT5"},
 | 
			
		||||
	"PG6":  {"UART1_TX", "", "", "", "PG_EINT6"},
 | 
			
		||||
	"PG7":  {"UART1_RX", "", "", "", "PG_EINT7"},
 | 
			
		||||
	"PG8":  {"UART1_RTS", "", "", "", "PG_EINT8"},
 | 
			
		||||
	"PG9":  {"UART1_CTS", "", "", "", "PG_EINT9"},
 | 
			
		||||
	"PG10": {"AIF3_SYNC", "I2S1_WS", "", "", "PG_EINT10"},
 | 
			
		||||
	"PG11": {"AIF3_BCLK", "I2S1_SCK", "", "", "PG_EINT11"},
 | 
			
		||||
	"PG12": {"AIF3_DOUT", "I2S1_DOUT", "", "", "PG_EINT12"},
 | 
			
		||||
	"PG13": {"AIF3_DIN", "I2S1_DIN", "", "", "PG_EINT13"},
 | 
			
		||||
	"PH0":  {"I2C0_SCL", "", "", "", "PH_EINT0"},
 | 
			
		||||
	"PH1":  {"I2C0_SDA", "", "", "", "PH_EINT1"},
 | 
			
		||||
	"PH2":  {"I2C1_SCL", "", "", "", "PH_EINT2"},
 | 
			
		||||
	"PH3":  {"I2C1_SDA", "", "", "", "PH_EINT3"},
 | 
			
		||||
	"PH4":  {"UART3_TX", "", "", "", "PH_EINT4"},
 | 
			
		||||
	"PH5":  {"UART3_RX", "", "", "", "PH_EINT5"},
 | 
			
		||||
	"PH6":  {"UART3_RTS", "", "", "", "PH_EINT6"},
 | 
			
		||||
	"PH7":  {"UART3_CTS", "", "", "", "PH_EINT7"},
 | 
			
		||||
	"PH8":  {"OWA_OUT", "", "", "", "PH_EINT8"},
 | 
			
		||||
	"PH9":  {"", "", "", "", "PH_EINT9"},
 | 
			
		||||
	"PH10": {"MIC_CLK", "", "", "", "PH_EINT10"},
 | 
			
		||||
	"PH11": {"MIC_DATA", "", "", "", "PH_EINT11"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mapA64Pins uses mappingA64 to actually set the altFunc fields of all gpio
 | 
			
		||||
// and mark them as available.
 | 
			
		||||
//
 | 
			
		||||
// It is called by the generic allwinner processor code if an A64 is detected.
 | 
			
		||||
func mapA64Pins() error {
 | 
			
		||||
	for name, altFuncs := range mappingA64 {
 | 
			
		||||
		pin := cpupins[name]
 | 
			
		||||
		pin.altFunc = altFuncs
 | 
			
		||||
		pin.available = true
 | 
			
		||||
		if strings.Contains(string(altFuncs[4]), "_EINT") {
 | 
			
		||||
			pin.supportEdge = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Initializes the sysfs corresponding pin right away.
 | 
			
		||||
		pin.sysfsPin = sysfs.Pins[pin.Number()]
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/periph.io/x/periph/host/allwinner/allwinner_arm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/periph.io/x/periph/host/allwinner/allwinner_arm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
const isArm = true
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/periph.io/x/periph/host/allwinner/allwinner_arm64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/periph.io/x/periph/host/allwinner/allwinner_arm64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build arm64
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
const isArm = true
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/periph.io/x/periph/host/allwinner/allwinner_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/periph.io/x/periph/host/allwinner/allwinner_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build !arm,!arm64
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
const isArm = false
 | 
			
		||||
							
								
								
									
										281
									
								
								vendor/periph.io/x/periph/host/allwinner/clock.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								vendor/periph.io/x/periph/host/allwinner/clock.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,281 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	clockSPIEnable clockSPI = 1 << 31 // SCLK_GATING
 | 
			
		||||
	// 30:26 reserved
 | 
			
		||||
	clockSPIOSC24M clockSPI = 0 << 24 // CLK_SRC_SEL
 | 
			
		||||
	clockSPIPLL6   clockSPI = 1 << 24 // A64: PLL_PERIPH0(1X)
 | 
			
		||||
	clockSPIPLL5   clockSPI = 2 << 24 // A64: PLL_PERIPH1(1X)  R8: PLL5 = DDR
 | 
			
		||||
	// 23:18 reserved
 | 
			
		||||
	clockSPIDiv1a clockSPI = 0 << 16 // CLK_DIV_RATIO_N
 | 
			
		||||
	clockSPIDiv2a clockSPI = 1 << 16 //
 | 
			
		||||
	clockSPIDiv4a clockSPI = 2 << 16 //
 | 
			
		||||
	clockSPIDiv8a clockSPI = 3 << 16 //
 | 
			
		||||
	// 15:4 reserved
 | 
			
		||||
	clockSPIDiv1b  clockSPI = 0 << 0  // CLK_DIV_RATIO_M
 | 
			
		||||
	clockSPIDiv2b  clockSPI = 1 << 0  //
 | 
			
		||||
	clockSPIDiv3b  clockSPI = 2 << 0  //
 | 
			
		||||
	clockSPIDiv4b  clockSPI = 3 << 0  //
 | 
			
		||||
	clockSPIDiv5b  clockSPI = 4 << 0  //
 | 
			
		||||
	clockSPIDiv6b  clockSPI = 5 << 0  //
 | 
			
		||||
	clockSPIDiv7b  clockSPI = 6 << 0  //
 | 
			
		||||
	clockSPIDiv8b  clockSPI = 7 << 0  //
 | 
			
		||||
	clockSPIDiv9b  clockSPI = 8 << 0  //
 | 
			
		||||
	clockSPIDiv10b clockSPI = 9 << 0  //
 | 
			
		||||
	clockSPIDiv11b clockSPI = 10 << 0 //
 | 
			
		||||
	clockSPIDiv12b clockSPI = 11 << 0 //
 | 
			
		||||
	clockSPIDiv13b clockSPI = 12 << 0 //
 | 
			
		||||
	clockSPIDiv14b clockSPI = 13 << 0 //
 | 
			
		||||
	clockSPIDiv15b clockSPI = 14 << 0 //
 | 
			
		||||
	clockSPIDiv16b clockSPI = 15 << 0 //
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Also valid for IR.
 | 
			
		||||
//
 | 
			
		||||
// SPI0_SCLK_CFG_REG / SPI1_SCLK_CFG_REG / SPI2_SCLK_CFG_REG / IR_SCLK_CFG_REG
 | 
			
		||||
//
 | 
			
		||||
// A64: Page 110-111. (Also Page 554?)
 | 
			
		||||
// R8: Page 71.
 | 
			
		||||
type clockSPI uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	clockPLL6Enable     clockPLL6R8Ctl = 1 << 31 // PLL6_Enable
 | 
			
		||||
	clockPLL6Force24Mhz clockPLL6R8Ctl = 1 << 30 // PLL6_BYPASS_EN; force 24Mhz
 | 
			
		||||
	// 29:13 reserved
 | 
			
		||||
	clockPLL6FactorMulN0  clockPLL6R8Ctl = 0 << 8  // PLL6_FACTOR_N
 | 
			
		||||
	clockPLL6FactorMulN1  clockPLL6R8Ctl = 1 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN2  clockPLL6R8Ctl = 2 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN3  clockPLL6R8Ctl = 3 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN4  clockPLL6R8Ctl = 4 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN5  clockPLL6R8Ctl = 5 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN6  clockPLL6R8Ctl = 6 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN7  clockPLL6R8Ctl = 7 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN8  clockPLL6R8Ctl = 8 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN9  clockPLL6R8Ctl = 9 << 8  //
 | 
			
		||||
	clockPLL6FactorMulN10 clockPLL6R8Ctl = 10 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN11 clockPLL6R8Ctl = 11 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN12 clockPLL6R8Ctl = 12 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN13 clockPLL6R8Ctl = 13 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN14 clockPLL6R8Ctl = 14 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN15 clockPLL6R8Ctl = 15 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN16 clockPLL6R8Ctl = 16 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN17 clockPLL6R8Ctl = 17 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN18 clockPLL6R8Ctl = 18 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN19 clockPLL6R8Ctl = 19 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN20 clockPLL6R8Ctl = 20 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN21 clockPLL6R8Ctl = 21 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN22 clockPLL6R8Ctl = 22 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN23 clockPLL6R8Ctl = 23 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN24 clockPLL6R8Ctl = 24 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN25 clockPLL6R8Ctl = 25 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN26 clockPLL6R8Ctl = 26 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN27 clockPLL6R8Ctl = 27 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN28 clockPLL6R8Ctl = 28 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN29 clockPLL6R8Ctl = 29 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN30 clockPLL6R8Ctl = 30 << 8 //
 | 
			
		||||
	clockPLL6FactorMulN31 clockPLL6R8Ctl = 31 << 8 //
 | 
			
		||||
	clockPLL6Damping      clockPLL6R8Ctl = 2 << 6  //
 | 
			
		||||
	clockPLL6FactorMulK1  clockPLL6R8Ctl = 0 << 4  // PLL6_FACTOR_K
 | 
			
		||||
	clockPLL6FactorMulK2  clockPLL6R8Ctl = 1 << 4  //
 | 
			
		||||
	clockPLL6FactorMulK3  clockPLL6R8Ctl = 2 << 4  //
 | 
			
		||||
	clockPLL6FactorMulK4  clockPLL6R8Ctl = 3 << 4  //
 | 
			
		||||
	// 3:2 reserved
 | 
			
		||||
	clockPLL6FactorDivM1 clockPLL6R8Ctl = 0 << 4 // PLL6_FACTOR_M
 | 
			
		||||
	clockPLL6FactorDivM2 clockPLL6R8Ctl = 1 << 4 //
 | 
			
		||||
	clockPLL6FactorDivM3 clockPLL6R8Ctl = 2 << 4 //
 | 
			
		||||
	clockPLL6FactorDivM4 clockPLL6R8Ctl = 3 << 4 //
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PLL6_CFG_REG
 | 
			
		||||
// R8: Page 63; default 0x21009931
 | 
			
		||||
//
 | 
			
		||||
// Output = (24MHz*N*K)/M/2
 | 
			
		||||
// Note: the output 24MHz*N*K clock must be in the range of 240MHz~3GHz if the
 | 
			
		||||
// bypass is disabled.
 | 
			
		||||
type clockPLL6R8Ctl uint32
 | 
			
		||||
 | 
			
		||||
// clockMap is the mapping of important registers across CPUs.
 | 
			
		||||
type clockMap struct {
 | 
			
		||||
	reserved0 [0xA0 / 4]uint32 //
 | 
			
		||||
	spi0Clk   clockSPI         // 0x0A0 SPI0_SCLK_CFG_REG SPI0 Clock
 | 
			
		||||
	spi1Clk   clockSPI         // 0x0A4 SPI1_SCLK_CFG_REG SPI1 Clock
 | 
			
		||||
	spi2Clk   clockSPI         // 0x0A8 SPI2_SCLK_CFG_REG SPI2 Clock (Not on A64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// R8: Page 57-59.
 | 
			
		||||
type clockMapR8 struct {
 | 
			
		||||
	r0      uint32         // 0x000 PLL1_CFG_REG PLL1 Control
 | 
			
		||||
	r1      uint32         // 0x004 PLL1_TUN_REG PLL1 Tuning
 | 
			
		||||
	r2      uint32         // 0x008 PLL2_CFG_REG PLL2 Control
 | 
			
		||||
	r3      uint32         // 0x00C PLL2_TUN_REG PLL2 Tuning
 | 
			
		||||
	r4      uint32         // 0x010 PLL3_CFG_REG PLL3 Control
 | 
			
		||||
	r5      uint32         // 0x014
 | 
			
		||||
	r6      uint32         // 0x018 PLL4_CFG_REG PLL4 Control
 | 
			
		||||
	r7      uint32         // 0x01C
 | 
			
		||||
	r8      uint32         // 0x020 PLL5_CFG_REG PLL5 Control
 | 
			
		||||
	r9      uint32         // 0x024 PLL5_TUN_REG PLL5 Tuning
 | 
			
		||||
	r10     clockPLL6R8Ctl // 0x028 PLL6_CFG_REG PLL6 Control
 | 
			
		||||
	r11     uint32         // 0x02C PLL6 Tuning
 | 
			
		||||
	r12     uint32         // 0x030 PLL7_CFG_REG
 | 
			
		||||
	r13     uint32         // 0x034
 | 
			
		||||
	r14     uint32         // 0x038 PLL1_TUN2_REG PLL1 Tuning2
 | 
			
		||||
	r15     uint32         // 0x03C PLL5_TUN2_REG PLL5 Tuning2
 | 
			
		||||
	r16     uint32         // 0x04C
 | 
			
		||||
	r17     uint32         // 0x050 OSC24M_CFG_REG OSC24M control
 | 
			
		||||
	r18     uint32         // 0x054 CPU_AHB_APB0_CFG_REG CPU, AHB And APB0 Divide Ratio
 | 
			
		||||
	r19     uint32         // 0x058 APB1_CLK_DIV_REG APB1 Clock Divider
 | 
			
		||||
	r20     uint32         // 0x05C AXI_GATING_REG AXI Module Clock Gating
 | 
			
		||||
	r21     uint32         // 0x060 AHB_GATING_REG0 AHB Module Clock Gating 0
 | 
			
		||||
	r22     uint32         // 0x064 AHB_GATING_REG1 AHB Module Clock Gating 1
 | 
			
		||||
	r23     uint32         // 0x068 APB0_GATING_REG APB0 Module Clock Gating
 | 
			
		||||
	r24     uint32         // 0x06C APB1_GATING_REG APB1 Module Clock Gating
 | 
			
		||||
	r25     uint32         // 0x080 NAND_SCLK_CFG_REG Nand Flash Clock
 | 
			
		||||
	r26     uint32         // 0x084
 | 
			
		||||
	r27     uint32         // 0x088 SD0_SCLK_CFG_REG SD0 Clock
 | 
			
		||||
	r28     uint32         // 0x08C SD1_SCLK_CFG_REG SD1 Clock
 | 
			
		||||
	r29     uint32         // 0x090 SD2_SCLK_CFG_REG SD2 Clock
 | 
			
		||||
	r30     uint32         // 0x094
 | 
			
		||||
	r31     uint32         // 0x098
 | 
			
		||||
	r32     uint32         // 0x09C CE_SCLK_CFG_REG Crypto Engine Clock
 | 
			
		||||
	spi0Clk clockSPI       // 0x0A0 SPI0_SCLK_CFG_REG SPI0 Clock
 | 
			
		||||
	spi1Clk clockSPI       // 0x0A4 SPI1_SCLK_CFG_REG SPI1 Clock
 | 
			
		||||
	spi2Clk clockSPI       // 0x0A8 SPI2_SCLK_CFG_REG SPI2 Clock
 | 
			
		||||
	r33     uint32         // 0x0AC
 | 
			
		||||
	irClk   clockSPI       // 0x0B0 IR_SCLK_CFG_REG IR Clock
 | 
			
		||||
	r34     uint32         // 0x0B4
 | 
			
		||||
	r35     uint32         // 0x0B8
 | 
			
		||||
	r36     uint32         // 0x0BC
 | 
			
		||||
	r37     uint32         // 0x0C0
 | 
			
		||||
	r38     uint32         // 0x0C4
 | 
			
		||||
	r39     uint32         // 0x0C8
 | 
			
		||||
	r40     uint32         // 0x0CC
 | 
			
		||||
	r41     uint32         // 0x0D0
 | 
			
		||||
	r42     uint32         // 0x0D4
 | 
			
		||||
	r43     uint32         // 0x100 DRAM_SCLK_CFG_REG DRAM Clock
 | 
			
		||||
	r44     uint32         // 0x104 BE_CFG_REG Display Engine Backend Clock
 | 
			
		||||
	r45     uint32         // 0x108
 | 
			
		||||
	r46     uint32         // 0x10C FE_CFG_REG Display Engine Front End Clock
 | 
			
		||||
	r47     uint32         // 0x110
 | 
			
		||||
	r48     uint32         // 0x114
 | 
			
		||||
	r49     uint32         // 0x118
 | 
			
		||||
	r50     uint32         // 0x11C
 | 
			
		||||
	r51     uint32         // 0x120
 | 
			
		||||
	r52     uint32         // 0x124
 | 
			
		||||
	r53     uint32         // 0x128
 | 
			
		||||
	r54     uint32         // 0x12C LCD_CH1_CFG_REG LCD Channel1 Clock
 | 
			
		||||
	r55     uint32         // 0x130
 | 
			
		||||
	r56     uint32         // 0x134 CSI_CFG_REG CSI Clock
 | 
			
		||||
	r57     uint32         // 0x138
 | 
			
		||||
	r58     uint32         // 0x13C VE_CFG_REG Video Engine Clock
 | 
			
		||||
	r59     uint32         // 0x140 AUDIO_CODEC_SCLK_CFG_REG Audio Codec Gating Special Clock
 | 
			
		||||
	r60     uint32         // 0x144 AVS_SCLK_CFG_REG AVS Gating Special Clock
 | 
			
		||||
	r61     uint32         // 0x148
 | 
			
		||||
	r62     uint32         // 0x14C
 | 
			
		||||
	r63     uint32         // 0x150
 | 
			
		||||
	r64     uint32         // 0x154 MALI_CLOCK_CFG_REG Mali400 Gating Special Clock
 | 
			
		||||
	r65     uint32         // 0x158
 | 
			
		||||
	r66     uint32         // 0x15C MBUS_SCLK_CFG_REG MBUS Gating Clock
 | 
			
		||||
	r67     uint32         // 0x160 IEP_SCLK_CFG_REG IEP Gating Clock
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A64: Page 81-84.
 | 
			
		||||
type clockMapA64 struct {
 | 
			
		||||
	r0      uint32   // 0x000 PLL_CPUX_CTRL_REG PLL_CPUX Control Register
 | 
			
		||||
	r1      uint32   // 0x008 PLL_AUDIO_CTRL_REG PLL_AUDIO Control Register
 | 
			
		||||
	r2      uint32   // 0x010 PLL_VIDEO0_CTRL_REG PLL_VIDEO0 Control Register
 | 
			
		||||
	r3      uint32   // 0x018 PLL_VE_CTRL_REG PLL_VE Control Register
 | 
			
		||||
	r4      uint32   // 0x020 PLL_DDR0_CTRL_REG PLL_DDR0 Control Register
 | 
			
		||||
	r5      uint32   // 0x028 PLL_PERIPH0_CTRL_REG PLL_PERIPH0 Control Register
 | 
			
		||||
	r6      uint32   // 0x02C PLL_PERIPH1_CTRL_REG PLL_PERIPH1 Control Register
 | 
			
		||||
	r7      uint32   // 0x030 PLL_VIDEO1_CTRL_REG PLL_VIDEO1 Control Register
 | 
			
		||||
	r8      uint32   // 0x038 PLL_GPU_CTRL_REG PLL_GPU Control Register
 | 
			
		||||
	r9      uint32   // 0x040 PLL_MIPI_CTRL_REG PLL_MIPI Control Register
 | 
			
		||||
	r10     uint32   // 0x044 PLL_HSIC_CTRL_REG PLL_HSIC Control Register
 | 
			
		||||
	r11     uint32   // 0x048 PLL_DE_CTRL_REG PLL_DE Control Register
 | 
			
		||||
	r12     uint32   // 0x04C PLL_DDR1_CTRL_REG PLL_DDR1 Control Register
 | 
			
		||||
	r13     uint32   // 0x050 CPU_AXI_CFG_REG CPUX/AXI Configuration Register
 | 
			
		||||
	r14     uint32   // 0x054 AHB1_APB1_CFG_REG AHB1/APB1 Configuration Register
 | 
			
		||||
	r15     uint32   // 0x058 APB2_CFG_REG APB2 Configuration Register
 | 
			
		||||
	r16     uint32   // 0x05C AHB2_CFG_REG AHB2 Configuration Register
 | 
			
		||||
	r17     uint32   // 0x060 BUS_CLK_GATING_REG0 Bus Clock Gating Register 0
 | 
			
		||||
	r18     uint32   // 0x064 BUS_CLK_GATING_REG1 Bus Clock Gating Register 1
 | 
			
		||||
	r19     uint32   // 0x068 BUS_CLK_GATING_REG2 Bus Clock Gating Register 2
 | 
			
		||||
	r20     uint32   // 0x06C BUS_CLK_GATING_REG3 Bus Clock Gating Register 3
 | 
			
		||||
	r21     uint32   // 0x070 BUS_CLK_GATING_REG4 Bus Clock Gating Register 4
 | 
			
		||||
	r22     uint32   // 0x074 THS_CLK_REG THS Clock Register
 | 
			
		||||
	r23     uint32   // 0x080 NAND_CLK_REG NAND Clock Register
 | 
			
		||||
	r24     uint32   // 0x088 SDMMC0_CLK_REG SDMMC0 Clock Register
 | 
			
		||||
	r25     uint32   // 0x08C SDMMC1_CLK_REG SDMMC1 Clock Register
 | 
			
		||||
	r26     uint32   // 0x090 SDMMC2_CLK_REG SDMMC2 Clock Register
 | 
			
		||||
	r27     uint32   // 0x098 TS_CLK_REG TS Clock Register
 | 
			
		||||
	r28     uint32   // 0x09C CE_CLK_REG CE Clock Register
 | 
			
		||||
	spi0Clk clockSPI // 0x0A0 SPI0_CLK_REG SPI0 Clock Register
 | 
			
		||||
	spi1Clk clockSPI // 0x0A4 SPI1_CLK_REG SPI1 Clock Register
 | 
			
		||||
	r29     uint32   // 0x0B0 I2S/PCM-0_CLK_REG I2S/PCM-0 Clock Register
 | 
			
		||||
	r30     uint32   // 0x0B4 I2S/PCM-1_CLK_REG I2S/PCM-1 Clock Register
 | 
			
		||||
	r31     uint32   // 0x0B8 I2S/PCM-2_CLK_REG I2S/PCM-2 Clock Register
 | 
			
		||||
	r32     uint32   // 0x0C0 SPDIF_CLK_REG SPDIF Clock Register
 | 
			
		||||
	r33     uint32   // 0x0CC USBPHY_CFG_REG USBPHY Configuration Register
 | 
			
		||||
	r34     uint32   // 0x0F4 DRAM_CFG_REG DRAM Configuration Register
 | 
			
		||||
	r35     uint32   // 0x0F8 PLL_DDR_CFG_REG PLL_DDR Configuration Register
 | 
			
		||||
	r36     uint32   // 0x0FC MBUS_RST_REG MBUS Reset Register
 | 
			
		||||
	r37     uint32   // 0x100 DRAM_CLK_GATING_REG DRAM Clock Gating Register
 | 
			
		||||
	r38     uint32   // 0x104 DE_CLK_REG DE Clock Register
 | 
			
		||||
	r39     uint32   // 0x118 TCON0_CLK_REG TCON0 Clock Register
 | 
			
		||||
	r40     uint32   // 0x11C TCON1_CLK_REG TCON1 Clock Register
 | 
			
		||||
	r41     uint32   // 0x124 DEINTERLACE_CLK_REG DEINTERLACE Clock Register
 | 
			
		||||
	r42     uint32   // 0x130 CSI_MISC_CLK_REG CSI_MISC Clock Register
 | 
			
		||||
	r43     uint32   // 0x134 CSI_CLK_REG CSI Clock Register
 | 
			
		||||
	r44     uint32   // 0x13C VE_CLK_REG VE Clock Register
 | 
			
		||||
	r45     uint32   // 0x140 AC_DIG_CLK_REG AC Digital Clock Register
 | 
			
		||||
	r46     uint32   // 0x144 AVS_CLK_REG AVS Clock Register
 | 
			
		||||
	r47     uint32   // 0x150 HDMI_CLK_REG HDMI Clock Register
 | 
			
		||||
	r48     uint32   // 0x154 HDMI_SLOW_CLK_REG HDMI Slow Clock Register
 | 
			
		||||
	r49     uint32   // 0x15C MBUS_CLK_REG MBUS Clock Register
 | 
			
		||||
	r50     uint32   // 0x168 MIPI_DSI_CLK_REG MIPI_DSI Clock Register
 | 
			
		||||
	r51     uint32   // 0x1A0 GPU_CLK_REG GPU Clock Register
 | 
			
		||||
	r52     uint32   // 0x200 PLL_STABLE_TIME_REG0 PLL Stable Time Register0
 | 
			
		||||
	r53     uint32   // 0x204 PLL_STABLE_TIME_REG1 PLL Stable Time Register1
 | 
			
		||||
	r54     uint32   // 0x21C PLL_PERIPH1_BIAS_REG PLL_PERIPH1 Bias Register
 | 
			
		||||
	r55     uint32   // 0x220 PLL_CPUX_BIAS_REG PLL_CPUX Bias Register
 | 
			
		||||
	r56     uint32   // 0x224 PLL_AUDIO_BIAS_REG PLL_AUDIO Bias Register
 | 
			
		||||
	r57     uint32   // 0x228 PLL_VIDEO0_BIAS_REG PLL_VIDEO0 Bias Register
 | 
			
		||||
	r58     uint32   // 0x22C PLL_VE_BIAS_REG PLL_VE Bias Register
 | 
			
		||||
	r59     uint32   // 0x230 PLL_DDR0_BIAS_REG PLL_DDR0 Bias Register
 | 
			
		||||
	r60     uint32   // 0x234 PLL_PERIPH0_BIAS_REG PLL_PERIPH0 Bias Register
 | 
			
		||||
	r61     uint32   // 0x238 PLL_VIDEO1_BIAS_REG PLL_VIDEO1 Bias Register
 | 
			
		||||
	r62     uint32   // 0x23C PLL_GPU_BIAS_REG PLL_GPU Bias Register
 | 
			
		||||
	r63     uint32   // 0x240 PLL_MIPI_BIAS_REG PLL_MIPI Bias Register
 | 
			
		||||
	r64     uint32   // 0x244 PLL_HSIC_BIAS_REG PLL_HSIC Bias Register
 | 
			
		||||
	r65     uint32   // 0x248 PLL_DE_BIAS_REG PLL_DE Bias Register
 | 
			
		||||
	r66     uint32   // 0x24C PLL_DDR1_BIAS_REG PLL_DDR1 Bias Register
 | 
			
		||||
	r67     uint32   // 0x250 PLL_CPUX_TUN_REG PLL_CPUX Tuning Register
 | 
			
		||||
	r68     uint32   // 0x260 PLL_DDR0_TUN_REG PLL_DDR0 Tuning Register
 | 
			
		||||
	r69     uint32   // 0x270 PLL_MIPI_TUN_REG PLL_MIPI Tuning Register
 | 
			
		||||
	r70     uint32   // 0x27C PLL_PERIPH1_PAT_CTRL_REG PLL_PERIPH1 Pattern Control Register
 | 
			
		||||
	r71     uint32   // 0x280 PLL_CPUX_PAT_CTRL_REG PLL_CPUX Pattern Control Register
 | 
			
		||||
	r72     uint32   // 0x284 PLL_AUDIO_PAT_CTRL_REG PLL_AUDIO Pattern Control Register
 | 
			
		||||
	r73     uint32   // 0x288 PLL_VIDEO0_PAT_CTRL_REG PLL_VIDEO0 Pattern Control Register
 | 
			
		||||
	r74     uint32   // 0x28C PLL_VE_PAT_CTRL_REG PLL_VE Pattern Control Register
 | 
			
		||||
	r75     uint32   // 0x290 PLL_DDR0_PAT_CTRL_REG PLL_DDR0 Pattern Control Register
 | 
			
		||||
	r76     uint32   // 0x298 PLL_VIDEO1_PAT_CTRL_REG PLL_VIDEO1 Pattern Control Register
 | 
			
		||||
	r77     uint32   // 0x29C PLL_GPU_PAT_CTRL_REG PLL_GPU Pattern Control Register
 | 
			
		||||
	r78     uint32   // 0x2A0 PLL_MIPI_PAT_CTRL_REG PLL_MIPI Pattern Control Register
 | 
			
		||||
	r79     uint32   // 0x2A4 PLL_HSIC_PAT_CTRL_REG PLL_HSIC Pattern Control Register
 | 
			
		||||
	r80     uint32   // 0x2A8 PLL_DE_PAT_CTRL_REG PLL_DE Pattern Control Register
 | 
			
		||||
	r81     uint32   // 0x2AC PLL_DDR1_PAT_CTRL_REG0 PLL_DDR1 Pattern Control Register0
 | 
			
		||||
	r82     uint32   // 0x2B0 PLL_DDR1_PAT_CTRL_REG1 PLL_DDR1 Pattern Control Register1
 | 
			
		||||
	r83     uint32   // 0x2C0 BUS_SOFT_RST_REG0 Bus Software Reset Register 0
 | 
			
		||||
	r84     uint32   // 0x2C4 BUS_SOFT_RST_REG1 Bus Software Reset Register 1
 | 
			
		||||
	r85     uint32   // 0x2C8 BUS_SOFT_RST_REG2 Bus Software Reset Register 2
 | 
			
		||||
	r86     uint32   // 0x2D0 BUS_SOFT_RST_REG3 Bus Software Reset Register 3
 | 
			
		||||
	r87     uint32   // 0x2D8 BUS_SOFT_RST_REG4 Bus Software Reset Register 4
 | 
			
		||||
	r88     uint32   // 0x2F0 CCM_SEC_SWITCH_REG CCM Security Switch Register
 | 
			
		||||
	r89     uint32   // 0x300 PS_CTRL_REG PS Control Register
 | 
			
		||||
	r90     uint32   // 0x304 PS_CNT_REG PS Counter Register
 | 
			
		||||
	r91     uint32   // 0x320 PLL_LOCK_CTRL_REG PLL Lock Control Register
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								vendor/periph.io/x/periph/host/allwinner/detect.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								vendor/periph.io/x/periph/host/allwinner/detect.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/host/distro"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Present detects whether the host CPU is an Allwinner CPU.
 | 
			
		||||
//
 | 
			
		||||
// https://en.wikipedia.org/wiki/Allwinner_Technology
 | 
			
		||||
func Present() bool {
 | 
			
		||||
	detection.do()
 | 
			
		||||
	return detection.isAllwinner
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsR8 detects whether the host CPU is an Allwinner R8 CPU.
 | 
			
		||||
//
 | 
			
		||||
// It looks for the string "sun5i-r8" in /proc/device-tree/compatible.
 | 
			
		||||
func IsR8() bool {
 | 
			
		||||
	detection.do()
 | 
			
		||||
	return detection.isR8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsA20 detects whether the host CPU is an Allwinner A20 CPU.
 | 
			
		||||
//
 | 
			
		||||
// It first looks for the string "sun71-a20" in /proc/device-tree/compatible,
 | 
			
		||||
// and if that fails it checks for "Hardware : sun7i" in /proc/cpuinfo.
 | 
			
		||||
func IsA20() bool {
 | 
			
		||||
	detection.do()
 | 
			
		||||
	return detection.isA20
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsA64 detects whether the host CPU is an Allwinner A64 CPU.
 | 
			
		||||
//
 | 
			
		||||
// It looks for the string "sun50iw1p1" in /proc/device-tree/compatible.
 | 
			
		||||
func IsA64() bool {
 | 
			
		||||
	detection.do()
 | 
			
		||||
	return detection.isA64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
type detectionS struct {
 | 
			
		||||
	mu          sync.Mutex
 | 
			
		||||
	done        bool
 | 
			
		||||
	isAllwinner bool
 | 
			
		||||
	isR8        bool
 | 
			
		||||
	isA20       bool
 | 
			
		||||
	isA64       bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var detection detectionS
 | 
			
		||||
 | 
			
		||||
// do contains the CPU detection logic that determines whether we have an
 | 
			
		||||
// Allwinner CPU and if so, which exact model.
 | 
			
		||||
//
 | 
			
		||||
// Sadly there is no science behind this, it's more of a trial and error using
 | 
			
		||||
// as many boards and OS flavors as possible.
 | 
			
		||||
func (d *detectionS) do() {
 | 
			
		||||
	d.mu.Lock()
 | 
			
		||||
	defer d.mu.Unlock()
 | 
			
		||||
	if !d.done {
 | 
			
		||||
		d.done = true
 | 
			
		||||
		if isArm {
 | 
			
		||||
			for _, c := range distro.DTCompatible() {
 | 
			
		||||
				if strings.Contains(c, "sun50iw1p1") {
 | 
			
		||||
					d.isA64 = true
 | 
			
		||||
				}
 | 
			
		||||
				if strings.Contains(c, "sun5i-r8") {
 | 
			
		||||
					d.isR8 = true
 | 
			
		||||
				}
 | 
			
		||||
				if strings.Contains(c, "sun7i-a20") {
 | 
			
		||||
					d.isA20 = true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			d.isAllwinner = d.isA64 || d.isR8 || d.isA20
 | 
			
		||||
 | 
			
		||||
			if !d.isAllwinner {
 | 
			
		||||
				// The kernel in the image that comes pre-installed on the pcDuino3 Nano
 | 
			
		||||
				// is an old 3.x kernel that doesn't expose the device-tree in procfs,
 | 
			
		||||
				// so do an extra check in cpuinfo as well if we haven't detected
 | 
			
		||||
				// anything yet.
 | 
			
		||||
				// Distros based on 4.x kernels do expose it.
 | 
			
		||||
				if hw, ok := distro.CPUInfo()["Hardware"]; ok {
 | 
			
		||||
					if hw == "sun7i" {
 | 
			
		||||
						d.isA20 = true
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										474
									
								
								vendor/periph.io/x/periph/host/allwinner/dma.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										474
									
								
								vendor/periph.io/x/periph/host/allwinner/dma.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,474 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Unlike the bcm283x, the allwinner CPUs do not have a "clear bit" and "set
 | 
			
		||||
// bit" registers, they only have the data register. Also, allwinner CPUs do
 | 
			
		||||
// not support linked lists of DMA buffers. On the other hand, the Allwinner DMA
 | 
			
		||||
// controller supports 8 bits transfers instead of 32-128 bits that the bcm283x
 | 
			
		||||
// DMA controller supports.
 | 
			
		||||
//
 | 
			
		||||
// This means that only 8 bits can be used per sample, and only one stream is
 | 
			
		||||
// necessary. This results in 1/8th th memory usage than on the bcm283x. The
 | 
			
		||||
// drawback is that a block of 8 contiguous GPIO pins must be dedicated to the
 | 
			
		||||
// stream.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph"
 | 
			
		||||
	"periph.io/x/periph/host/pmem"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// dmaMap represents the DMA memory mapped CPU registers.
 | 
			
		||||
//
 | 
			
		||||
// This map is specific to the currently supported CPUs and will have to be
 | 
			
		||||
// adapted as more CPUs are supported. In particular the number of physical
 | 
			
		||||
// channels varies across different CPUs.
 | 
			
		||||
//
 | 
			
		||||
// Note that we modify the DMA controllers without telling the kernel driver.
 | 
			
		||||
// The driver keeps its own table of which DMA channel is available so this
 | 
			
		||||
// code could effectively crash the whole system. It practice this works.
 | 
			
		||||
// #everythingisfine
 | 
			
		||||
type dmaMap struct {
 | 
			
		||||
	irqEn       dmaR8Irq                // DMA_IRQ_EN_REG
 | 
			
		||||
	irqPendStas dmaR8PendingIrq         // DMA_IRQ_PEND_STAS_REG
 | 
			
		||||
	reserved0   [(0x100 - 8) / 4]uint32 //
 | 
			
		||||
	normal      [8]dmaR8NormalGroup     // 0x100 The "8" "normal" DMA channels (only one active at a time so there's effectively one)
 | 
			
		||||
	reserved1   [0x100 / 4]uint32       //
 | 
			
		||||
	dedicated   [8]dmaDedicatedGroup    // 0x300 The 8 "dedicated" (as in actually existing) DMA channels
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dmaMap) getDedicated() int {
 | 
			
		||||
	for i := len(d.dedicated) - 1; i >= 0; i-- {
 | 
			
		||||
		if d.dedicated[i].isAvailable() {
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dmaNormalGroup is the control registers for the first block of 8 DMA
 | 
			
		||||
// controllers.
 | 
			
		||||
//
 | 
			
		||||
// They can be intentionally slowed down, unlike the dedicated DMA ones.
 | 
			
		||||
//
 | 
			
		||||
// The big caveat is that only one controller can be active at a time and the
 | 
			
		||||
// execution sequence is in accordance with the priority level. This means that
 | 
			
		||||
// two normal DMA cannot be used to do simultaneous read and write. This
 | 
			
		||||
// feature is critical for bus bitbanging.
 | 
			
		||||
type dmaR8NormalGroup struct {
 | 
			
		||||
	cfg         ndmaR8Cfg // NDMA_CTRL_REG
 | 
			
		||||
	srcAddr     uint32    // NDMA_SRC_ADDR_REG
 | 
			
		||||
	dstAddr     uint32    // NDMA_DEST_ADDR_REG
 | 
			
		||||
	byteCounter uint32    // NDMA_BC_REG
 | 
			
		||||
	reserved    [4]uint32 //
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dmaR8NormalGroup) isAvailable() bool {
 | 
			
		||||
	return d.cfg == 0 && d.srcAddr == 0 && d.dstAddr == 0 && d.byteCounter == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dmaR8NormalGroup) release() error {
 | 
			
		||||
	d.srcAddr = 0
 | 
			
		||||
	d.dstAddr = 0
 | 
			
		||||
	d.byteCounter = 0
 | 
			
		||||
	d.cfg = ndmaLoad
 | 
			
		||||
	//drvDMA.dmaMemory.irqEn &^= ...
 | 
			
		||||
	//drvDMA.dmaMemory.irqPendStas &^= ...
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dmaNormalGroup is the control registers for the second block of 8 DMA
 | 
			
		||||
// controllers.
 | 
			
		||||
//
 | 
			
		||||
// They support different DReq and can do non-linear streaming.
 | 
			
		||||
type dmaDedicatedGroup struct {
 | 
			
		||||
	cfg         ddmaR8Cfg   // DDMA_CTRL_REG
 | 
			
		||||
	srcAddr     uint32      // DDMA_SRC_ADDR_REG
 | 
			
		||||
	dstAddr     uint32      // DDMA_DEST_ADDR_REG
 | 
			
		||||
	byteCounter uint32      // DDMA_BC_REG (24 bits)
 | 
			
		||||
	reserved0   [2]uint32   //
 | 
			
		||||
	param       ddmaR8Param // DDMA_PARA_REG (dedicated DMA only)
 | 
			
		||||
	reserved1   uint32      //
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dmaDedicatedGroup) isAvailable() bool {
 | 
			
		||||
	return d.cfg == 0 && d.srcAddr == 0 && d.dstAddr == 0 && d.byteCounter == 0 && d.param == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dmaDedicatedGroup) set(srcAddr, dstAddr, l uint32, srcIO, dstIO bool, src ddmaR8Cfg) {
 | 
			
		||||
	d.srcAddr = srcAddr
 | 
			
		||||
	d.dstAddr = dstAddr
 | 
			
		||||
	d.byteCounter = l
 | 
			
		||||
	// TODO(maruel): Slow down the clock by another 2*250x
 | 
			
		||||
	//d.param = ddmaR8Param(250 | 250<<16)
 | 
			
		||||
	d.param = ddmaR8Param(1<<24 | 1<<8 | 1)
 | 
			
		||||
	// All these have value 0. This statement only exist for documentation.
 | 
			
		||||
	cfg := ddmaDstWidth8 | ddmaDstBurst1 | ddmaDstLinear | ddmaSrcWidth8 | ddmaSrcLinear | ddmaSrcBurst1
 | 
			
		||||
	cfg |= src | ddmaBCRemain
 | 
			
		||||
	if srcIO {
 | 
			
		||||
		cfg |= ddmaSrcIOMode
 | 
			
		||||
	} else if dstIO {
 | 
			
		||||
		cfg |= ddmaDstIOMode
 | 
			
		||||
	}
 | 
			
		||||
	d.cfg = ddmaLoad | cfg
 | 
			
		||||
	for i := 0; d.cfg&ddmaLoad != 0 && i < 100000; i++ {
 | 
			
		||||
	}
 | 
			
		||||
	if d.cfg&ddmaLoad != 0 {
 | 
			
		||||
		log.Printf("failed to load DDMA: %# v\n", d)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dmaDedicatedGroup) release() error {
 | 
			
		||||
	d.param = 0
 | 
			
		||||
	d.srcAddr = 0
 | 
			
		||||
	d.dstAddr = 0
 | 
			
		||||
	d.byteCounter = 0
 | 
			
		||||
	d.cfg = ddmaLoad
 | 
			
		||||
	//drvDMA.dmaMemory.irqEn &^= ...
 | 
			
		||||
	//drvDMA.dmaMemory.irqPendStas &^= ...
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31 reserved
 | 
			
		||||
	dma7QueueEndIrq   dmaA64Irq = 1 << 30 // DMA7_END_IRQ_EN; DMA 7 Queue End Transfer Interrupt Enable.
 | 
			
		||||
	dma7PackageEndIrq dmaA64Irq = 1 << 29 // DMA7_PKG_IRQ_EN; DMA 7 Package End Transfer Interrupt Enable.
 | 
			
		||||
	dma7HalfIrq       dmaA64Irq = 1 << 28 // DMA7_HLAF_IRQ_EN; DMA 7 Half Package Transfer Interrupt Enable.
 | 
			
		||||
	// ...
 | 
			
		||||
	// 3 reserved
 | 
			
		||||
	dma0QueueEndIrq   dmaA64Irq = 1 << 2 // DMA0_END_IRQ_EN; DMA 0 Queue End Transfer Interrupt Enable.
 | 
			
		||||
	dma0PackageEndIrq dmaA64Irq = 1 << 1 // DMA0_PKG_IRQ_EN; DMA 0 Package End Transfer Interrupt Enable.
 | 
			
		||||
	dma0HalfIrq       dmaA64Irq = 1 << 0 // DMA0_HLAF_IRQ_EN; DMA 0 Half Package Transfer Interrupt Enable.
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DMA_IRQ_EN_REG
 | 
			
		||||
// A64: Page 199-201.
 | 
			
		||||
type dmaA64Irq uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ddma7EndIrq   dmaR8Irq = 1 << 31 // DDMA7_END_IRQ_EN
 | 
			
		||||
	ddma7HalfIreq dmaR8Irq = 1 << 30 // DDMA7_HF_IRQ_EN
 | 
			
		||||
	// ...
 | 
			
		||||
	ddma0EndIrq   dmaR8Irq = 1 << 17 // DDMA0_END_IRQ_EN
 | 
			
		||||
	ddma0HalfIreq dmaR8Irq = 1 << 16 // DDMA0_HF_IRQ_EN
 | 
			
		||||
	ndma7EndIrq   dmaR8Irq = 1 << 15 // NDMA7_END_IRQ_EN
 | 
			
		||||
	ndma7HalfIreq dmaR8Irq = 1 << 16 // NDDMA7_HF_IRQ_EN
 | 
			
		||||
	// ...
 | 
			
		||||
	ndma0EndIrq dmaR8Irq = 1 << 1 // NDMA0_END_IRQ_EN
 | 
			
		||||
	ndma0HFIreq dmaR8Irq = 1 << 0 // NDMA0_HF_IRQ_EN
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DMA_IRQ_EN_REG
 | 
			
		||||
// R8: Page 124-126.
 | 
			
		||||
type dmaR8Irq uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31 reserved
 | 
			
		||||
	dma7QueueEndIrqPend   dmaA64PendingIrq = 1 << 30 // DMA7_QUEUE_IRQ_PEND; DMA 7 Queue End Transfer Interrupt Pending. Set 1 to the bit will clear it.
 | 
			
		||||
	dma7PackageEndIrqPend dmaA64PendingIrq = 1 << 29 // DMA7_PKG_IRQ_PEND; DMA 7 Package End Transfer Interrupt Pending. Set 1 to the bit will clear it.
 | 
			
		||||
	dma7HalfIrqPend       dmaA64PendingIrq = 1 << 28 // DMA7_HLAF_IRQ_PEND; DMA 7 Half Package Transfer Interrupt Pending. Set 1 to the bit will clear it.
 | 
			
		||||
	// ...
 | 
			
		||||
	// 3 reserved
 | 
			
		||||
	dma0QueueEndIrqPend   dmaA64PendingIrq = 1 << 2 // DMA0_QUEUE_IRQ_PEND; DMA 0 Queue End Transfer Interrupt Pending. Set 1 to the bit will clear it.
 | 
			
		||||
	dma0PackageEndIrqPend dmaA64PendingIrq = 1 << 1 // DMA0_PKG_IRQ_PEND; DMA 0 Package End Transfer Interrupt Pending. Set 1 to the bit will clear it.
 | 
			
		||||
	dma0HalfIrqPend       dmaA64PendingIrq = 1 << 0 // DMA0_HLAF_IRQ_PEND; DMA 0 Half Package Transfer Interrupt Pending. Set 1 to the bit will clear it.
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DMA_IRQ_PEND_REG0
 | 
			
		||||
// A64: Page 201-203.
 | 
			
		||||
type dmaA64PendingIrq uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ddma7EndIrqPend   dmaR8PendingIrq = 1 << 31 // DDMA7_END_IRQ_PEND
 | 
			
		||||
	ddma7HalfIreqPend dmaR8PendingIrq = 1 << 30 // DDMA7_HF_IRQ_PEND
 | 
			
		||||
	// ...
 | 
			
		||||
	ddma0EndIrqPend   dmaR8PendingIrq = 1 << 17 // DDMA0_END_IRQ_PEND
 | 
			
		||||
	ddma0HalfIreqPend dmaR8PendingIrq = 1 << 16 // DDMA0_HF_IRQ_PEND
 | 
			
		||||
	ndma7EndIrqPend   dmaR8PendingIrq = 1 << 15 // NDMA7_END_IRQ_PEND
 | 
			
		||||
	ndma7HalfIreqPend dmaR8PendingIrq = 1 << 16 // NDDMA7_HF_IRQ_PEND
 | 
			
		||||
	// ...
 | 
			
		||||
	ndma0EndIrqPend   dmaR8PendingIrq = 1 << 1 // NDMA0_END_IRQ_PEND
 | 
			
		||||
	ndma0HalfIreqPend dmaR8PendingIrq = 1 << 0 // NDMA0_HF_IRQ_PEND
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DMA_IRQ_PEND_STAS_REG
 | 
			
		||||
// R8: Page 126-129.
 | 
			
		||||
type dmaR8PendingIrq uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ndmaLoad       ndmaR8Cfg = 1 << 31 // NDMA_LOAD
 | 
			
		||||
	ndmaContinuous ndmaR8Cfg = 1 << 30 // NDMA_CONTI_EN Continuous mode
 | 
			
		||||
	ndmaWaitClk0   ndmaR8Cfg = 0 << 27 // NDMA_WAIT_STATE Number of clock to wait for
 | 
			
		||||
	ndmaWaitClk2   ndmaR8Cfg = 1 << 27 // 2(n+1)
 | 
			
		||||
	ndmaWaitClk6   ndmaR8Cfg = 2 << 27 //
 | 
			
		||||
	ndmaWaitClk8   ndmaR8Cfg = 3 << 27 //
 | 
			
		||||
	ndmaWaitClk10  ndmaR8Cfg = 4 << 27 //
 | 
			
		||||
	ndmaWaitClk12  ndmaR8Cfg = 5 << 27 //
 | 
			
		||||
	ndmaWaitClk14  ndmaR8Cfg = 6 << 27 //
 | 
			
		||||
	ndmaWaitClk16  ndmaR8Cfg = 7 << 27 //
 | 
			
		||||
	ndmaDstWidth32 ndmaR8Cfg = 2 << 25 // NDMA_DST_DATA_WIDTH
 | 
			
		||||
	ndmaDstWidth16 ndmaR8Cfg = 1 << 25 //
 | 
			
		||||
	ndmaDstWidth8  ndmaR8Cfg = 0 << 25 //
 | 
			
		||||
	ndmaDstBurst8  ndmaR8Cfg = 2 << 23 // NDMA_DST_BST_LEN
 | 
			
		||||
	ndmaDstBurst4  ndmaR8Cfg = 1 << 23 //
 | 
			
		||||
	ndmaDstBurst1  ndmaR8Cfg = 0 << 23 //
 | 
			
		||||
	// 22 reserved NDMA_CFG_DST_NON_SECURE ?
 | 
			
		||||
	ndmaDstAddrNoInc  ndmaR8Cfg = 1 << 21  // NDMA_DST_ADDR_TYPE
 | 
			
		||||
	ndmaDstDrqIRTX    ndmaR8Cfg = 0 << 16  // NDMA_DST_DRQ_TYPE
 | 
			
		||||
	ndmaDstDrqUART1TX ndmaR8Cfg = 9 << 16  //
 | 
			
		||||
	ndmaDstDrqUART3TX ndmaR8Cfg = 11 << 16 //
 | 
			
		||||
	ndmaDstDrqAudio   ndmaR8Cfg = 19 << 16 // 24.576MHz (Page 53)
 | 
			
		||||
	ndmaDstDrqSRAM    ndmaR8Cfg = 21 << 16 //
 | 
			
		||||
	ndmaDstDrqSPI0TX  ndmaR8Cfg = 24 << 16 //
 | 
			
		||||
	ndmaDstDrqSPI1TX  ndmaR8Cfg = 25 << 16 //
 | 
			
		||||
	ndmaDstDrqSPI2TX  ndmaR8Cfg = 26 << 16 //
 | 
			
		||||
	ndmaDstDrqUSB1    ndmaR8Cfg = 27 << 16 // 480MHz
 | 
			
		||||
	ndmaDstDrqUSB2    ndmaR8Cfg = 28 << 16 //
 | 
			
		||||
	ndmaDstDrqUSB3    ndmaR8Cfg = 29 << 16 //
 | 
			
		||||
	ndmaDstDrqUSB4    ndmaR8Cfg = 30 << 16 //
 | 
			
		||||
	ndmaDstDrqUSB5    ndmaR8Cfg = 31 << 16 //
 | 
			
		||||
	ndmaBCRemain      ndmaR8Cfg = 1 << 15  // BC_MODE_SEL
 | 
			
		||||
	// 14:11 reserved
 | 
			
		||||
	ndmaSrcWidth32 ndmaR8Cfg = 2 << 9 // NDMA_SRC_DATA_WIDTH
 | 
			
		||||
	ndmaSrcWidth16 ndmaR8Cfg = 1 << 9 //
 | 
			
		||||
	ndmaSrcWidth8  ndmaR8Cfg = 0 << 9 //
 | 
			
		||||
	ndmaSrcBurst8  ndmaR8Cfg = 2 << 7 // NDMA_SRC_BST_LEN
 | 
			
		||||
	ndmaSrcBurst4  ndmaR8Cfg = 1 << 7 //
 | 
			
		||||
	ndmaSrcBurst1  ndmaR8Cfg = 0 << 7 //
 | 
			
		||||
	// 6 reserved NDMA_CFG_SRC_NON_SECURE ?
 | 
			
		||||
	ndmaSrcAddrNoInc  ndmaR8Cfg = 1 << 5  // NDMA_SRC_ADDR_TYPE
 | 
			
		||||
	ndmaSrcDrqIRTX    ndmaR8Cfg = 0 << 0  // NDMA_SRC_DRQ_TYPE
 | 
			
		||||
	ndmaSrcDrqUART1RX ndmaR8Cfg = 9 << 0  //
 | 
			
		||||
	ndmaSrcDrqUART3RX ndmaR8Cfg = 11 << 0 //
 | 
			
		||||
	ndmaSrcDrqAudio   ndmaR8Cfg = 19 << 0 // 24.576MHz (Page 53)
 | 
			
		||||
	ndmaSrcDrqSRAM    ndmaR8Cfg = 21 << 0 //
 | 
			
		||||
	ndmaSrcDrqSDRAM   ndmaR8Cfg = 22 << 0 // 0~400MHz
 | 
			
		||||
	ndmaSrcDrqTPAD    ndmaR8Cfg = 23 << 0 //
 | 
			
		||||
	ndmaSrcDrqSPI0RX  ndmaR8Cfg = 24 << 0 //
 | 
			
		||||
	ndmaSrcDrqSPI1RX  ndmaR8Cfg = 25 << 0 //
 | 
			
		||||
	ndmaSrcDrqSPI2RX  ndmaR8Cfg = 26 << 0 //
 | 
			
		||||
	ndmaSrcDrqUSB1    ndmaR8Cfg = 27 << 0 // 480MHz
 | 
			
		||||
	ndmaSrcDrqUSB2    ndmaR8Cfg = 28 << 0 //
 | 
			
		||||
	ndmaSrcDrqUSB3    ndmaR8Cfg = 29 << 0 //
 | 
			
		||||
	ndmaSrcDrqUSB4    ndmaR8Cfg = 30 << 0 //
 | 
			
		||||
	ndmaSrcDrqUSB5    ndmaR8Cfg = 31 << 0 //
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NDMA_CTRL_REG
 | 
			
		||||
// R8: Page 129-131.
 | 
			
		||||
type ndmaR8Cfg uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ddmaLoad       ddmaR8Cfg = 1 << 31 // DDMA_LOAD
 | 
			
		||||
	ddmaBusy       ddmaR8Cfg = 1 << 30 // DDMA_BSY_STA
 | 
			
		||||
	ddmaContinuous ddmaR8Cfg = 1 << 29 // DDMA_CONTI_MODE_EN
 | 
			
		||||
	// 28:27 reserved  28 = DDMA_CFG_DST_NON_SECURE ?
 | 
			
		||||
	ddmaDstWidth32     ddmaR8Cfg = 2 << 25  // DDMA_DST_DATA_WIDTH
 | 
			
		||||
	ddmaDstWidth16     ddmaR8Cfg = 1 << 25  //
 | 
			
		||||
	ddmaDstWidth8      ddmaR8Cfg = 0 << 25  //
 | 
			
		||||
	ddmaDstBurst8      ddmaR8Cfg = 2 << 23  // DDMA_DST_BST_LEN
 | 
			
		||||
	ddmaDstBurst4      ddmaR8Cfg = 1 << 23  //
 | 
			
		||||
	ddmaDstBurst1      ddmaR8Cfg = 0 << 23  //
 | 
			
		||||
	ddmaDstVertical    ddmaR8Cfg = 3 << 21  // DDMA_ADDR_MODE; no idea what it's use it. It's not explained in the datasheet ...
 | 
			
		||||
	ddmaDstHorizontal  ddmaR8Cfg = 2 << 21  // ... and the official drivers/dma/sun6i-dma.c driver doesn't use it
 | 
			
		||||
	ddmaDstIOMode      ddmaR8Cfg = 1 << 21  // Non incrementing
 | 
			
		||||
	ddmaDstLinear      ddmaR8Cfg = 0 << 21  // Normal incrementing position
 | 
			
		||||
	ddmaDstDrqSRAM     ddmaR8Cfg = 0 << 16  // DDMA_DST_DRQ_SEL
 | 
			
		||||
	ddmaDstDrqSDRAM    ddmaR8Cfg = 1 << 16  // DDR ram speed
 | 
			
		||||
	ddmaDstDrqNAND     ddmaR8Cfg = 3 << 16  //
 | 
			
		||||
	ddmaDstDrqUSB0     ddmaR8Cfg = 4 << 16  //
 | 
			
		||||
	ddmaDstDrqSPI1TX   ddmaR8Cfg = 8 << 16  //
 | 
			
		||||
	ddmaDstDrqCryptoTX ddmaR8Cfg = 10 << 16 //
 | 
			
		||||
	ddmaDstDrqTCON0    ddmaR8Cfg = 14 << 16 //
 | 
			
		||||
	ddmaDstDrqSPI0TX   ddmaR8Cfg = 26 << 16 //
 | 
			
		||||
	ddmaDstDrqSPI2TX   ddmaR8Cfg = 28 << 16 //
 | 
			
		||||
	ddmaBCRemain       ddmaR8Cfg = 1 << 15  // BC_MODE_SEL
 | 
			
		||||
	// 14:11 reserved
 | 
			
		||||
	ddmaSrcWidth32    ddmaR8Cfg = 2 << 9 // DDMA_SRC_DATA_WIDTH
 | 
			
		||||
	ddmaSrcWidth16    ddmaR8Cfg = 1 << 9 //
 | 
			
		||||
	ddmaSrcWidth8     ddmaR8Cfg = 0 << 9 //
 | 
			
		||||
	ddmaSrcBurst8     ddmaR8Cfg = 2 << 7 // DDMA_SRC_BST_LEN
 | 
			
		||||
	ddmaSrcBurst4     ddmaR8Cfg = 1 << 7 //
 | 
			
		||||
	ddmaSrcBurst1     ddmaR8Cfg = 0 << 7 //
 | 
			
		||||
	ddmaSrcVertical   ddmaR8Cfg = 3 << 5 // DDMA_SRC_ADDR_MODE
 | 
			
		||||
	ddmaSrcHorizontal ddmaR8Cfg = 2 << 5 //
 | 
			
		||||
	ddmaSrcIOMode     ddmaR8Cfg = 1 << 5 // Non incrementing
 | 
			
		||||
	ddmaSrcLinear     ddmaR8Cfg = 0 << 5 // Normal incrementing position
 | 
			
		||||
	// 4:0 drq
 | 
			
		||||
	ddmaSrcDrqSRAM     ddmaR8Cfg = 0 << 0  // DDMA_SRC_DRQ_TYPE
 | 
			
		||||
	ddmaSrcDrqSDRAM    ddmaR8Cfg = 1 << 0  //
 | 
			
		||||
	ddmaSrcDrqNAND     ddmaR8Cfg = 3 << 0  //
 | 
			
		||||
	ddmaSrcDrqUSB0     ddmaR8Cfg = 4 << 0  //
 | 
			
		||||
	ddmaSrcDrqSPI1RX   ddmaR8Cfg = 9 << 0  //
 | 
			
		||||
	ddmaSrcDrqCryptoRX ddmaR8Cfg = 11 << 0 //
 | 
			
		||||
	ddmaSrcDrqSPI0RX   ddmaR8Cfg = 27 << 0 //
 | 
			
		||||
	ddmaSrcDrqSPI2RX   ddmaR8Cfg = 29 << 0 //
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DDMA_CFG_REG
 | 
			
		||||
// R8: Page 131-134.
 | 
			
		||||
type ddmaR8Cfg uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// For each value, N+1 is actually used.
 | 
			
		||||
	ddmaDstBlkSizeMask      ddmaR8Param = 0xFF << 24 // DEST_DATA_BLK_SIZE
 | 
			
		||||
	ddmaDstWaitClkCycleMask ddmaR8Param = 0xFF << 16 // DEST_WAIT_CLK_CYC
 | 
			
		||||
	ddmaSrcBlkSizeMask      ddmaR8Param = 0xFF << 8  // SRC_DATA_BLK_SIZE
 | 
			
		||||
	ddmaSrcWaitClkCycleMask ddmaR8Param = 0xFF << 0  // SRC_WAIT_CLK_CYC
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DDMA_PARA_REG
 | 
			
		||||
// R8: Page 134.
 | 
			
		||||
type ddmaR8Param uint32
 | 
			
		||||
 | 
			
		||||
// smokeTest allocates two physical pages, ask the DMA controller to copy the
 | 
			
		||||
// data from one page to another (with a small offset) and make sure the
 | 
			
		||||
// content is as expected.
 | 
			
		||||
//
 | 
			
		||||
// This should take a fraction of a second and will make sure the driver is
 | 
			
		||||
// usable.
 | 
			
		||||
func smokeTest() error {
 | 
			
		||||
	const size = 4096  // 4kb
 | 
			
		||||
	const holeSize = 1 // Minimum DMA alignment.
 | 
			
		||||
 | 
			
		||||
	alloc := func(s int) (pmem.Mem, error) {
 | 
			
		||||
		return pmem.Alloc(s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	copyMem := func(pDst, pSrc uint64) error {
 | 
			
		||||
		n := drvDMA.dmaMemory.getDedicated()
 | 
			
		||||
		if n == -1 {
 | 
			
		||||
			return errors.New("no channel available")
 | 
			
		||||
		}
 | 
			
		||||
		drvDMA.dmaMemory.irqEn &^= 3 << uint(2*n+16)
 | 
			
		||||
		drvDMA.dmaMemory.irqPendStas = 3 << uint(2*n+16)
 | 
			
		||||
		ch := &drvDMA.dmaMemory.dedicated[n]
 | 
			
		||||
		defer func() {
 | 
			
		||||
			_ = ch.release()
 | 
			
		||||
		}()
 | 
			
		||||
		ch.set(uint32(pSrc), uint32(pDst)+holeSize, 4096-2*holeSize, false, false, ddmaDstDrqSDRAM|ddmaSrcDrqSDRAM)
 | 
			
		||||
 | 
			
		||||
		for ch.cfg&ddmaBusy != 0 {
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pmem.TestCopy(size, holeSize, alloc, copyMem)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// driverDMA implements periph.Driver.
 | 
			
		||||
//
 | 
			
		||||
// It implements much more than the DMA controller, it also exposes the clocks,
 | 
			
		||||
// the PWM and PCM controllers.
 | 
			
		||||
type driverDMA struct {
 | 
			
		||||
	// dmaMemory is the memory map of the CPU DMA registers.
 | 
			
		||||
	dmaMemory *dmaMap
 | 
			
		||||
	// pwmMemory is the memory map of the CPU PWM registers.
 | 
			
		||||
	pwmMemory *pwmMap
 | 
			
		||||
	// spiMemory is the memory mapping for the spi CPU registers.
 | 
			
		||||
	spiMemory *spiMap
 | 
			
		||||
	// clockMemory is the memory mapping for the clock CPU registers.
 | 
			
		||||
	clockMemory *clockMap
 | 
			
		||||
	// timerMemory is the memory mapping for the timer CPU registers.
 | 
			
		||||
	timerMemory *timerMap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverDMA) String() string {
 | 
			
		||||
	return "allwinner-dma"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverDMA) Prerequisites() []string {
 | 
			
		||||
	return []string{"allwinner-gpio"}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverDMA) After() []string {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverDMA) Init() (bool, error) {
 | 
			
		||||
	// dmaBaseAddr is the physical base address of the DMA registers.
 | 
			
		||||
	var dmaBaseAddr uint32
 | 
			
		||||
	// pwmBaseAddr is the physical base address of the PWM registers.
 | 
			
		||||
	var pwmBaseAddr uint32
 | 
			
		||||
	// spiBaseAddr is the physical base address of the clock registers.
 | 
			
		||||
	var spiBaseAddr uint32
 | 
			
		||||
	// clockBaseAddr is the physical base address of the clock registers.
 | 
			
		||||
	var clockBaseAddr uint32
 | 
			
		||||
	// timerBaseAddr is the physical base address of the timer registers.
 | 
			
		||||
	var timerBaseAddr uint32
 | 
			
		||||
	if IsA64() {
 | 
			
		||||
		// Page 198.
 | 
			
		||||
		dmaBaseAddr = 0x1C02000
 | 
			
		||||
		// Page 194.
 | 
			
		||||
		pwmBaseAddr = 0x1C21400
 | 
			
		||||
		// Page 161.
 | 
			
		||||
		timerBaseAddr = 0x1C20C00
 | 
			
		||||
		// Page 81.
 | 
			
		||||
		clockBaseAddr = 0x1C20000
 | 
			
		||||
		// Page Page 545.
 | 
			
		||||
		spiBaseAddr = 0x01C68000
 | 
			
		||||
	} else if IsR8() {
 | 
			
		||||
		// Page 124.
 | 
			
		||||
		dmaBaseAddr = 0x1C02000
 | 
			
		||||
		// Page 83.
 | 
			
		||||
		pwmBaseAddr = 0x1C20C00 + 0x200
 | 
			
		||||
		// Page 85.
 | 
			
		||||
		timerBaseAddr = 0x1C20C00
 | 
			
		||||
		// Page 57.
 | 
			
		||||
		clockBaseAddr = 0x1C20000
 | 
			
		||||
		// Page 151.
 | 
			
		||||
		spiBaseAddr = 0x01C05000
 | 
			
		||||
	} else {
 | 
			
		||||
		// H3
 | 
			
		||||
		// Page 194.
 | 
			
		||||
		//dmaBaseAddr = 0x1C02000
 | 
			
		||||
		// Page 187.
 | 
			
		||||
		//pwmBaseAddr = 0x1C21400
 | 
			
		||||
		// Page 154.
 | 
			
		||||
		//timerBaseAddr = 0x1C20C00
 | 
			
		||||
		return false, errors.New("unsupported CPU architecture")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := pmem.MapAsPOD(uint64(dmaBaseAddr), &d.dmaMemory); err != nil {
 | 
			
		||||
		if os.IsPermission(err) {
 | 
			
		||||
			return true, fmt.Errorf("need more access, try as root: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := pmem.MapAsPOD(uint64(pwmBaseAddr), &d.pwmMemory); err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := pmem.MapAsPOD(uint64(timerBaseAddr), &d.timerMemory); err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := pmem.MapAsPOD(uint64(clockBaseAddr), &d.clockMemory); err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := pmem.MapAsPOD(uint64(spiBaseAddr), &d.spiMemory); err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true, smokeTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverDMA) Close() error {
 | 
			
		||||
	// Stop DMA and PWM controllers.
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	if false && isArm {
 | 
			
		||||
		// TODO(maruel): This is intense, wait to be sure it works.
 | 
			
		||||
		periph.MustRegister(&drvDMA)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var drvDMA driverDMA
 | 
			
		||||
							
								
								
									
										33
									
								
								vendor/periph.io/x/periph/host/allwinner/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/periph.io/x/periph/host/allwinner/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package allwinner exposes the GPIO functionality that is common to all
 | 
			
		||||
// AllWinner processors.
 | 
			
		||||
//
 | 
			
		||||
// This driver implements memory-mapped GPIO pin manipulation and leverages
 | 
			
		||||
// sysfs-gpio for edge detection.
 | 
			
		||||
//
 | 
			
		||||
// If you are looking at the actual implementation, open doc.go for further
 | 
			
		||||
// implementation details.
 | 
			
		||||
//
 | 
			
		||||
// Datasheets
 | 
			
		||||
//
 | 
			
		||||
// A64: http://files.pine64.org/doc/datasheet/pine64/Allwinner_A64_User_Manual_V1.0.pdf
 | 
			
		||||
//
 | 
			
		||||
// H3: http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf
 | 
			
		||||
//
 | 
			
		||||
// R8: https://github.com/NextThingCo/CHIP-Hardware/raw/master/CHIP%5Bv1_0%5D/CHIPv1_0-BOM-Datasheets/Allwinner%20R8%20User%20Manual%20V1.1.pdf
 | 
			
		||||
//
 | 
			
		||||
// Physical overview: http://files.pine64.org/doc/datasheet/pine64/A64_Datasheet_V1.1.pdf
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
// Other implementation details
 | 
			
		||||
//
 | 
			
		||||
// The most active kernel branch is
 | 
			
		||||
// https://github.com/linux-sunxi/linux-sunxi/commits/sunxi-next
 | 
			
		||||
//
 | 
			
		||||
// In particular look at
 | 
			
		||||
// https://github.com/linux-sunxi/linux-sunxi/blob/sunxi-next/drivers/dma/sun4i-dma.c
 | 
			
		||||
// and
 | 
			
		||||
// https://github.com/linux-sunxi/linux-sunxi/blob/sunxi-next/drivers/dma/sun6i-dma.c
 | 
			
		||||
							
								
								
									
										1065
									
								
								vendor/periph.io/x/periph/host/allwinner/gpio.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1065
									
								
								vendor/periph.io/x/periph/host/allwinner/gpio.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										563
									
								
								vendor/periph.io/x/periph/host/allwinner/gpio_pl.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										563
									
								
								vendor/periph.io/x/periph/host/allwinner/gpio_pl.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,563 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph"
 | 
			
		||||
	"periph.io/x/periph/conn/gpio"
 | 
			
		||||
	"periph.io/x/periph/conn/gpio/gpioreg"
 | 
			
		||||
	"periph.io/x/periph/conn/physic"
 | 
			
		||||
	"periph.io/x/periph/conn/pin"
 | 
			
		||||
	"periph.io/x/periph/host/pmem"
 | 
			
		||||
	"periph.io/x/periph/host/sysfs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// All the pins in the PL group.
 | 
			
		||||
var PL0, PL1, PL2, PL3, PL4, PL5, PL6, PL7, PL8, PL9, PL10, PL11, PL12 *PinPL
 | 
			
		||||
 | 
			
		||||
// PinPL defines one CPU supported pin in the PL group.
 | 
			
		||||
//
 | 
			
		||||
// PinPL implements gpio.PinIO.
 | 
			
		||||
type PinPL struct {
 | 
			
		||||
	// Immutable.
 | 
			
		||||
	offset      uint8     // as per register offset calculation
 | 
			
		||||
	name        string    // name as per datasheet
 | 
			
		||||
	defaultPull gpio.Pull // default pull at startup
 | 
			
		||||
 | 
			
		||||
	// Immutable after driver initialization.
 | 
			
		||||
	sysfsPin  *sysfs.Pin // Set to the corresponding sysfs.Pin, if any.
 | 
			
		||||
	available bool       // Set when the pin is available on this CPU architecture.
 | 
			
		||||
 | 
			
		||||
	// Mutable.
 | 
			
		||||
	usingEdge bool // Set when edge detection is enabled.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements conn.Resource.
 | 
			
		||||
//
 | 
			
		||||
// It returns the pin name and number, ex: "PL5(352)".
 | 
			
		||||
func (p *PinPL) String() string {
 | 
			
		||||
	return fmt.Sprintf("%s(%d)", p.name, p.Number())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Halt implements conn.Resource.
 | 
			
		||||
//
 | 
			
		||||
// It stops edge detection if enabled.
 | 
			
		||||
func (p *PinPL) Halt() error {
 | 
			
		||||
	if p.usingEdge {
 | 
			
		||||
		if err := p.sysfsPin.Halt(); err != nil {
 | 
			
		||||
			return p.wrap(err)
 | 
			
		||||
		}
 | 
			
		||||
		p.usingEdge = false
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name implements pin.Pin.
 | 
			
		||||
//
 | 
			
		||||
// It returns the pin name, ex: "PL5".
 | 
			
		||||
func (p *PinPL) Name() string {
 | 
			
		||||
	return p.name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Number implements pin.Pin.
 | 
			
		||||
//
 | 
			
		||||
// It returns the GPIO pin number as represented by gpio sysfs.
 | 
			
		||||
func (p *PinPL) Number() int {
 | 
			
		||||
	return 11*32 + int(p.offset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Function implements pin.Pin.
 | 
			
		||||
func (p *PinPL) Function() string {
 | 
			
		||||
	return string(p.Func())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Func implements pin.PinFunc.
 | 
			
		||||
func (p *PinPL) Func() pin.Func {
 | 
			
		||||
	if !p.available {
 | 
			
		||||
		// We do not want the error message about uninitialized system.
 | 
			
		||||
		return pin.FuncNone
 | 
			
		||||
	}
 | 
			
		||||
	if drvGPIOPL.gpioMemoryPL == nil {
 | 
			
		||||
		if p.sysfsPin == nil {
 | 
			
		||||
			return pin.Func("ERR")
 | 
			
		||||
		}
 | 
			
		||||
		return p.sysfsPin.Func()
 | 
			
		||||
	}
 | 
			
		||||
	switch f := p.function(); f {
 | 
			
		||||
	case in:
 | 
			
		||||
		if p.FastRead() {
 | 
			
		||||
			return gpio.IN_HIGH
 | 
			
		||||
		}
 | 
			
		||||
		return gpio.IN_LOW
 | 
			
		||||
	case out:
 | 
			
		||||
		if p.FastRead() {
 | 
			
		||||
			return gpio.OUT_HIGH
 | 
			
		||||
		}
 | 
			
		||||
		return gpio.OUT_LOW
 | 
			
		||||
	case alt1:
 | 
			
		||||
		if s := mappingPL[p.offset][0]; len(s) != 0 {
 | 
			
		||||
			return pin.Func(s)
 | 
			
		||||
		}
 | 
			
		||||
		return pin.Func("ALT1")
 | 
			
		||||
	case alt2:
 | 
			
		||||
		if s := mappingPL[p.offset][1]; len(s) != 0 {
 | 
			
		||||
			return pin.Func(s)
 | 
			
		||||
		}
 | 
			
		||||
		return pin.Func("ALT2")
 | 
			
		||||
	case alt3:
 | 
			
		||||
		if s := mappingPL[p.offset][2]; len(s) != 0 {
 | 
			
		||||
			return pin.Func(s)
 | 
			
		||||
		}
 | 
			
		||||
		return pin.Func("ALT3")
 | 
			
		||||
	case alt4:
 | 
			
		||||
		if s := mappingPL[p.offset][3]; len(s) != 0 {
 | 
			
		||||
			return pin.Func(s)
 | 
			
		||||
		}
 | 
			
		||||
		return pin.Func("ALT4")
 | 
			
		||||
	case alt5:
 | 
			
		||||
		if s := mappingPL[p.offset][4]; len(s) != 0 {
 | 
			
		||||
			if strings.Contains(string(s), "_EINT") {
 | 
			
		||||
				// It's an input supporting interrupts.
 | 
			
		||||
				if p.FastRead() {
 | 
			
		||||
					return gpio.IN_HIGH
 | 
			
		||||
				}
 | 
			
		||||
				return gpio.IN_LOW
 | 
			
		||||
			}
 | 
			
		||||
			return pin.Func(s)
 | 
			
		||||
		}
 | 
			
		||||
		return pin.Func("ALT5")
 | 
			
		||||
	case disabled:
 | 
			
		||||
		return pin.FuncNone
 | 
			
		||||
	default:
 | 
			
		||||
		return pin.FuncNone
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SupportedFuncs implements pin.PinFunc.
 | 
			
		||||
func (p *PinPL) SupportedFuncs() []pin.Func {
 | 
			
		||||
	f := make([]pin.Func, 0, 2+2)
 | 
			
		||||
	f = append(f, gpio.IN, gpio.OUT)
 | 
			
		||||
	for _, m := range mappingPL[p.offset] {
 | 
			
		||||
		if m != pin.FuncNone && !strings.Contains(string(m), "_EINT") {
 | 
			
		||||
			f = append(f, m)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetFunc implements pin.PinFunc.
 | 
			
		||||
func (p *PinPL) SetFunc(f pin.Func) error {
 | 
			
		||||
	switch f {
 | 
			
		||||
	case gpio.FLOAT:
 | 
			
		||||
		return p.In(gpio.Float, gpio.NoEdge)
 | 
			
		||||
	case gpio.IN:
 | 
			
		||||
		return p.In(gpio.PullNoChange, gpio.NoEdge)
 | 
			
		||||
	case gpio.IN_LOW:
 | 
			
		||||
		return p.In(gpio.PullDown, gpio.NoEdge)
 | 
			
		||||
	case gpio.IN_HIGH:
 | 
			
		||||
		return p.In(gpio.PullUp, gpio.NoEdge)
 | 
			
		||||
	case gpio.OUT_HIGH:
 | 
			
		||||
		return p.Out(gpio.High)
 | 
			
		||||
	case gpio.OUT_LOW:
 | 
			
		||||
		return p.Out(gpio.Low)
 | 
			
		||||
	default:
 | 
			
		||||
		isGeneral := f == f.Generalize()
 | 
			
		||||
		for i, m := range mappingPL[p.offset] {
 | 
			
		||||
			if m == f || (isGeneral && m.Generalize() == f) {
 | 
			
		||||
				if err := p.Halt(); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				switch i {
 | 
			
		||||
				case 0:
 | 
			
		||||
					p.setFunction(alt1)
 | 
			
		||||
				case 1:
 | 
			
		||||
					p.setFunction(alt2)
 | 
			
		||||
				case 2:
 | 
			
		||||
					p.setFunction(alt3)
 | 
			
		||||
				case 3:
 | 
			
		||||
					p.setFunction(alt4)
 | 
			
		||||
				case 4:
 | 
			
		||||
					p.setFunction(alt5)
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return p.wrap(errors.New("unsupported function"))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// In implements gpio.PinIn.
 | 
			
		||||
func (p *PinPL) In(pull gpio.Pull, edge gpio.Edge) error {
 | 
			
		||||
	if !p.available {
 | 
			
		||||
		// We do not want the error message about uninitialized system.
 | 
			
		||||
		return p.wrap(errors.New("not available on this CPU architecture"))
 | 
			
		||||
	}
 | 
			
		||||
	if p.usingEdge && edge == gpio.NoEdge {
 | 
			
		||||
		if err := p.sysfsPin.Halt(); err != nil {
 | 
			
		||||
			return p.wrap(err)
 | 
			
		||||
		}
 | 
			
		||||
		p.usingEdge = false
 | 
			
		||||
	}
 | 
			
		||||
	if drvGPIOPL.gpioMemoryPL == nil {
 | 
			
		||||
		if p.sysfsPin == nil {
 | 
			
		||||
			return p.wrap(errors.New("subsystem gpiomem not initialized and sysfs not accessible; try running as root?"))
 | 
			
		||||
		}
 | 
			
		||||
		if pull != gpio.PullNoChange {
 | 
			
		||||
			return p.wrap(errors.New("pull cannot be used when subsystem gpiomem not initialized; try running as root?"))
 | 
			
		||||
		}
 | 
			
		||||
		if err := p.sysfsPin.In(pull, edge); err != nil {
 | 
			
		||||
			return p.wrap(err)
 | 
			
		||||
		}
 | 
			
		||||
		p.usingEdge = edge != gpio.NoEdge
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if !p.setFunction(in) {
 | 
			
		||||
		return p.wrap(errors.New("failed to set pin as input"))
 | 
			
		||||
	}
 | 
			
		||||
	if pull != gpio.PullNoChange {
 | 
			
		||||
		off := p.offset / 16
 | 
			
		||||
		shift := 2 * (p.offset % 16)
 | 
			
		||||
		// Do it in a way that is concurrent safe.
 | 
			
		||||
		drvGPIOPL.gpioMemoryPL.pull[off] &^= 3 << shift
 | 
			
		||||
		switch pull {
 | 
			
		||||
		case gpio.PullDown:
 | 
			
		||||
			drvGPIOPL.gpioMemoryPL.pull[off] = 2 << shift
 | 
			
		||||
		case gpio.PullUp:
 | 
			
		||||
			drvGPIOPL.gpioMemoryPL.pull[off] = 1 << shift
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if edge != gpio.NoEdge {
 | 
			
		||||
		if p.sysfsPin == nil {
 | 
			
		||||
			return p.wrap(fmt.Errorf("pin %d is not exported by sysfs", p.Number()))
 | 
			
		||||
		}
 | 
			
		||||
		// This resets pending edges.
 | 
			
		||||
		if err := p.sysfsPin.In(gpio.PullNoChange, edge); err != nil {
 | 
			
		||||
			return p.wrap(err)
 | 
			
		||||
		}
 | 
			
		||||
		p.usingEdge = true
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read implements gpio.PinIn.
 | 
			
		||||
func (p *PinPL) Read() gpio.Level {
 | 
			
		||||
	if drvGPIOPL.gpioMemoryPL == nil {
 | 
			
		||||
		if p.sysfsPin == nil {
 | 
			
		||||
			return gpio.Low
 | 
			
		||||
		}
 | 
			
		||||
		return p.sysfsPin.Read()
 | 
			
		||||
	}
 | 
			
		||||
	return gpio.Level(drvGPIOPL.gpioMemoryPL.data&(1<<p.offset) != 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FastRead reads without verification.
 | 
			
		||||
func (p *PinPL) FastRead() gpio.Level {
 | 
			
		||||
	return gpio.Level(drvGPIOPL.gpioMemoryPL.data&(1<<p.offset) != 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WaitForEdge implements gpio.PinIn.
 | 
			
		||||
func (p *PinPL) WaitForEdge(timeout time.Duration) bool {
 | 
			
		||||
	if p.sysfsPin != nil {
 | 
			
		||||
		return p.sysfsPin.WaitForEdge(timeout)
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pull implements gpio.PinIn.
 | 
			
		||||
func (p *PinPL) Pull() gpio.Pull {
 | 
			
		||||
	if drvGPIOPL.gpioMemoryPL == nil {
 | 
			
		||||
		// If gpioMemoryPL is set, p.available is true.
 | 
			
		||||
		return gpio.PullNoChange
 | 
			
		||||
	}
 | 
			
		||||
	switch (drvGPIOPL.gpioMemoryPL.pull[p.offset/16] >> (2 * (p.offset % 16))) & 3 {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return gpio.Float
 | 
			
		||||
	case 1:
 | 
			
		||||
		return gpio.PullUp
 | 
			
		||||
	case 2:
 | 
			
		||||
		return gpio.PullDown
 | 
			
		||||
	default:
 | 
			
		||||
		// Confused.
 | 
			
		||||
		return gpio.PullNoChange
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultPull implements gpio.PinIn.
 | 
			
		||||
func (p *PinPL) DefaultPull() gpio.Pull {
 | 
			
		||||
	return p.defaultPull
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Out implements gpio.PinOut.
 | 
			
		||||
func (p *PinPL) Out(l gpio.Level) error {
 | 
			
		||||
	if !p.available {
 | 
			
		||||
		// We do not want the error message about uninitialized system.
 | 
			
		||||
		return p.wrap(errors.New("not available on this CPU architecture"))
 | 
			
		||||
	}
 | 
			
		||||
	if drvGPIOPL.gpioMemoryPL == nil {
 | 
			
		||||
		if p.sysfsPin != nil {
 | 
			
		||||
			return p.wrap(errors.New("subsystem gpiomem not initialized and sysfs not accessible; try running as root?"))
 | 
			
		||||
		}
 | 
			
		||||
		return p.sysfsPin.Out(l)
 | 
			
		||||
	}
 | 
			
		||||
	// First disable edges.
 | 
			
		||||
	if err := p.Halt(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	p.FastOut(l)
 | 
			
		||||
	if !p.setFunction(out) {
 | 
			
		||||
		return p.wrap(errors.New("failed to set pin as output"))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FastOut sets a pin output level with Absolutely No error checking.
 | 
			
		||||
//
 | 
			
		||||
// See Pin.FastOut for more information.
 | 
			
		||||
func (p *PinPL) FastOut(l gpio.Level) {
 | 
			
		||||
	bit := uint32(1 << p.offset)
 | 
			
		||||
	if l {
 | 
			
		||||
		drvGPIOPL.gpioMemoryPL.data |= bit
 | 
			
		||||
	} else {
 | 
			
		||||
		drvGPIOPL.gpioMemoryPL.data &^= bit
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PWM implements gpio.PinOut.
 | 
			
		||||
func (p *PinPL) PWM(gpio.Duty, physic.Frequency) error {
 | 
			
		||||
	// TODO(maruel): PWM support for PL10.
 | 
			
		||||
	return p.wrap(errors.New("not available on this CPU architecture"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// function returns the current GPIO pin function.
 | 
			
		||||
//
 | 
			
		||||
// It must not be called if drvGPIOPL.gpioMemoryPL is nil.
 | 
			
		||||
func (p *PinPL) function() function {
 | 
			
		||||
	shift := 4 * (p.offset % 8)
 | 
			
		||||
	return function((drvGPIOPL.gpioMemoryPL.cfg[p.offset/8] >> shift) & 7)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setFunction changes the GPIO pin function.
 | 
			
		||||
//
 | 
			
		||||
// Returns false if the pin was in AltN. Only accepts in and out
 | 
			
		||||
//
 | 
			
		||||
// It must not be called if drvGPIOPL.gpioMemoryPL is nil.
 | 
			
		||||
func (p *PinPL) setFunction(f function) bool {
 | 
			
		||||
	if f != in && f != out {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// Interrupt based edge triggering is Alt5 but this is only supported on some
 | 
			
		||||
	// pins.
 | 
			
		||||
	// TODO(maruel): This check should use a whitelist of pins.
 | 
			
		||||
	if actual := p.function(); actual != in && actual != out && actual != disabled && actual != alt5 {
 | 
			
		||||
		// Pin is in special mode.
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	off := p.offset / 8
 | 
			
		||||
	shift := 4 * (p.offset % 8)
 | 
			
		||||
	mask := uint32(disabled) << shift
 | 
			
		||||
	v := (uint32(f) << shift) ^ mask
 | 
			
		||||
	// First disable, then setup. This is concurrent safe.
 | 
			
		||||
	drvGPIOPL.gpioMemoryPL.cfg[off] |= mask
 | 
			
		||||
	drvGPIOPL.gpioMemoryPL.cfg[off] &^= v
 | 
			
		||||
	if p.function() != f {
 | 
			
		||||
		panic(f)
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PinPL) wrap(err error) error {
 | 
			
		||||
	return fmt.Errorf("allwinner-gpio-pl (%s): %v", p, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// cpuPinsPL is all the pins as supported by the CPU. There is no guarantee that
 | 
			
		||||
// they are actually connected to anything on the board.
 | 
			
		||||
var cpuPinsPL = []PinPL{
 | 
			
		||||
	{offset: 0, name: "PL0", defaultPull: gpio.PullUp},
 | 
			
		||||
	{offset: 1, name: "PL1", defaultPull: gpio.PullUp},
 | 
			
		||||
	{offset: 2, name: "PL2", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 3, name: "PL3", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 4, name: "PL4", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 5, name: "PL5", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 6, name: "PL6", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 7, name: "PL7", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 8, name: "PL8", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 9, name: "PL9", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 10, name: "PL10", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 11, name: "PL11", defaultPull: gpio.Float},
 | 
			
		||||
	{offset: 12, name: "PL12", defaultPull: gpio.Float},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// See gpio.go for details.
 | 
			
		||||
var mappingPL = [13][5]pin.Func{
 | 
			
		||||
	{"RSB_SCK", "I2C_SCL", "", "", "PL_EINT0"}, // PL0
 | 
			
		||||
	{"RSB_SDA", "I2C_SDA", "", "", "PL_EINT1"}, // PL1
 | 
			
		||||
	{"UART_TX", "", "", "", "PL_EINT2"},        // PL2
 | 
			
		||||
	{"UART_RX", "", "", "", "PL_EINT3"},        // PL3
 | 
			
		||||
	{"JTAG_TMS", "", "", "", "PL_EINT4"},       // PL4
 | 
			
		||||
	{"JTAG_TCK", "", "", "", "PL_EINT5"},       // PL5
 | 
			
		||||
	{"JTAG_TDO", "", "", "", "PL_EINT6"},       // PL6
 | 
			
		||||
	{"JTAG_TDI", "", "", "", "PL_EINT7"},       // PL7
 | 
			
		||||
	{"I2C_SCL", "", "", "", "PL_EINT8"},        // PL8
 | 
			
		||||
	{"I2C_SDA", "", "", "", "PL_EINT9"},        // PL9
 | 
			
		||||
	{"PWM0", "", "", "", "PL_EINT10"},          // PL10
 | 
			
		||||
	{"CIR_RX", "", "", "", "PL_EINT11"},        // PL11
 | 
			
		||||
	{"", "", "", "", "PL_EINT12"},              // PL12
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	PL0 = &cpuPinsPL[0]
 | 
			
		||||
	PL1 = &cpuPinsPL[1]
 | 
			
		||||
	PL2 = &cpuPinsPL[2]
 | 
			
		||||
	PL3 = &cpuPinsPL[3]
 | 
			
		||||
	PL4 = &cpuPinsPL[4]
 | 
			
		||||
	PL5 = &cpuPinsPL[5]
 | 
			
		||||
	PL6 = &cpuPinsPL[6]
 | 
			
		||||
	PL7 = &cpuPinsPL[7]
 | 
			
		||||
	PL8 = &cpuPinsPL[8]
 | 
			
		||||
	PL9 = &cpuPinsPL[9]
 | 
			
		||||
	PL10 = &cpuPinsPL[10]
 | 
			
		||||
	PL11 = &cpuPinsPL[11]
 | 
			
		||||
	PL12 = &cpuPinsPL[12]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getBaseAddressPL queries the virtual file system to retrieve the base address
 | 
			
		||||
// of the GPIO registers for GPIO pins in group PL.
 | 
			
		||||
//
 | 
			
		||||
// Defaults to 0x01F02C00 as per datasheet if could query the file system.
 | 
			
		||||
func getBaseAddressPL() uint64 {
 | 
			
		||||
	base := uint64(0x01F02C00)
 | 
			
		||||
	link, err := os.Readlink("/sys/bus/platform/drivers/sun50i-r-pinctrl/driver")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return base
 | 
			
		||||
	}
 | 
			
		||||
	parts := strings.SplitN(path.Base(link), ".", 2)
 | 
			
		||||
	if len(parts) != 2 {
 | 
			
		||||
		return base
 | 
			
		||||
	}
 | 
			
		||||
	base2, err := strconv.ParseUint(parts[0], 16, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return base
 | 
			
		||||
	}
 | 
			
		||||
	return base2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// driverGPIOPL implements periph.Driver.
 | 
			
		||||
type driverGPIOPL struct {
 | 
			
		||||
	// gpioMemoryPL is only the PL group in that case. Note that groups PI, PJ, PK
 | 
			
		||||
	// do not exist.
 | 
			
		||||
	gpioMemoryPL *gpioGroup
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverGPIOPL) String() string {
 | 
			
		||||
	return "allwinner-gpio-pl"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverGPIOPL) Prerequisites() []string {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverGPIOPL) After() []string {
 | 
			
		||||
	return []string{"sysfs-gpio"}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *driverGPIOPL) Init() (bool, error) {
 | 
			
		||||
	// BUG(maruel): H3 supports group PL too.
 | 
			
		||||
	if !IsA64() {
 | 
			
		||||
		return false, errors.New("A64 CPU not detected")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Mark the right pins as available even if the memory map fails so they can
 | 
			
		||||
	// callback to sysfs.Pins.
 | 
			
		||||
	functions := map[pin.Func]struct{}{}
 | 
			
		||||
	for i := range cpuPinsPL {
 | 
			
		||||
		name := cpuPinsPL[i].Name()
 | 
			
		||||
		num := strconv.Itoa(cpuPinsPL[i].Number())
 | 
			
		||||
		cpuPinsPL[i].available = true
 | 
			
		||||
		gpion := "GPIO" + num
 | 
			
		||||
 | 
			
		||||
		// Unregister the pin if already registered. This happens with sysfs-gpio.
 | 
			
		||||
		// Do not error on it, since sysfs-gpio may have failed to load.
 | 
			
		||||
		_ = gpioreg.Unregister(gpion)
 | 
			
		||||
		_ = gpioreg.Unregister(num)
 | 
			
		||||
 | 
			
		||||
		// Register the pin with gpio.
 | 
			
		||||
		if err := gpioreg.Register(&cpuPinsPL[i]); err != nil {
 | 
			
		||||
			return true, err
 | 
			
		||||
		}
 | 
			
		||||
		if err := gpioreg.RegisterAlias(gpion, name); err != nil {
 | 
			
		||||
			return true, err
 | 
			
		||||
		}
 | 
			
		||||
		if err := gpioreg.RegisterAlias(num, name); err != nil {
 | 
			
		||||
			return true, err
 | 
			
		||||
		}
 | 
			
		||||
		switch f := cpuPinsPL[i].Func(); f {
 | 
			
		||||
		case gpio.IN, gpio.OUT, pin.FuncNone:
 | 
			
		||||
		default:
 | 
			
		||||
			// Registering the same alias twice fails. This can happen if two pins
 | 
			
		||||
			// are configured with the same function.
 | 
			
		||||
			if _, ok := functions[f]; !ok {
 | 
			
		||||
				// TODO(maruel): We'd have to clear out the ones from allwinner-gpio
 | 
			
		||||
				// too.
 | 
			
		||||
				functions[f] = struct{}{}
 | 
			
		||||
				_ = gpioreg.RegisterAlias(string(f), name)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now do a second loop but do the alternate functions.
 | 
			
		||||
	for i := range cpuPinsPL {
 | 
			
		||||
		for _, f := range cpuPinsPL[i].SupportedFuncs() {
 | 
			
		||||
			switch f {
 | 
			
		||||
			case gpio.IN, gpio.OUT:
 | 
			
		||||
			default:
 | 
			
		||||
				if _, ok := functions[f]; !ok {
 | 
			
		||||
					// TODO(maruel): We'd have to clear out the ones from allwinner-gpio
 | 
			
		||||
					// too.
 | 
			
		||||
					functions[f] = struct{}{}
 | 
			
		||||
					_ = gpioreg.RegisterAlias(string(f), cpuPinsPL[i].name)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m, err := pmem.Map(getBaseAddressPL(), 4096)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if os.IsPermission(err) {
 | 
			
		||||
			return true, fmt.Errorf("need more access, try as root: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := m.AsPOD(&d.gpioMemoryPL); err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	if isArm {
 | 
			
		||||
		periph.MustRegister(&drvGPIOPL)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var drvGPIOPL driverGPIOPL
 | 
			
		||||
 | 
			
		||||
var _ gpio.PinIO = &PinPL{}
 | 
			
		||||
var _ gpio.PinIn = &PinPL{}
 | 
			
		||||
var _ gpio.PinOut = &PinPL{}
 | 
			
		||||
var _ pin.PinFunc = &PinPL{}
 | 
			
		||||
							
								
								
									
										197
									
								
								vendor/periph.io/x/periph/host/allwinner/pwm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								vendor/periph.io/x/periph/host/allwinner/pwm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const pwmClock = 24000000
 | 
			
		||||
const pwmMaxPeriod = 0x10000
 | 
			
		||||
 | 
			
		||||
// prescalers is the value for pwm0Prescale*
 | 
			
		||||
var prescalers = []struct {
 | 
			
		||||
	freq   uint32
 | 
			
		||||
	scaler pwmPrescale
 | 
			
		||||
}{
 | 
			
		||||
	// Base frequency (min freq is half that) / PWM clock at pwmMaxPeriod
 | 
			
		||||
	{pwmClock, pwmPrescale1},             //  24MHz / 366Hz
 | 
			
		||||
	{pwmClock / 120, pwmPrescale120},     // 200kHz / 3Hz
 | 
			
		||||
	{pwmClock / 180, pwmPrescale180},     // 133kHz / 2Hz
 | 
			
		||||
	{pwmClock / 240, pwmPrescale240},     // 100kHz / 1.5Hz
 | 
			
		||||
	{pwmClock / 360, pwmPrescale360},     //  66kHz / 1.01Hz
 | 
			
		||||
	{pwmClock / 480, pwmPrescale480},     //  50kHz / 0.7Hz
 | 
			
		||||
	{pwmClock / 12000, pwmPrescale12000}, //   2kHz
 | 
			
		||||
	{pwmClock / 24000, pwmPrescale24000}, //   1kHz
 | 
			
		||||
	{pwmClock / 36000, pwmPrescale36000}, // 666 Hz
 | 
			
		||||
	{pwmClock / 48000, pwmPrescale48000}, // 500 Hz
 | 
			
		||||
	{pwmClock / 72000, pwmPrescale72000}, // 333 Hz / 0.005Hz
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31:29 reserved
 | 
			
		||||
	pwmBusy pwmCtl = 1 << 28 // PWM0_RDY
 | 
			
		||||
	// 27:10 reserved (used for pwm1)
 | 
			
		||||
	pwm0Mask       pwmCtl = (1 << 10) - 1
 | 
			
		||||
	pwm0Bypass     pwmCtl = 1 << 9 // PWM0_BYPASS (marked as unused on some drivers?)
 | 
			
		||||
	pwm0PulseStart pwmCtl = 1 << 8 // PWM_CH0_PUL_START
 | 
			
		||||
	pwm0ModePulse  pwmCtl = 1 << 7 // PWM_CHANNEL0_MODE
 | 
			
		||||
	pwm0SCLK       pwmCtl = 1 << 6 // SCLK_CH0_GATING
 | 
			
		||||
	pwm0Polarity   pwmCtl = 1 << 5 // PWM_CH0_ACT_STA
 | 
			
		||||
	pwm0Enable     pwmCtl = 1 << 4 // PWM_CH0_EN
 | 
			
		||||
	// 3:0
 | 
			
		||||
	pwm0PrescaleMask pwmCtl = pwmCtl(pwmPrescaleMask) // PWM_CH0_PRESCAL
 | 
			
		||||
	pwm0Prescale120  pwmCtl = pwmCtl(pwmPrescale120)
 | 
			
		||||
	pwm0Prescale180  pwmCtl = pwmCtl(pwmPrescale180)
 | 
			
		||||
	pwm0Prescale240  pwmCtl = pwmCtl(pwmPrescale240)
 | 
			
		||||
	pwm0Prescale360  pwmCtl = pwmCtl(pwmPrescale360)
 | 
			
		||||
	pwm0Prescale480  pwmCtl = pwmCtl(pwmPrescale480)
 | 
			
		||||
	// 5, 6, 7 reserved
 | 
			
		||||
	pwm0Prescale12000 pwmCtl = pwmCtl(pwmPrescale12000)
 | 
			
		||||
	pwm0Prescale24000 pwmCtl = pwmCtl(pwmPrescale24000)
 | 
			
		||||
	pwm0Prescale36000 pwmCtl = pwmCtl(pwmPrescale36000)
 | 
			
		||||
	pwm0Prescale48000 pwmCtl = pwmCtl(pwmPrescale48000)
 | 
			
		||||
	pwm0Prescale72000 pwmCtl = pwmCtl(pwmPrescale72000)
 | 
			
		||||
	// 13, 14 reserved
 | 
			
		||||
	pwm0Prescale1 pwmCtl = pwmCtl(pwmPrescale1)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A64: Pages 194-195.
 | 
			
		||||
// R8: Pages 83-84.
 | 
			
		||||
type pwmCtl uint32
 | 
			
		||||
 | 
			
		||||
func (p pwmCtl) String() string {
 | 
			
		||||
	var out []string
 | 
			
		||||
	if p&pwmBusy != 0 {
 | 
			
		||||
		out = append(out, "PWM0_RDY")
 | 
			
		||||
		p &^= pwmBusy
 | 
			
		||||
	}
 | 
			
		||||
	if p&pwm0Bypass != 0 {
 | 
			
		||||
		out = append(out, "PWM0_BYPASS")
 | 
			
		||||
		p &^= pwm0Bypass
 | 
			
		||||
	}
 | 
			
		||||
	if p&pwm0PulseStart != 0 {
 | 
			
		||||
		out = append(out, "PWM0_CH0_PUL_START")
 | 
			
		||||
		p &^= pwm0PulseStart
 | 
			
		||||
	}
 | 
			
		||||
	if p&pwm0ModePulse != 0 {
 | 
			
		||||
		out = append(out, "PWM0_CHANNEL0_MODE")
 | 
			
		||||
		p &^= pwm0ModePulse
 | 
			
		||||
	}
 | 
			
		||||
	if p&pwm0SCLK != 0 {
 | 
			
		||||
		out = append(out, "SCLK_CH0_GATING")
 | 
			
		||||
		p &^= pwm0SCLK
 | 
			
		||||
	}
 | 
			
		||||
	if p&pwm0Polarity != 0 {
 | 
			
		||||
		out = append(out, "PWM_CH0_ACT_STA")
 | 
			
		||||
		p &^= pwm0Polarity
 | 
			
		||||
	}
 | 
			
		||||
	if p&pwm0Enable != 0 {
 | 
			
		||||
		out = append(out, "PWM_CH0_EN")
 | 
			
		||||
		p &^= pwm0Enable
 | 
			
		||||
	}
 | 
			
		||||
	out = append(out, pwmPrescale(p&pwm0PrescaleMask).String())
 | 
			
		||||
	p &^= pwm0PrescaleMask
 | 
			
		||||
	if p != 0 {
 | 
			
		||||
		out = append(out, fmt.Sprintf("Unknown(0x%08X)", uint32(p)))
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Join(out, "|")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	pwmPrescaleMask pwmPrescale = 0xF
 | 
			
		||||
	pwmPrescale120  pwmPrescale = 0
 | 
			
		||||
	pwmPrescale180  pwmPrescale = 1
 | 
			
		||||
	pwmPrescale240  pwmPrescale = 2
 | 
			
		||||
	pwmPrescale360  pwmPrescale = 3
 | 
			
		||||
	pwmPrescale480  pwmPrescale = 4
 | 
			
		||||
	// 5, 6, 7 reserved
 | 
			
		||||
	pwmPrescale12000 pwmPrescale = 8
 | 
			
		||||
	pwmPrescale24000 pwmPrescale = 9
 | 
			
		||||
	pwmPrescale36000 pwmPrescale = 10
 | 
			
		||||
	pwmPrescale48000 pwmPrescale = 11
 | 
			
		||||
	pwmPrescale72000 pwmPrescale = 12
 | 
			
		||||
	// 13, 14 reserved
 | 
			
		||||
	pwmPrescale1 pwmPrescale = 15
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type pwmPrescale uint32
 | 
			
		||||
 | 
			
		||||
func (p pwmPrescale) String() string {
 | 
			
		||||
	switch p {
 | 
			
		||||
	case pwmPrescale120:
 | 
			
		||||
		return "/120"
 | 
			
		||||
	case pwmPrescale180:
 | 
			
		||||
		return "/180"
 | 
			
		||||
	case pwmPrescale240:
 | 
			
		||||
		return "/240"
 | 
			
		||||
	case pwmPrescale360:
 | 
			
		||||
		return "/360"
 | 
			
		||||
	case pwmPrescale480:
 | 
			
		||||
		return "/480"
 | 
			
		||||
	case pwmPrescale12000:
 | 
			
		||||
		return "/12k"
 | 
			
		||||
	case pwmPrescale24000:
 | 
			
		||||
		return "/24k"
 | 
			
		||||
	case pwmPrescale36000:
 | 
			
		||||
		return "/36k"
 | 
			
		||||
	case pwmPrescale48000:
 | 
			
		||||
		return "/48k"
 | 
			
		||||
	case pwmPrescale72000:
 | 
			
		||||
		return "/72k"
 | 
			
		||||
	case pwmPrescale1:
 | 
			
		||||
		return "/1"
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Sprintf("InvalidScalar(%d)", p&pwmPrescaleMask)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A64: Page 195.
 | 
			
		||||
// R8: Page 84
 | 
			
		||||
type pwmPeriod uint32
 | 
			
		||||
 | 
			
		||||
func (p pwmPeriod) String() string {
 | 
			
		||||
	return fmt.Sprintf("%d/%d", p&0xFFFF, uint32((p>>16)&0xFFFF)+1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toPeriod(total uint32, active uint16) pwmPeriod {
 | 
			
		||||
	if total > pwmMaxPeriod {
 | 
			
		||||
		total = pwmMaxPeriod
 | 
			
		||||
	}
 | 
			
		||||
	return pwmPeriod(total-1)<<16 | pwmPeriod(active)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getBestPrescale finds the best prescaler.
 | 
			
		||||
//
 | 
			
		||||
// Cycles must be between 2 and 0x10000/2.
 | 
			
		||||
func getBestPrescale(period time.Duration) pwmPrescale {
 | 
			
		||||
	// TODO(maruel): Rewrite this function, it is incorrect.
 | 
			
		||||
	for _, v := range prescalers {
 | 
			
		||||
		p := time.Second / time.Duration(v.freq)
 | 
			
		||||
		smallest := (period / pwmMaxPeriod)
 | 
			
		||||
		largest := (period / 2)
 | 
			
		||||
		if p > smallest && p < largest {
 | 
			
		||||
			return v.scaler
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Period is longer than 196s.
 | 
			
		||||
	return pwmPrescale72000
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// pwmMap represents the PWM memory mapped CPU registers.
 | 
			
		||||
//
 | 
			
		||||
// The base frequency is 24Mhz.
 | 
			
		||||
//
 | 
			
		||||
// TODO(maruel): Some CPU have 2 PWMs.
 | 
			
		||||
type pwmMap struct {
 | 
			
		||||
	ctl    pwmCtl    // PWM_CTRL_REG
 | 
			
		||||
	period pwmPeriod // PWM_CH0_PERIOD
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *pwmMap) String() string {
 | 
			
		||||
	return fmt.Sprintf("pwmMap{%s, %v}", p.ctl, p.period)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										149
									
								
								vendor/periph.io/x/periph/host/allwinner/r8.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								vendor/periph.io/x/periph/host/allwinner/r8.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// This file contains pin mapping information that is specific to the Allwinner
 | 
			
		||||
// R8 model.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn/pin"
 | 
			
		||||
	"periph.io/x/periph/host/sysfs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// R8 specific pins.
 | 
			
		||||
var (
 | 
			
		||||
	FEL            *pin.BasicPin // Boot mode selection
 | 
			
		||||
	MIC_IN         *pin.BasicPin // Microphone in
 | 
			
		||||
	MIC_GND        *pin.BasicPin // Microphone ground
 | 
			
		||||
	HP_LEFT        *pin.BasicPin // Left speaker out
 | 
			
		||||
	HP_RIGHT       *pin.BasicPin // Right speaker out
 | 
			
		||||
	HP_COM         *pin.BasicPin // Speaker common
 | 
			
		||||
	X1, X2, Y1, Y2 *pin.BasicPin // Touch screen pins
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	FEL = &pin.BasicPin{N: "FEL"}
 | 
			
		||||
	MIC_IN = &pin.BasicPin{N: "MIC_IN"}
 | 
			
		||||
	MIC_GND = &pin.BasicPin{N: "MIC_GND"}
 | 
			
		||||
	HP_LEFT = &pin.BasicPin{N: "HP_LEFT"}
 | 
			
		||||
	HP_RIGHT = &pin.BasicPin{N: "HP_RIGHT"}
 | 
			
		||||
	HP_COM = &pin.BasicPin{N: "HP_COM"}
 | 
			
		||||
 | 
			
		||||
	X1 = &pin.BasicPin{N: "X1"}
 | 
			
		||||
	X2 = &pin.BasicPin{N: "X2"}
 | 
			
		||||
	Y1 = &pin.BasicPin{N: "Y1"}
 | 
			
		||||
	Y2 = &pin.BasicPin{N: "Y2"}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mappingR8 describes the mapping of each R8 processor gpio to their alternate
 | 
			
		||||
// functions.
 | 
			
		||||
//
 | 
			
		||||
// It omits the in & out functions which are available on all pins.
 | 
			
		||||
//
 | 
			
		||||
// The mapping comes from the datasheet page 18:
 | 
			
		||||
// https://github.com/NextThingCo/CHIP-Hardware/raw/master/CHIP%5Bv1_0%5D/CHIPv1_0-BOM-Datasheets/Allwinner%20R8%20Datasheet%20V1.2.pdf
 | 
			
		||||
//
 | 
			
		||||
// - The datasheet uses TWI instead of I2C but this is renamed here for consistency.
 | 
			
		||||
var mappingR8 = map[string][5]pin.Func{
 | 
			
		||||
	"PB0":  {"I2C0_SCL"},
 | 
			
		||||
	"PB1":  {"I2C0_SDA"},
 | 
			
		||||
	"PB2":  {"PWM0", "", "", "", "EINT16"},
 | 
			
		||||
	"PB3":  {"IR_TX", "", "", "", "EINT17"},
 | 
			
		||||
	"PB4":  {"IR_RX", "", "", "", "EINT18"},
 | 
			
		||||
	"PB10": {"SPI2_CS1"},
 | 
			
		||||
	"PB15": {"I2C1_SCL"},
 | 
			
		||||
	"PB16": {"I2C1_SDA"},
 | 
			
		||||
	"PB17": {"I2C2_SCL"},
 | 
			
		||||
	"PB18": {"I2C2_SDA"},
 | 
			
		||||
	"PC0":  {"NAND_WE", "SPI0_MOSI"},
 | 
			
		||||
	"PC1":  {"NAND_ALE", "SPI0_MISO"},
 | 
			
		||||
	"PC2":  {"NAND_CLE", "SPI0_CLK"},
 | 
			
		||||
	"PC3":  {"NAND_CE1", "SPI0_CS0"},
 | 
			
		||||
	"PC4":  {"NAND_CE0"},
 | 
			
		||||
	"PC5":  {"NAND_RE"},
 | 
			
		||||
	"PC6":  {"NAND_RB0", "SDC2_CMD"},
 | 
			
		||||
	"PC7":  {"NAND_RB1", "SDC2_CLK"},
 | 
			
		||||
	"PC8":  {"NAND_DQ0", "SDC2_D0"},
 | 
			
		||||
	"PC9":  {"NAND_DQ1", "SDC2_D1"},
 | 
			
		||||
	"PC10": {"NAND_DQ2", "SDC2_D2"},
 | 
			
		||||
	"PC11": {"NAND_DQ3", "SDC2_D3"},
 | 
			
		||||
	"PC12": {"NAND_DQ4", "SDC2_D4"},
 | 
			
		||||
	"PC13": {"NAND_DQ5", "SDC2_D5"},
 | 
			
		||||
	"PC14": {"NAND_DQ6", "SDC2_D6"},
 | 
			
		||||
	"PC15": {"NAND_DQ7", "SDC2_D7"},
 | 
			
		||||
	"PC19": {""},
 | 
			
		||||
	"PD2":  {"LCD_D2", "UART2_TX"},
 | 
			
		||||
	"PD3":  {"LCD_D3", "UART2_RX"},
 | 
			
		||||
	"PD4":  {"LCD_D4", "UART2_CTX"},
 | 
			
		||||
	"PD5":  {"LCD_D5", "UART2_RTS"},
 | 
			
		||||
	"PD6":  {"LCD_D6", "ECRS"},
 | 
			
		||||
	"PD7":  {"LCD_D7", "ECOL"},
 | 
			
		||||
	"PD10": {"LCD_D10", "ERXD0"},
 | 
			
		||||
	"PD11": {"LCD_D11", "ERXD1"},
 | 
			
		||||
	"PD12": {"LCD_D12", "ERXD2"},
 | 
			
		||||
	"PD13": {"LCD_D13", "ERXD3"},
 | 
			
		||||
	"PD14": {"LCD_D14", "ERXCK"},
 | 
			
		||||
	"PD15": {"LCD_D15", "ERXERR"},
 | 
			
		||||
	"PD18": {"LCD_D18", "ERXDV"},
 | 
			
		||||
	"PD19": {"LCD_D19", "ETXD0"},
 | 
			
		||||
	"PD20": {"LCD_D20", "ETXD1"},
 | 
			
		||||
	"PD21": {"LCD_D21", "ETXD2"},
 | 
			
		||||
	"PD22": {"LCD_D22", "ETXD3"},
 | 
			
		||||
	"PD23": {"LCD_D23", "ETXEN"},
 | 
			
		||||
	"PD24": {"LCD_CLK", "ETXCK"},
 | 
			
		||||
	"PD25": {"LCD_DE", "ETXERR"},
 | 
			
		||||
	"PD26": {"LCD_HSYNC", "EMDC"},
 | 
			
		||||
	"PD27": {"LCD_VSYNC", "EMDIO"},
 | 
			
		||||
	"PE0":  {"TS_CLK", "CSI_PCLK", "SPI2_CS0", "", "EINT14"},
 | 
			
		||||
	"PE1":  {"TS_ERR", "CSI_MCLK", "SPI2_CLK", "", "EINT15"},
 | 
			
		||||
	"PE2":  {"TS_SYNC", "CSI_HSYNC", "SPI2_MOSI"},
 | 
			
		||||
	"PE3":  {"TS_DVLD", "CSI_VSYNC", "SPI2_MISO"},
 | 
			
		||||
	"PE4":  {"TS_D0", "CSI_D0", "SDC2_D0"},
 | 
			
		||||
	"PE5":  {"TS_D1", "CSI_D1", "SDC2_D1"},
 | 
			
		||||
	"PE6":  {"TS_D2", "CSI_D2", "SDC2_D2"},
 | 
			
		||||
	"PE7":  {"TS_D3", "CSI_D3", "SDC2_D3"},
 | 
			
		||||
	"PE8":  {"TS_D4", "CSI_D4", "SDC2_CMD"},
 | 
			
		||||
	"PE9":  {"TS_D5", "CSI_D5", "SDC2_CLK"},
 | 
			
		||||
	"PE10": {"TS_D6", "CSI_D6", "UART1_TX"},
 | 
			
		||||
	"PE11": {"TS_D7", "CSI_D7", "UART1_RX"},
 | 
			
		||||
	"PF0":  {"SDC0_D1", "", "JTAG1_TMS"},
 | 
			
		||||
	"PF1":  {"SDC0_D0", "", "JTAG1_TDI"},
 | 
			
		||||
	"PF2":  {"SDC0_CLK", "", "UART0_TX"},
 | 
			
		||||
	"PF3":  {"SDC0_CMD", "", "JTAG1_TDO"},
 | 
			
		||||
	"PF4":  {"SDC0_D3", "", "UART0_RX"},
 | 
			
		||||
	"PF5":  {"SDC0_D2", "", "JTAG1_TCK"},
 | 
			
		||||
	"PG0":  {"GPS_CLK", "", "", "", "EINT0"},
 | 
			
		||||
	"PG1":  {"GPS_SIGN", "", "", "", "EINT1"},
 | 
			
		||||
	"PG2":  {"GPS_MAG", "", "", "", "EINT2"},
 | 
			
		||||
	"PG3":  {"", "", "UART1_TX", "", "EINT3"},
 | 
			
		||||
	"PG4":  {"", "", "UART1_RX", "", "EINT4"},
 | 
			
		||||
	"PG9":  {"SPI1_CS0", "UART3_TX", "", "", "EINT9"},
 | 
			
		||||
	"PG10": {"SPI1_CLK", "UART3_RX", "", "", "EINT10"},
 | 
			
		||||
	"PG11": {"SPI1_MOSI", "UART3_CTS", "", "", "EINT11"},
 | 
			
		||||
	"PG12": {"SPI1_MISO", "UART3_RTS", "", "", "EINT12"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mapR8Pins uses mappingR8 to actually set the altFunc fields of all gpio and
 | 
			
		||||
// mark them as available.
 | 
			
		||||
//
 | 
			
		||||
// It is called by the generic allwinner processor code if a R8 is detected.
 | 
			
		||||
func mapR8Pins() error {
 | 
			
		||||
	for name, altFuncs := range mappingR8 {
 | 
			
		||||
		pin := cpupins[name]
 | 
			
		||||
		pin.altFunc = altFuncs
 | 
			
		||||
		pin.available = true
 | 
			
		||||
		if strings.Contains(string(altFuncs[4]), "EINT") {
 | 
			
		||||
			pin.supportEdge = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Initializes the sysfs corresponding pin right away.
 | 
			
		||||
		pin.sysfsPin = sysfs.Pins[pin.Number()]
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										207
									
								
								vendor/periph.io/x/periph/host/allwinner/spi.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								vendor/periph.io/x/periph/host/allwinner/spi.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,207 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31:20 reserved
 | 
			
		||||
	// Set this bit to โ1โ to make the internal read sample point with a delay of
 | 
			
		||||
	// half cycle of SPI_CLK. It is used in high speed read operation to reduce
 | 
			
		||||
	// the error caused by the time delay of SPI_CLK propagating between master
 | 
			
		||||
	// and slave.
 | 
			
		||||
	// 1 โ delay internal read sample point
 | 
			
		||||
	// 0 โ normal operation, do not delay internal read sample point
 | 
			
		||||
	spiR8HalfDelay       spiR8Ctl = 1 << 19 // Master Sample Data Control
 | 
			
		||||
	spiR8TransmitPause   spiR8Ctl = 1 << 18 // Transmit Pause Enable
 | 
			
		||||
	spiR8CSLevel         spiR8Ctl = 1 << 17 // SS_LEVEL; Chip Select level
 | 
			
		||||
	spiR8CSManual        spiR8Ctl = 1 << 16 // SS_CTRL; Do not switch CS automatically
 | 
			
		||||
	spiR8DiscardHash     spiR8Ctl = 1 << 15 // DHB
 | 
			
		||||
	spiR8DummyBurst      spiR8Ctl = 1 << 14 // DDB
 | 
			
		||||
	spiR8CS0             spiR8Ctl = 0 << 12 // SS; Which CS line to use. For SPI0 only
 | 
			
		||||
	spiR8CS1             spiR8Ctl = 1 << 12 //
 | 
			
		||||
	spiR8CS2             spiR8Ctl = 2 << 12 //
 | 
			
		||||
	spiR8CS3             spiR8Ctl = 3 << 12 //
 | 
			
		||||
	spiR8RapidsReadMode  spiR8Ctl = 1 << 11 // RPSM
 | 
			
		||||
	spiR8ExchangeBurst   spiR8Ctl = 1 << 10 // XCH
 | 
			
		||||
	spiR8RXFIFOReset     spiR8Ctl = 1 << 9  // RXFIFO Reset; Write to reset the FIFO as empty
 | 
			
		||||
	spiR8TXFIFOReset     spiR8Ctl = 1 << 8  // TXFIFO Reset; Write to reset the FIFO as empty
 | 
			
		||||
	spiR8CSBetweenBursts spiR8Ctl = 1 << 7  // SSCTL
 | 
			
		||||
	spiR8LSB             spiR8Ctl = 1 << 6  // LMTF; MSB by default, LSB when set
 | 
			
		||||
	spiR8DDMA            spiR8Ctl = 1 << 5  // DMAM; Use dedicated DMA if set, normal DMA otherwise
 | 
			
		||||
	spiR8CSActiveLow     spiR8Ctl = 1 << 4  // SSPOL; CS line polarity
 | 
			
		||||
	spiR8ClkActiveLow    spiR8Ctl = 1 << 3  // POL; Clock line polarity
 | 
			
		||||
	spiR8PHA             spiR8Ctl = 1 << 2  // PHA; Phase 1 if set (leading edge for setup data)
 | 
			
		||||
	spiR8Master          spiR8Ctl = 1 << 1  // MODE; Slave mode if not set
 | 
			
		||||
	spiR8Enable          spiR8Ctl = 1 << 0  // EN; Enable mode
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SPI_CTL
 | 
			
		||||
// R8: Page 153-155.  Default: 0x0002001C
 | 
			
		||||
type spiR8Ctl uint32
 | 
			
		||||
 | 
			
		||||
// SPI_INTCTL
 | 
			
		||||
// R8: Page 155-156.
 | 
			
		||||
type spiR8IntCtl uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	spiR8ClearInterrupt spiR8IntStatus = 1 << 31 // Clear interrupt busy flag
 | 
			
		||||
	// 30:18 reserved
 | 
			
		||||
	spiR8InvalidSS spiR8IntStatus = 1 << 17 // SSI
 | 
			
		||||
	spiR8TC        spiR8IntStatus = 1 << 16 // TC; Transfer Completed
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SPI_INT_STA
 | 
			
		||||
// R8: Page 156-157.
 | 
			
		||||
type spiR8IntStatus uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31:13 reserved
 | 
			
		||||
	spiR8DMATX3Quarter spiR8DMACtl = 1 << 12 // TXFIFO 3/4 empty
 | 
			
		||||
	spiR8DMATX1Quarter spiR8DMACtl = 1 << 11 // TXFIFO 1/4 empty
 | 
			
		||||
	spiR8DMATXByte     spiR8DMACtl = 1 << 10 // TXFIFO Not Full
 | 
			
		||||
	spiR8DMATXHalf     spiR8DMACtl = 1 << 9  // TXFIFO 1/2 empty
 | 
			
		||||
	spiR8DMATXEmpty    spiR8DMACtl = 1 << 8  // TXFIFO empty
 | 
			
		||||
	// 7:5 reserved
 | 
			
		||||
	spiR8DMARX3Quarter spiR8DMACtl = 1 << 4 // RXFIFO 3/4 empty
 | 
			
		||||
	spiR8DMARX1Quarter spiR8DMACtl = 1 << 3 // RXFIFO 1/4 empty
 | 
			
		||||
	spiR8DMARXByte     spiR8DMACtl = 1 << 2 // RXFIFO Not Full
 | 
			
		||||
	spiR8DMARXHalf     spiR8DMACtl = 1 << 1 // RXFIFO 1/2 empty
 | 
			
		||||
	spiR8DMARXEmpty    spiR8DMACtl = 1 << 0 // RXFIFO empty
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SPI_DMACTL
 | 
			
		||||
// R8: Page 158.
 | 
			
		||||
type spiR8DMACtl uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31:13 reserved
 | 
			
		||||
	spiR8DivRateSelect2 spiR8ClockCtl = 1 << 12 // DRS; Use spiDivXX if set, use mask otherwise
 | 
			
		||||
	spiR8Div2           spiR8ClockCtl = 0 << 8  // CDR1; Use divisor 2^(n+1)
 | 
			
		||||
	spiR8Div4           spiR8ClockCtl = 1 << 8  //
 | 
			
		||||
	spiR8Div8           spiR8ClockCtl = 2 << 8  //
 | 
			
		||||
	spiR8Div16          spiR8ClockCtl = 3 << 8  //
 | 
			
		||||
	spiR8Div32          spiR8ClockCtl = 4 << 8  //
 | 
			
		||||
	spiR8Div64          spiR8ClockCtl = 5 << 8  //
 | 
			
		||||
	spiR8Div128         spiR8ClockCtl = 6 << 8  //
 | 
			
		||||
	spiR8Div256         spiR8ClockCtl = 7 << 8  //
 | 
			
		||||
	spiR8Div512         spiR8ClockCtl = 8 << 8  //
 | 
			
		||||
	spiR8Div1024        spiR8ClockCtl = 9 << 8  //
 | 
			
		||||
	spiR8Div2048        spiR8ClockCtl = 10 << 8 //
 | 
			
		||||
	spiR8Div4096        spiR8ClockCtl = 11 << 8 //
 | 
			
		||||
	spiR8Div8192        spiR8ClockCtl = 12 << 8 //
 | 
			
		||||
	spiR8Div16384       spiR8ClockCtl = 13 << 8 //
 | 
			
		||||
	spiR8Div32768       spiR8ClockCtl = 14 << 8 //
 | 
			
		||||
	spiR8Div65536       spiR8ClockCtl = 15 << 8 //
 | 
			
		||||
	spiR8Div1Mask       spiR8ClockCtl = 0xFF    // CDR2; Use divisor 2*(n+1)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SPI_CCTL
 | 
			
		||||
// R8: Page 159.
 | 
			
		||||
type spiR8ClockCtl uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31:25 reserved
 | 
			
		||||
	spiR8FIFOTXShift = 16 // 0 to 64
 | 
			
		||||
	// 15:7 reserved
 | 
			
		||||
	spiR8FIFORXShift = 0 // 0 to 64
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SPI_FIFO_STA
 | 
			
		||||
// R8: Page 160.
 | 
			
		||||
type spiR8FIFOStatus uint32
 | 
			
		||||
 | 
			
		||||
func (s spiR8FIFOStatus) tx() uint8 {
 | 
			
		||||
	return uint8((uint32(s) >> 16) & 127)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s spiR8FIFOStatus) rx() uint8 {
 | 
			
		||||
	return uint8(uint32(s) & 127)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// spiR8Group is the mapping of SPI registers for one SPI controller.
 | 
			
		||||
// R8: Page 152-153.
 | 
			
		||||
type spiR8Group struct {
 | 
			
		||||
	rx              uint32          // 0x00 SPI_RX_DATA RX Data
 | 
			
		||||
	tx              uint32          // 0x04 SPI_TX_DATA TX Data
 | 
			
		||||
	ctl             spiR8Ctl        // 0x08 SPI_CTL Control
 | 
			
		||||
	intCtl          spiR8IntCtl     // 0x0C SPI_INTCTL Interrupt Control
 | 
			
		||||
	status          spiR8IntStatus  // 0x10 SPI_ST Status
 | 
			
		||||
	dmaCtl          spiR8DMACtl     // 0x14 SPI_DMACTL DMA Control
 | 
			
		||||
	wait            uint32          // 0x18 SPI_WAIT Clock Counter; 16 bits
 | 
			
		||||
	clockCtl        spiR8ClockCtl   // 0x1C SPI_CCTL Clock Rate Control
 | 
			
		||||
	burstCounter    uint32          // 0x20 SPI_BC Burst Counter; 24 bits
 | 
			
		||||
	transmitCounter uint32          // 0x24 SPI_TC Transmit Counter; 24 bits
 | 
			
		||||
	fifoStatus      spiR8FIFOStatus // 0x28 SPI_FIFO_STA FIFO Status
 | 
			
		||||
	reserved        [(0x1000 - 0x02C) / 4]uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *spiR8Group) setup() {
 | 
			
		||||
	s.intCtl = 0
 | 
			
		||||
	s.status = 0
 | 
			
		||||
	//s.dmaCtl = spiR8DMARXByte
 | 
			
		||||
	s.dmaCtl = 0
 | 
			
		||||
	s.wait = 2
 | 
			
		||||
	s.clockCtl = spiR8DivRateSelect2 | spiR8Div1024
 | 
			
		||||
	// spiR8DDMA
 | 
			
		||||
	s.ctl = spiR8CSManual | spiR8LSB | spiR8Master | spiR8Enable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// spiMap is the mapping of SPI registers.
 | 
			
		||||
// R8: Page 152-153.
 | 
			
		||||
type spiMap struct {
 | 
			
		||||
	groups [3]spiR8Group
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// spi2Write do a write on SPI2_MOSI via polling.
 | 
			
		||||
func spi2Write(w []byte) error {
 | 
			
		||||
	if drvDMA.clockMemory == nil || drvDMA.spiMemory == nil {
 | 
			
		||||
		return errors.New("subsystem not initialized")
 | 
			
		||||
	}
 | 
			
		||||
	// Make sure the source clock is disabled. Set it at 250kHz.
 | 
			
		||||
	//drvDMA.clockMemory.spi2Clk &^= clockSPIEnable
 | 
			
		||||
	drvDMA.clockMemory.spi2Clk |= clockSPIEnable
 | 
			
		||||
	drvDMA.clockMemory.spi2Clk = clockSPIDiv8a | clockSPIDiv12b
 | 
			
		||||
	ch := &drvDMA.spiMemory.groups[2]
 | 
			
		||||
	ch.setup()
 | 
			
		||||
	fmt.Printf("Setup done\n")
 | 
			
		||||
	for i := 0; i < len(w)/4; i++ {
 | 
			
		||||
		// TODO(maruel): Access it in 8bit mode.
 | 
			
		||||
		ch.tx = uint32(w[0])
 | 
			
		||||
		for ch.fifoStatus.tx() == 0 {
 | 
			
		||||
			log.Printf("Waiting for bit %# v\n", ch)
 | 
			
		||||
			time.Sleep(time.Second)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Done\n")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// spi2Read do a read on SPI2_MISO via polling.
 | 
			
		||||
func spi2Read(r []byte) error {
 | 
			
		||||
	if drvDMA.clockMemory == nil || drvDMA.spiMemory == nil {
 | 
			
		||||
		return errors.New("subsystem not initialized")
 | 
			
		||||
	}
 | 
			
		||||
	// Make sure the source clock is disabled. Set it at 250kHz.
 | 
			
		||||
	//drvDMA.clockMemory.spi2Clk &^= clockSPIEnable
 | 
			
		||||
	drvDMA.clockMemory.spi2Clk |= clockSPIEnable
 | 
			
		||||
	drvDMA.clockMemory.spi2Clk = clockSPIDiv8a | clockSPIDiv12b
 | 
			
		||||
	ch := &drvDMA.spiMemory.groups[2]
 | 
			
		||||
	ch.setup()
 | 
			
		||||
	for i := 0; i < len(r)/4; i++ {
 | 
			
		||||
		ch.tx = 0
 | 
			
		||||
		for ch.status&spiR8TC == 0 {
 | 
			
		||||
		}
 | 
			
		||||
		// TODO(maruel): Access it in 8bit mode.
 | 
			
		||||
		r[i] = uint8(ch.rx)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Done\n")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										128
									
								
								vendor/periph.io/x/periph/host/allwinner/timer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								vendor/periph.io/x/periph/host/allwinner/timer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package allwinner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/host/cpu"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ReadTime returns the time on a monotonic timer.
 | 
			
		||||
//
 | 
			
		||||
// It only works if allwinner-dma successfully loaded. Otherwise it returns 0.
 | 
			
		||||
func ReadTime() time.Duration {
 | 
			
		||||
	if drvDMA.timerMemory == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	v := uint64(drvDMA.timerMemory.counterHigh)<<32 | uint64(drvDMA.timerMemory.counterLow)
 | 
			
		||||
	if v == 0 {
 | 
			
		||||
		// BUG(maruel): Implement using AVS_CNT0_REG on A64.
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	// BUG(maruel): Assumes that counterCtrl & timerPLL6 is not set.
 | 
			
		||||
	const tick = time.Microsecond / 24
 | 
			
		||||
	return time.Duration(v) * tick
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Nanospin spins the CPU without calling into the kernel code if possible.
 | 
			
		||||
func Nanospin(t time.Duration) {
 | 
			
		||||
	start := ReadTime()
 | 
			
		||||
	if start == 0 {
 | 
			
		||||
		// Use the slow generic version.
 | 
			
		||||
		cpu.Nanospin(t)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for ReadTime()-start < t {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// 31:3 reserved
 | 
			
		||||
	timerPLL6            timerCtrl = 2 << 1 // CONT64_CLK_SRC_SEL; OSC24M if not set;
 | 
			
		||||
	timerReadLatchEnable timerCtrl = 1 << 1 // CONT64_RLATCH_EN; 1 to latch the counter to the registers
 | 
			
		||||
	timerClear                     = 1 << 0 // CONT64_CLR_EN; clears the counter
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// R8: Page 96
 | 
			
		||||
type timerCtrl uint32
 | 
			
		||||
 | 
			
		||||
// timerMap is the mapping of important registers across CPUs.
 | 
			
		||||
type timerMap struct {
 | 
			
		||||
	reserved0   [0x80 / 4]uint32 //
 | 
			
		||||
	cntCtl      timerCtrl        // 0x80 AVS_CNT_CTL_REG AVS Control Register
 | 
			
		||||
	cnt0        uint32           // 0x84 AVS_CNT0_REG AVS Counter 0 Register
 | 
			
		||||
	cnt1        uint32           // 0x88 AVS_CNT1_REG AVS Counter 1 Register
 | 
			
		||||
	cndDrv      uint32           // 0x8C AVS_CNT_DIV_REG AVS Divisor Register
 | 
			
		||||
	reserved1   [0x10 / 4]uint32 // On R8 only.
 | 
			
		||||
	counterCtrl timerCtrl        // 0x0A0 COUNTER64_CTRL_REG 64-bit Counter control
 | 
			
		||||
	counterLow  uint32           // 0x0A4 COUNTER64_LOW_REG 64-bit Counter low
 | 
			
		||||
	counterHigh uint32           // 0x0A8 COUNTER64_HI_REG 64-bit Counter high
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A64: Page 161.
 | 
			
		||||
type timerMapA64 struct {
 | 
			
		||||
	reserved0  uint32    // 0x0 TMR_IRQ_EN_REG Timer IRQ Enable Register
 | 
			
		||||
	reserved1  uint32    // 0x4 TMR_IRQ_STA_REG Timer Status Register
 | 
			
		||||
	reserved2  uint32    // 0x10 TMR0_CTRL_REG Timer 0 Control Register
 | 
			
		||||
	reserved3  uint32    // 0x14 TMR0_INTV_VALUE_REG Timer 0 Interval Value Register
 | 
			
		||||
	reserved4  uint32    // 0x18 TMR0_CUR_VALUE_REG Timer 0 Current Value Register
 | 
			
		||||
	reserved5  uint32    // 0x20 TMR1_CTRL_REG Timer 1 Control Register
 | 
			
		||||
	reserved6  uint32    // 0x24 TMR1_INTV_VALUE_REG Timer 1 Interval Value Register
 | 
			
		||||
	reserved7  uint32    // 0x28 TMR1_CUR_VALUE_REG Timer 1 Current Value Register
 | 
			
		||||
	cntCtl     timerCtrl // 0x80 AVS_CNT_CTL_REG AVS Control Register
 | 
			
		||||
	cnt0       uint32    // 0x84 AVS_CNT0_REG AVS Counter 0 Register
 | 
			
		||||
	cnt1       uint32    // 0x88 AVS_CNT1_REG AVS Counter 1 Register
 | 
			
		||||
	cndDrv     uint32    // 0x8C AVS_CNT_DIV_REG AVS Divisor Register
 | 
			
		||||
	reserved8  uint32    // 0xA0 WDOG0_IRQ_EN_REG Watchdog 0 IRQ Enable Register
 | 
			
		||||
	reserved9  uint32    // 0xA4 WDOG0_IRQ_STA_REG Watchdog 0 Status Register
 | 
			
		||||
	reserved10 uint32    // 0xB0 WDOG0_CTRL_REG Watchdog 0 Control Register
 | 
			
		||||
	reserved11 uint32    // 0xB4 WDOG0_CFG_REG Watchdog 0 Configuration Register
 | 
			
		||||
	reserved12 uint32    // 0xB8 WDOG0_MODE_REG Watchdog 0 Mode Register
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// R8: Page 85
 | 
			
		||||
type timerMapR8 struct {
 | 
			
		||||
	reserved0   uint32       // 0x000 ASYNC_TMR_IRQ_EN_REG Timer IRQ Enable
 | 
			
		||||
	reserved1   uint32       // 0x004 ASYNC_TMR_IRQ_STAS_REG Timer Status
 | 
			
		||||
	reserved2   [2]uint32    // 0x008-0x00C
 | 
			
		||||
	reserved3   uint32       // 0x010 ASYNC_TMR0_CTRL_REG Timer 0 Control
 | 
			
		||||
	reserved4   uint32       // 0x014 ASYNC_TMR0_INTV_VALUE_REG Timer 0 Interval Value
 | 
			
		||||
	reserved5   uint32       // 0x018 ASYNC_TMR0_CURNT_VALUE_REG Timer 0 Current Value
 | 
			
		||||
	reserved6   uint32       // 0x01C
 | 
			
		||||
	reserved7   uint32       // 0x020 ASYNC_TMR1_CTRL_REG Timer 1 Control
 | 
			
		||||
	reserved8   uint32       // 0x024 ASYNC_TMR1_INTV_VALUE_REG Timer 1 Interval Value
 | 
			
		||||
	reserved9   uint32       // 0x028 ASYNC_TMR1_CURNT_VALUE_REG Timer 1 Current Value
 | 
			
		||||
	reserved10  uint32       // 0x02C
 | 
			
		||||
	reserved11  uint32       // 0x030 ASYNC_TMR2_CTRL_REG Timer 2 Control
 | 
			
		||||
	reserved12  uint32       // 0x034 ASYNC_TMR2_INTV_VALUE_REG Timer 2 Interval Value
 | 
			
		||||
	reserved13  uint32       // 0x038 ASYNC_TMR2_CURNT_VALUE_REG Timer 2 Current Value
 | 
			
		||||
	reserved14  uint32       // 0x03C
 | 
			
		||||
	reserved15  uint32       // 0x040 ASYNC_TMR3_CTRL_REG Timer 3 Control
 | 
			
		||||
	reserved16  uint32       // 0x044 ASYNC_TMR3_INTV_VALUE_REG Timer 3 Interval Value
 | 
			
		||||
	reserved17  [2]uint32    // 0x048-0x04C
 | 
			
		||||
	reserved18  uint32       // 0x050 ASYNC_TMR4_CTRL_REG Timer 4 Control
 | 
			
		||||
	reserved19  uint32       // 0x054 ASYNC_TMR4_INTV_VALUE_REG Timer 4 Interval Value
 | 
			
		||||
	reserved20  uint32       // 0x058 ASYNC_TMR4_CURNT_VALUE_REG Timer 4 Current Value
 | 
			
		||||
	reserved21  uint32       // 0x05C
 | 
			
		||||
	reserved22  uint32       // 0x060 ASYNC_TMR5_CTRL_REG Timer 5 Control
 | 
			
		||||
	reserved23  uint32       // 0x064 ASYNC_TMR5_INTV_VALUE_REG Timer 5 Interval Value
 | 
			
		||||
	reserved24  uint32       // 0x068 ASYNC_TMR5_CURNT_VALUE_REG Timer 5 Current Value
 | 
			
		||||
	reserved25  [5]uint32    // 0x06C-0x07C
 | 
			
		||||
	cntCtl      timerCtrl    // 0x080 AVS_CNT_CTL_REG AVS Control Register
 | 
			
		||||
	cnt0        uint32       // 0x084 AVS_CNT0_REG AVS Counter 0 Register
 | 
			
		||||
	cnt1        uint32       // 0x088 AVS_CNT1_REG AVS Counter 1 Register
 | 
			
		||||
	cndDiv      uint32       // 0x08C AVS_CNT_DIVISOR_REG AVS Divisor
 | 
			
		||||
	reserved26  uint32       // 0x090 WDOG_CTRL_REG
 | 
			
		||||
	reserved27  uint32       // 0x094 WDOG_MODE_REG Watchdog Mode
 | 
			
		||||
	reserved28  [2]uint32    // 0x098-0x09C
 | 
			
		||||
	counterCtrl timerCtrl    // 0x0A0 COUNTER64_CTRL_REG 64-bit Counter control
 | 
			
		||||
	counterLow  uint32       // 0x0A4 COUNTER64_LOW_REG 64-bit Counter low
 | 
			
		||||
	counterHigh uint32       // 0x0A8 COUNTER64_HI_REG 64-bit Counter high
 | 
			
		||||
	reserved29  [0x94]uint32 // 0x0AC-0x13C
 | 
			
		||||
	reserved30  uint32       // 0x140 CPU_CFG_REG CPU configuration register
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user