#################################################################################
# Helper script: /load_kernel_modules.scr/platform/aarch64/broadcom
# Purpose......: Set the Kernel modules for Hardware Models that use the BCMxxxx
#                SoC within the Slackware initial RAM disk ('OS initrd')
#                and the Slackware Installer.
#                Currently supported Hardware Models:
#                * Raspberry Pi 3 (BCM2837)
#                * Raspberry Pi 4 (BCM2711)
#                * Raspberry Pi 5 (BCM2712)
#                This script is sourced from '/load_kernel_modules'
# Author.......: Stuart Winter <mozes@slackware.com>
# Date.........: 14-Jan-2025
# Maintainer...: Stuart Winter, Brent Earl.
#
# Please use this as an reference and example of how to add support for
# a new Hardware Model to Slackware ARM/AArch64.
#
# Important Note:
# * You must _append_ to the module lists (as this script does)
#   otherwise the base set of modules will not be loaded and would result in
#   a Kernel panic.
# * The initrd uses the 'bash' shell, rather than 'busybox'
#   (as in upstream/x86 Slackware). This allows you (for example)
#   to use 'fallthrough' (case statements terminated with ';&'
#   rather than ';;') within case statements and regular expression
#   matches within 'if' statements.
#   This permits the 'c'-style switch statements where you can
#   'inherit' the previous matches as you move down the cases.
#   This enables you to match on varients of boards, and inherit
#   a 'baseline' of platform modules for that board.
#
# The 'PLATWALK' match is to enable build scripts to process these
# scripts outside of the initrd environment and determine which
# modules will be loaded by a particular Hardware Model.  This must remain
# in place for all scripts.
#################################################################################
# Change log
#################################################################################
# 14-Jan-2025: Added Raspberry Pi 5.
# 30-Mar-2021: Created.
#################################################################################

# $HWM is set by the caller ('/load_kernel_modules') of this helper script
# and the value is taken from /proc/device-tree/model.
# If your Hardware Model does not have a /proc/device-tree/model interface
# (such as QEMU), see the 'virt-qemu' loader script for the other Hardware
# Model detection method.

# Typically these short names are only used to blacklist particular modules
# from loading within the OS InitRD or Installer.  Within the OS the regular
# location of /lib/modprobe.d/ is used and has no connection to the content of
# the OS InitRD/Installer.

# Set the 'short name' that is used by /load_kernel_modules to install
# the appropriate configuration for modprobe for this Hardware Model.
# These files are stored within the source tree:
# source/k/SlkOS-initrd-overlay/usr/share/hwm-configure/platform/aarch64/modprobe.d/
# Modprobe config file name format: ${SOC_NAME}_${HWM_SHORTNAME}.conf
# Ensure the closest or strictest match is listed first:
# For the RPi we group them into a generic bucket since a single
# profile can handle all of them. In the future if we require divergence,
# we'll split them out as we previously did.

# Note: the reason the HWM_SHORTNAME is set to 'rpi' for all, is because
# at present, there's no requirement for divergence.
# If this changes, we'll adjust the code below and create a new modprobe.conf
case $hwm in
   "Raspberry Pi 3"*)
      #SOC_NAME=bcm2837
      #HWM_SHORTNAME=rpi3 ;;
      SOC_NAME=broadcom
      HWM_SHORTNAME=rpi ;;
#      HWM_SHORTNAME=rpi3 ;;

   "Raspberry Pi 400"*)
      #SOC_NAME=bcm2711
      #HWM_SHORTNAME=rpi400 ;;
      SOC_NAME=broadcom
      HWM_SHORTNAME=rpi ;;
#      HWM_SHORTNAME=rpi400 ;;

   "Raspberry Pi 4"*)
      #SOC_NAME=bcm2711
      #HWM_SHORTNAME=rpi4 ;;
      SOC_NAME=broadcom
      HWM_SHORTNAME=rpi ;;
#      HWM_SHORTNAME=rpi4 ;;

   "Raspberry Pi 5"*)
      #SOC_NAME=bcm2712
      #HWM_SHORTNAME=rpi5 ;;
      SOC_NAME=broadcom
      HWM_SHORTNAME=rpi ;;
#      HWM_SHORTNAME=rpi5 ;;

esac

# Set Kernel modules based on the Raspberry Pi Hardware Model:
case $HWM in
   "Raspberry Pi 3"*|PLATWALK)
      platform_detected=1
      # If one of the modules within the base list is causing problems on
      # your platform, here are the options laid out as examples:
      # USB="${USB/ehci_orion/differentmodule}" # Substitute module 'ehci_orion' with 'differentmodule'
      # USB="${USB/ehci_orion/}" # Remove the 'ehci_orion' module from the list
      MOD_GPIO+="   "
      # Drivers for PCI and other core sub systems:
      MOD_PHY+="    bcm_phy_lib phy_generic macb_pci"
      # Video drivers:
      MOD_VIDEO+="  simpledrm"
      # MFD (Multi Functional Devices) drivers:
      MOD_MFD+="    "
      MOD_CARDS+="  sdhci-iproc bcm2835"
      MOD_USB+="    dwc2"
      MOD_NET+="    "
      MOD_CMP+="    "
      MOD_CRYPTO+=" "

      # Real Time Clock:
      MOD_RTC+="    rtc-ds1307 rtc-pcf8523" 
      # Modules for the peripherals on the Hardware Model's main board
      # (outside of the SoC itself)
      MOD_HWM+="    "
      # Modules for the IP blocks/peripherals embedded within the SoC:
      MOD_SOC+="    "
      ;;
      # Note: The RPi3 will probably benefit from the same post-module-loading
      # function as included within the RPi4's helper script, which initialises
      # an RTC on the GPIO array.
      # The RPi3 support is presently only supported to the basic level though,
      # and this can enhancement can be added later when there are people
      # with hardware and interest to test it.
esac

case $HWM in
   "Raspberry Pi 4"*|"Raspberry Pi 5"*|PLATWALK)
      platform_detected=y
      # If one of the modules within the base list is causing problems on
      # your platform, here are the options laid out as examples:
      # USB="${USB/ehci_orion/differentmodule}" # Substitute module 'ehci_orion' with 'differentmodule'
      # USB="${USB/ehci_orion/}" # Remove the 'ehci_orion' module from the list
      MOD_GPIO+="   spi_bcm2835"
      # Drivers for PCI and other core sub systems:
      MOD_PHY+="    bcm_phy_lib phy_generic"
      # MFD (Multi Functional Devices) drivers:
      MOD_MFD+="    "
      # Video drivers:
      MOD_VIDEO+="  simpledrm v3d"
      MOD_CARDS+="  sdhci-iproc"
      MOD_USB+="    dwc2 dwc3"
      MOD_NET+="    genet macb" # eth0: genet=rpi4,macb=rpi5
      MOD_CMP+="    "
      MOD_CRYPTO+=" "

      # Real Time Clock:
      MOD_RTC+="    rtc-ds1307 rtc-pcf8523"
      # Modules for the peripherals on the Hardware Model's main board
      # (outside of the SoC itself)
      # Note: the distinction between the SoC and HWM is blurred presently
      #       This needs organising according to the hardware - TODO!
      MOD_HWM+="    pcie_brcmstb mdio_bcm_unimac iproc_rng200 pwrseq_simple"
      # Modules for the IP blocks/peripherals embedded within the SoC:
      MOD_SOC+="    broadcom clk_raspberrypi pwm-bcm2835 raspberrypi-hwmon i2c-bcm2835 i2c_brcmstb"

      # /load_kernel_modules provides the ability to run a defined function
      # just prior to loading the Linux Kernel module lists that have been
      # defined in the base set + directly above these lines.
      # There's no current use case for this - it's here to expose it as
      # an option should it be useful at some future time.
      #function hwm_hook_pre-modload() {
      #}
      #
      # And the same functionality once the Kernel modules have been loaded.
      # This allows us to set up the RTC, which we cannot do at the time this
      # script is loaded initially, as the RTC device is only addressable upon
      # having loaded the driver into the Kernel.
      # To achieve this effect locally, users should look at
      # /boot/local/README.txt
      # and create /boot/local/load_kernel_modules.post from the sample file.
      # This is a shell script in which you can 'modprobe' additional modules,
      # and run shell code as we do below to write a value into the RTC's
      # Kernel interface to initialise it.
      #
      # This function is here because this particular RTC is officially
      # supported by Slackware AArch64, as it's connected to this author's
      # RPi4.
      #
      # Note that we use the lower case $hwm because when the Installer is booted
      # in generic mode, the HWM = "platwalk" which means we will run inappropriate
      # code on the wrong platforms.
      if [[ "${hwm}" == "Raspberry Pi 4"* ]]; then
         function hwm_hook_post-modload() {
            #{ lspci 2>/dev/null | grep -q 'SATA cont.*ATA' ;} && modprobe xyz

            # Initialise a DS1307 RTC without Device Tree Overlay.
            #
            # When booting Slackware directly from the RPi's native Boot Loader,
            # we add a Kernel command line operator 'slkrpinbl' which enables
            # these types of conditional actions:
            grep -iq "slkrpinbl" /proc/cmdline 2> /dev/null || {
               # Silently detect peripherals on bus 1.
               # Something like this, self-contained would be ideal:
               #sensors-detect --auto > /dev/null 2>&1
               i2cdetect -y 1 > /dev/null 2>&1
               # Unless you change this setting, it'll appear as position 68.
               [ -f /sys/class/i2c-adapter/i2c-1/new_device ] && \
                   echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
            }
         }
      fi

      # Define a function to run from the OS InitRD's '/init' immediately prior
      # to switching into the Slackware OS proper.
      # This is after any software RAID arrays et al have been initialised.
      # There's no current use case for this, but it may be useful in the future.
      #
      # At this stage, the following paths for Slackware OS are mounted:
      # /proc, /sys, /run, /dev
      # The root file system ('/') is mounted under /mnt
      #
      #function hwm_hook_pre_switch_root() {
      #  echo "Just about to switch into the Slackware OS proper, leaving the OS InitRD"
      #  sleep 4
      #}

     # End of stanza - the ';;' below must be the last line:
     ;;
esac

# The Raspberry Pi 5 has its own additional modules:
case $HWM in
   "Raspberry Pi 5"*|PLATWALK)
      # Drivers for PCI and other core sub systems:
      MOD_PHY+="    rp1-pci clk-rp1 pinctrl-rp1"
    ;;
esac

# Generic settings for all Raspberry Pi's:
case $HWM in
   "Raspberry Pi"*|PLATWALK)
      # Load the parent platform drivers for the SoC:
      kmod_load_subsyst_soc=1
    ;;
esac

# The '/load_kernel_modules' script will load the modules
# set above.
