|
| 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 |
0 commit comments