Skip to content

Commit 9f0d9f7

Browse files
biotinkermaruel
andauthored
Allwinner: Implement nanopi neo air (#30)
* Implement nanopi neo air * Support for PL pins Co-authored-by: Marc-Antoine Ruel <[email protected]>
1 parent 2dfc6ee commit 9f0d9f7

File tree

8 files changed

+245
-10
lines changed

8 files changed

+245
-10
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Google Inc.
1313
Josh Gardiner
1414
Matt Aimonetti <[email protected]>
1515
Max Ekman <[email protected]>
16+
Peter LoVerso <[email protected]>
1617
Rifiniti, Inc
1718
Stephan Sperber
1819
Thorsten von Eicken <[email protected]>

allwinner/h3.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package allwinner
99

1010
import (
11+
"strconv"
1112
"strings"
1213

1314
"periph.io/x/conn/v3/pin"
@@ -138,16 +139,28 @@ var mappingH3 = map[string][5]pin.Func{
138139
// code detects a H2+ or H3 processor.
139140
func mapH3Pins() error {
140141
for name, altFuncs := range mappingH3 {
141-
pin := cpupins[name]
142-
pin.altFunc = altFuncs
143-
pin.available = true
144-
if strings.Contains(string(altFuncs[4]), "_EINT") ||
145-
strings.Contains(string(altFuncs[3]), "_EINT") {
146-
pin.supportEdge = true
147-
}
142+
if strings.HasPrefix(name, "PL") {
143+
pinNumStr := name[2:]
144+
pinNum, err := strconv.Atoi(pinNumStr)
145+
if err != nil {
146+
return err
147+
}
148+
pin := &cpuPinsPL[pinNum]
149+
pin.available = true
148150

149-
// Initializes the sysfs corresponding pin right away.
150-
pin.sysfsPin = sysfs.Pins[pin.Number()]
151+
// Initializes the sysfs corresponding pin right away.
152+
pin.sysfsPin = sysfs.Pins[pin.Number()]
153+
} else {
154+
pin := cpupins[name]
155+
pin.altFunc = altFuncs
156+
pin.available = true
157+
if strings.Contains(string(altFuncs[4]), "_EINT") ||
158+
strings.Contains(string(altFuncs[3]), "_EINT") {
159+
pin.supportEdge = true
160+
}
161+
// Initializes the sysfs corresponding pin right away.
162+
pin.sysfsPin = sysfs.Pins[pin.Number()]
163+
}
151164
}
152165
return nil
153166
}

cpu/cpu.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func getMaxSpeedLinux() int64 {
5959
if maxSpeed == -1 {
6060
maxSpeed = 0
6161
if f, err := openFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", os.O_RDONLY); err == nil {
62-
defer f.Close()
62+
defer f.Close() //#nosec G307 -- File is opened readonly so errors on file close cannot cause write errors
6363
if b, err := io.ReadAll(f); err == nil {
6464
s := strings.TrimSpace(string(b))
6565
if i, err := strconv.ParseInt(s, 10, 64); err == nil {

nanopi/doc.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2022 The Periph Authors. All rights reserved.
2+
// Use of this source code is governed under the Apache License, Version 2.0
3+
// that can be found in the LICENSE file.
4+
5+
// Package nanopi contains nanoPi hardware logic.
6+
//
7+
// Requires armbian jessie server.
8+
//
9+
// # Physical
10+
package nanopi

nanopi/nanopi.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Copyright 2022 The Periph Authors. All rights reserved.
2+
// Use of this source code is governed under the Apache License, Version 2.0
3+
// that can be found in the LICENSE file.
4+
5+
// nanoPi pin out.
6+
7+
package nanopi
8+
9+
import (
10+
"errors"
11+
"fmt"
12+
"strings"
13+
14+
"periph.io/x/conn/v3/driver/driverreg"
15+
"periph.io/x/conn/v3/gpio"
16+
"periph.io/x/conn/v3/pin"
17+
"periph.io/x/conn/v3/pin/pinreg"
18+
"periph.io/x/host/v3/allwinner"
19+
"periph.io/x/host/v3/distro"
20+
)
21+
22+
// Present return true if a NanoPi board is detected.
23+
func Present() bool {
24+
if isArm {
25+
// This works for the NanoPi Neo Air, not sure if other NAnoPi boards
26+
// match the same DTModel prefix.
27+
return strings.HasPrefix(distro.DTModel(), "FriendlyARM")
28+
}
29+
30+
return false
31+
}
32+
33+
const (
34+
boardNeoAir string = "NanoPi NEO Air" // + LTS (H2/H3 have identical pinouts)
35+
)
36+
37+
var (
38+
PA1_1 pin.Pin = pin.DC_IN // VCC 3v3 Ext
39+
PA1_2 pin.Pin = pin.V5
40+
PA1_3 gpio.PinIO = allwinner.PA12
41+
PA1_4 pin.Pin = pin.V5
42+
PA1_5 gpio.PinIO = allwinner.PA11
43+
PA1_6 pin.Pin = pin.GROUND
44+
PA1_7 gpio.PinIO = allwinner.PG11
45+
PA1_8 gpio.PinIO = allwinner.PG6
46+
PA1_9 pin.Pin = pin.GROUND
47+
PA1_10 gpio.PinIO = allwinner.PG7
48+
PA1_11 gpio.PinIO = allwinner.PA0
49+
PA1_12 gpio.PinIO = allwinner.PA6
50+
PA1_13 gpio.PinIO = allwinner.PA2
51+
PA1_14 pin.Pin = pin.GROUND
52+
PA1_15 gpio.PinIO = allwinner.PA3
53+
PA1_16 gpio.PinIO = allwinner.PA8
54+
PA1_17 pin.Pin = pin.DC_IN // VCC 3v3 Ext
55+
PA1_18 gpio.PinIO = allwinner.PG9
56+
PA1_19 gpio.PinIO = allwinner.PC0
57+
PA1_20 pin.Pin = pin.GROUND
58+
PA1_21 gpio.PinIO = allwinner.PC1
59+
PA1_22 gpio.PinIO = allwinner.PA1
60+
PA1_23 gpio.PinIO = allwinner.PC2
61+
PA1_24 gpio.PinIO = allwinner.PC3
62+
63+
FUN1_1 pin.Pin = pin.V5
64+
FUN1_2 pin.Pin = gpio.INVALID // USB-DP2
65+
FUN1_3 pin.Pin = gpio.INVALID // USB-DM2
66+
FUN1_4 pin.Pin = gpio.INVALID // USB-DP3
67+
FUN1_5 pin.Pin = gpio.INVALID // USB-DM3
68+
FUN1_6 pin.Pin = allwinner.PL11 // IR-RX
69+
FUN1_7 pin.Pin = allwinner.PA17 // SPDIF-OUT
70+
FUN1_8 pin.Pin = allwinner.PA18 // PCM0_SYNC/I2S0_LRC
71+
FUN1_9 pin.Pin = allwinner.PA19 // PCM0_CLK/I2S0_BCK
72+
FUN1_10 pin.Pin = allwinner.PA20 // PCM0_DOUT/I2S0_SDOUT
73+
FUN1_11 pin.Pin = allwinner.PA21 // PCM0_DIN/I2S0_SDIN
74+
FUN1_12 pin.Pin = pin.GROUND //
75+
76+
FUN2_1 pin.Pin = allwinner.HP_LEFT // LINEOUTL
77+
FUN2_2 pin.Pin = allwinner.HP_RIGHT // LINEOUT
78+
FUN2_3 pin.Pin = allwinner.MIC_GND // MIC GND
79+
FUN2_4 pin.Pin = allwinner.MIC_IN // MIC IN
80+
81+
FUN3_1 pin.Pin = pin.GROUND
82+
FUN3_2 pin.Pin = pin.V5
83+
FUN3_3 pin.Pin = allwinner.PA4 // UART TX
84+
FUN3_4 pin.Pin = allwinner.PA5 // UART RX
85+
86+
)
87+
88+
// registerHeaders registers the headers for various NanoPi boards. Currently
89+
// only NanoPi NEO Air is supported.
90+
func registerHeaders(model string) error {
91+
if strings.Contains(model, boardNeoAir) {
92+
// 24pin expansion port
93+
if err := pinreg.Register("PA", [][]pin.Pin{
94+
{PA1_1, PA1_2},
95+
{PA1_3, PA1_4},
96+
{PA1_5, PA1_6},
97+
{PA1_7, PA1_8},
98+
{PA1_9, PA1_10},
99+
{PA1_11, PA1_12},
100+
{PA1_13, PA1_14},
101+
{PA1_15, PA1_16},
102+
{PA1_17, PA1_18},
103+
{PA1_19, PA1_20},
104+
{PA1_21, PA1_22},
105+
{PA1_23, PA1_24},
106+
}); err != nil {
107+
return err
108+
}
109+
110+
// 12pin function interface
111+
if err := pinreg.Register("FUN", [][]pin.Pin{
112+
{FUN1_1},
113+
{FUN1_2},
114+
{FUN1_3},
115+
{FUN1_4},
116+
{FUN1_5},
117+
{FUN1_6},
118+
{FUN1_7},
119+
{FUN1_8},
120+
{FUN1_9},
121+
{FUN1_10},
122+
{FUN1_11},
123+
{FUN1_12},
124+
{FUN2_1},
125+
{FUN2_2},
126+
{FUN2_3},
127+
{FUN2_4},
128+
{FUN3_1},
129+
{FUN3_2},
130+
{FUN3_3},
131+
{FUN3_4},
132+
}); err != nil {
133+
return err
134+
}
135+
}
136+
137+
return nil
138+
}
139+
140+
// driver implements periph.Driver.
141+
type driver struct {
142+
}
143+
144+
// String is the text representation of the board.
145+
func (d *driver) String() string {
146+
return "nanopi"
147+
}
148+
149+
// Prerequisites load drivers before the actual driver is loaded. For
150+
// these boards, we do not need any prerequisites.
151+
func (d *driver) Prerequisites() []string {
152+
return nil
153+
}
154+
155+
// After this driver is loaded, we need to load generic Allwinner drivers
156+
// for the GPIO pins which are identical on all Allwinner CPUs.
157+
func (d *driver) After() []string {
158+
return []string{"allwinner-gpio", "allwinner-gpio-pl"}
159+
}
160+
161+
// Init initializes the driver by checking its presence and if found, the
162+
// driver will be registered.
163+
func (d *driver) Init() (bool, error) {
164+
if !Present() {
165+
return false, errors.New("NanoPi board not detected")
166+
}
167+
168+
model := distro.DTModel()
169+
if model == "<unknown>" {
170+
return true, fmt.Errorf("nanopi: failed to obtain model")
171+
}
172+
173+
err := registerHeaders(model)
174+
return true, err
175+
}
176+
177+
// init register the driver.
178+
func init() {
179+
if isArm {
180+
driverreg.MustRegister(&drv)
181+
}
182+
}
183+
184+
var drv driver

nanopi/nanopi_arm.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2022 The Periph Authors. All rights reserved.
2+
// Use of this source code is governed under the Apache License, Version 2.0
3+
// that can be found in the LICENSE file.
4+
5+
package nanopi
6+
7+
const isArm = true

nanopi/nanopi_arm64.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2022 The Periph Authors. All rights reserved.
2+
// Use of this source code is governed under the Apache License, Version 2.0
3+
// that can be found in the LICENSE file.
4+
5+
//go:build arm64
6+
// +build arm64
7+
8+
package nanopi
9+
10+
const isArm = true

nanopi/nanopi_other.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2022 The Periph Authors. All rights reserved.
2+
// Use of this source code is governed under the Apache License, Version 2.0
3+
// that can be found in the LICENSE file.
4+
5+
//go:build !arm && !arm64
6+
// +build !arm,!arm64
7+
8+
package nanopi
9+
10+
const isArm = false

0 commit comments

Comments
 (0)