// 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/host/v3/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 } } } } } }