Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
# Ambarella S3L driver bring-up, in the vendor's order: iav and what it needs,
# then the sensor, then the DSP microcode.
#
# The sensor sits in reset until its driver loads, so a probe to find out which
# driver to load finds nothing. A board profile setting sensor= avoids the
# question and is the path to rely on. Otherwise the pin, which differs by board,
# comes from the device tree and is released here, before iav.ko claims it.
#
# Releasing it is not enough on its own: the sensor also needs a clock to answer
# I2C, and of everything here only its driver starts one. So the probe works only
# if U-Boot left the sensor PLL running, as the Dahua U-Boot on the IP4M-1026E
# does. A board whose U-Boot stops it detects nothing and needs sensor=.
#
# iav registers plain character devices and no device class, so mdev never sees
# them and the nodes have to be made here. The major comes from /proc/devices;
# the minors are fixed.
Expand Down Expand Up @@ -37,6 +47,49 @@ make_node() {
[ -c "/dev/$1" ] || mknod -m 600 "/dev/$1" c "${major}" "$2"
}

# The pin in /iav/vinc0/vinrst-gpios, on the SoC's own GPIO. A vendor board may
# put it on an I2C expander, which sysfs numbers differently: leave that alone.
# iav.ko resets with flag bit 0 as the level, so flag 0 is held low.
release_sensor() {
prop=/proc/device-tree/iav/vinc0/vinrst-gpios
soc=/proc/device-tree/apb@e8000000/pinctrl@e8009000/gpio@0
[ -r "$prop" ] || return 1

# shellcheck disable=SC2046
set -- $(od -An -tu1 -v "$prop")
[ $# -eq 12 ] || return 1
phandle="$1 $2 $3 $4"
pin=$(($5 << 24 | $6 << 16 | $7 << 8 | $8))
flags=${12}

for name in phandle linux,phandle; do
[ -r "$soc/$name" ] || continue
# shellcheck disable=SC2046
set -- $(od -An -tu1 -v "$soc/$name")
[ "$*" = "$phandle" ] || return 1
level=high
[ $((flags & 1)) -eq 1 ] && level=low

echo "$pin" >/sys/class/gpio/export || return 1
ret=0
echo "$level" >"/sys/class/gpio/gpio$pin/direction" || ret=1
# Even after a failed direction: iav.ko can't claim a pin sysfs holds.
echo "$pin" >/sys/class/gpio/unexport || ret=1
return $ret
done
return 1
}

find_sensor() {
sensor=$(fw_printenv -n sensor 2>/dev/null | tr 'A-Z' 'a-z')
# A failed probe may have been stored as "unknown". That must not stop
# this one from trying again.
if [ -z "${sensor}" ] || [ "${sensor}" = unknown ]; then
release_sensor || log_vendor "Sensor reset not released, detection may find nothing"
sensor=$(ipcinfo -s 2>/dev/null | tr 'A-Z' 'a-z')
fi
}

# ipcinfo reports a bare name and cannot tell the interface, so a bare name
# means MIPI. imx290 and imx326 also come as LVDS drivers, reached by setting
# sensor=imx290_lvds or sensor=imx326_lvds.
Expand All @@ -62,13 +115,6 @@ sensor_module() {
}

load_sensor() {
sensor=$(fw_printenv -n sensor 2>/dev/null | tr 'A-Z' 'a-z')
# A failed probe may have been stored as "unknown". That must not stop
# this one from trying again.
if [ -z "${sensor}" ] || [ "${sensor}" = unknown ]; then
sensor=$(ipcinfo -s 2>/dev/null | tr 'A-Z' 'a-z')
fi

if [ -z "${sensor}" ]; then
log_vendor "No sensor in the environment and none detected"
return 1
Expand All @@ -93,6 +139,8 @@ load_microcode() {
}

insert_ko() {
find_sensor

if ! load iav; then
log_vendor "Failed to load iav"
return 1
Expand Down
Loading