Files
go-orange/vendor/periph.io/x/host/v3/allwinner/address.go
T
2024-08-09 10:16:42 -04:00

107 lines
2.5 KiB
Go

// Copyright 2024 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"
"os"
"path"
"regexp"
"strconv"
"strings"
)
// getBaseAddress queries the virtual file system to retrieve the base address
// of the GPIO registers for GPIO pins in groups PA to PI.
//
// Defaults to 0x01C20800 as per datasheet if it could not query the file
// system.
func getBaseAddress() (uint64, error) {
driverDir := "/sys/bus/platform/drivers"
if IsH6() {
return getBaseAddressForH6CPU(driverDir)
}
return getDefaultBaseAddress(driverDir), nil
}
func getDefaultBaseAddress(driverDir string) uint64 {
base := uint64(0x01C20800)
link, err := os.Readlink(path.Join(driverDir, "sun50i-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
}
func getBaseAddressForH6CPU(driverDir string) (uint64, error) {
items, err := os.ReadDir(driverDir)
if err != nil {
return 0, err
}
return getBaseAddressFromDirItemsForH6CPU(driverDir, items)
}
func getBaseAddressFromDirItemsForH6CPU(root string, items []os.DirEntry) (uint64, error) {
for _, item := range items {
if ret, ok := getBaseAddressFromDirItemForH6CPU(root, item); ok {
return ret, nil
}
}
return 0, errors.New("file with base address not found")
}
func getBaseAddressFromDirItemForH6CPU(root string, item os.DirEntry) (uint64, bool) {
if !item.IsDir() {
return 0, false
}
if matched, _ := regexp.MatchString(`^sun50i-h6\d*-pinctrl$`, item.Name()); !matched {
return 0, false
}
return extractBaseAddressFromDriverDirForH6CPU(path.Join(root, item.Name()))
}
func extractBaseAddressFromDriverDirForH6CPU(dir string) (uint64, bool) {
if fileInfo, err := os.Stat(dir); err != nil || !fileInfo.IsDir() {
return 0, false
}
items, err := os.ReadDir(dir)
if err != nil {
return 0, false
}
for _, item := range items {
if address, ok := extractBaseAddress(item); ok {
return address, ok
}
}
return 0, false
}
func extractBaseAddress(item os.DirEntry) (uint64, bool) {
if item.IsDir() {
return 0, false
}
if !strings.HasSuffix(item.Name(), ".pinctrl") {
return 0, false
}
prefix := item.Name()[:len(item.Name())-len(".pinctrl")]
if address, err := strconv.ParseUint(prefix, 16, 64); err != nil {
return 0, false
} else {
return address, true
}
}