Skip to content
Merged
Show file tree
Hide file tree
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
15 changes: 12 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ endif()
# Same shape as IPCHW_VENDORS above, and for the same reason -- set(... CACHE)
# here means a parent project has to FORCE it.
set(IPCHW_PADMUX_FAMILIES v1 v2 v2a v3 v3a v4 v4a v5 3536c 3536d sstar
ingenic novatek)
ingenic novatek xm)
set(IPCHW_PADMUX "all" CACHE STRING
"Pad-mux tables compiled into libipchw: 'all', 'none', or a subset of ${IPCHW_PADMUX_FAMILIES}")

Expand All @@ -98,6 +98,15 @@ foreach(_f IN LISTS _padmux_selected)
string(TOUPPER ${_f} _F)
list(APPEND IPCHW_PADMUX_DEFS IPCHW_PADMUX_${_F})
endforeach()

# Xiongmai's backend is reached only through a chip_generation that only the
# Xiongmai HAL sets, so without that HAL it is code nothing can call. Every
# camera's libipchw is built with the default 'all' tables; this keeps the
# Xiongmai one out of all of them but Xiongmai's own.
if("xm" IN_LIST _padmux_selected AND NOT "xm" IN_LIST _ipchw_selected)
list(REMOVE_ITEM _padmux_selected xm)
list(REMOVE_ITEM IPCHW_PADMUX_DEFS IPCHW_PADMUX_XM)
endif()
message(STATUS "libipchw pad-mux tables: ${_padmux_selected}")

# The vendors whose pad-mux is its own backend rather than a table in
Expand All @@ -107,13 +116,13 @@ message(STATUS "libipchw pad-mux tables: ${_padmux_selected}")
# SigmaStar tables in a build that detects nothing else, which is exactly what
# reginfo_test does.
set(IPCHW_PADMUX_BACKENDS "")
foreach(_f sstar ingenic novatek)
foreach(_f sstar ingenic novatek xm)
if(_f IN_LIST _padmux_selected)
list(APPEND IPCHW_PADMUX_BACKENDS src/hal/${_f}_padmux.c)
endif()
endforeach()
set(IPCHW_PADMUX_BACKENDS_ALL src/hal/sstar_padmux.c src/hal/ingenic_padmux.c
src/hal/novatek_padmux.c)
src/hal/novatek_padmux.c src/hal/xm_padmux.c)

# Which HiSilicon generations libipchw can identify. IPCHW_VENDORS does not
# reach the CODE: chipid.c dispatches to the HiSilicon HAL directly rather
Expand Down
61 changes: 60 additions & 1 deletion docs/padmux.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ puts the pad back.
> pad to GPIO. A pad that a MISC-style table drop hides from `reginfo --pads`
> still answers here, which is the one place to see it.

## Four vendors, four mechanisms
## Five vendors, four mechanisms

This is the thing to understand before touching any of it. The API looks like
one question, and underneath it is four different pieces of silicon.
Expand Down Expand Up @@ -350,6 +350,38 @@ for SIF. Where neither names a pad the name is the option's own -- `SENSOR_12BIT
`MIPI_LVDS_CLK0`, `ETH_RMII` -- which, like SigmaStar's `I2C1_MODE_3`, names a
bus and not a wire.

### Xiongmai -- an enable bit per alternative

XM510 and XM530/XM550 keep a pad's mux in the GPIO block at `0x10020000`, as
one enable bit per alternative with all bits clear meaning GPIO. They differ
only in where the bits live:

| part | register | a pad's field |
|---|---|---|
| XM530/XM550 | `0x10020000 + 4 * pad`, one per pad, pads 0..99 | bits 1-3, MUX1..MUX3 (`GPIO_MUX1_EN`..`GPIO_MUX3_EN` in the vendor's `mach-xm530/platform.h`); the same word holds the drive strength and GPIO state |
| XM510 | `0x10020000 + 4 * port`, one per port of eight pins, ports 0..8 (`GPIOn_MULT_USE_EN`) | pin `b`'s bits `b`, `8 + b` and `16 + b` |

So it is HiSilicon's shape -- one register, one field, every row a plain
read-modify-write that leaves the rest of the word alone -- with a bit per
function where HiSilicon has a selector nibble. Hence `func` for MUX1 on
XM530 is `0x2`, and `gpio mux 6 2` and `gpio mux 6 FUNC1` mean the same.

Xiongmai publishes no table of what each pad's alternatives carry, so rows are
named after the selector -- `FUNC1`, `FUNC2`, `FUNC3` -- except where the
vendor's own code says what it puts there, under its own names:

| part | pads | alternative | names | source |
|---|---|---|---|---|
| XM530/XM550 | 9..14 | MUX2 | `FLASH_CLK`, `FLASH_CSN`, `FLASH_DI`, `FLASH_DO`, `FLASH_WPN`, `FLASH_HOLD` | `platform.h` `GPIO_FLASH_*`, `xmsfc_v2.c` |
| XM530/XM550 | 43..50, 52 | MUX1 | `SDIO0_CLK`, `SDIO0_CMD`, `SDIO0_DATA0`..`3`, `SDIO0_DETECT`, `SDIO0_PWSV`, `SDIO0_LENON` | `sdio0_sd.c` `sdio0_powerup()` |
| XM510 | `5_0`..`5_3` | 1st | `SDIO1` | `sdio1_sd.c`, port 5's word |
| XM510 | `6_0`..`6_3` | 1st | `SDIO2` | `sdio2_wifi.c`, port 6's word |

XM510's SD and Wi-Fi drivers write a port's whole word and never say which pin
is clock, command or data, so those pads carry the bus's name, as SigmaStar's
modes do. `chip_generation` is `CHIP_XM510` or `CHIP_XM530` (XM550 is the
XM530 die), set by `xm_detect_cpu()`.

## Pad numbers and names

`gpio_pad` is the number the kernel uses, and it is the number to speak to
Expand All @@ -361,6 +393,8 @@ every consumer:
| SigmaStar | the vendor pad id, which is the gpiochip index (base 0) | `"PAD_SR_IO03"` |
| Ingenic | `port * 32 + pin` | `"PB25"` |
| Novatek | the Linux GPIO number, `group * 32 + pin` | `"P_GPIO22"` |
| Xiongmai XM530/XM550 | the pad, as the vendor's `GPIO N` | `"GPIO43"` |
| Xiongmai XM510 | `port * 8 + pin` | `"GPIO8_1"` |

Function names are the vendor's own and are **not portable**, not even within
HiSilicon: `PWM_OUT0` on V1, `PWM0` from V2, `PWM0_OUT1` on V5. `"PWM"` also
Expand Down Expand Up @@ -538,6 +572,31 @@ in.
that is their report, without posted output. NA51055 and NA51084 have not
been run at all.

Xiongmai has, on a lab XM510 + JX-H62 and a lab XM550:
- **XM510:** `reginfo --pads` agreed with every port's mux word read
through `devmem`: `0_4`/`0_5` and `1_0`/`1_2` on their 2nd function,
`1_4`/`1_5` on their 3rd, `5_0`..`5_3` as `SDIO1`, `7_0` on its 1st,
everything else GPIO. `gpio mux 3_0 FUNC1` set port 3's bit 0 and
nothing else, and `gpio mux 3_0 GPIO` cleared it.
- **XM550:** all 100 pads agreed with their registers, compared by
script. The SPI flash pads showed as `FLASH_*`; the SD pads 43..48 and
52 as `SDIO0_*`. `gpio mux 51 FUNC3` took pad 51 from `0x80` (8 mA
drive) to `0x88` and `gpio mux 51 GPIO` back to `0x80`.

- **Most Xiongmai alternatives are unnamed.** Only the pads above are named,
because nothing public says what MUX1..3 carry anywhere else. Two groups
are left as selectors on purpose, though the vendor touches them:
- XM510 `0_4`/`0_5`, which `mach-xm510/core.c` moves from their 1st to
their 2nd function at boot, beside the UART clock setup, without saying
what it is;
- XM510 `5_4`..`5_7`, which `sdio1_sd.c` puts on their 1st function for
card detect, power save, write protect and LED -- but its two branches
disagree on which pin is which.

XM510's port 8 word at `+0x20` is inferred from the layout of the other
eight; the vendor only ever names `GPIO78_MULT_USE_EN` (`+0x1C`), and on
the lab board `+0x20` reads zero.

## Adding a family

1. Find the vendor's tables and check which of the three mechanisms it is.
Expand Down
8 changes: 8 additions & 0 deletions src/hal/xm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include <sys/ioctl.h>
#include <unistd.h>

#include "chipid.h"
#include "hal/common.h"
#include "hal/xm.h"
#include "ram.h"
#include "tools.h"

Expand Down Expand Up @@ -145,7 +147,13 @@ bool xm_detect_cpu(char *chip_name, uint32_t base) {
*ptr = toupper(*ptr);
ptr++;
}
/* Only the two layouts hal/xm_padmux.c knows. Any other name keeps
* generation 0, and pad mux answers that it has no table rather than
* reading registers on a layout nobody checked. */
if (!strcmp(chip_name, "XM510"))
chip_generation = CHIP_XM510;
if (!strcmp(chip_name, "XM530")) {
chip_generation = CHIP_XM530; /* XM550 is the same die */
uint32_t reg;
if (mem_reg(0x100B001C, (uint32_t *)&reg, OP_READ)) {
// bank_size, 0x2 for 512M and 0x3 for 1024M
Expand Down
8 changes: 8 additions & 0 deletions src/hal/xm.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#ifndef HAL_XM_H
#define HAL_XM_H

#include <stdbool.h>
#include <stdint.h>

/* chip_generation for the two pad layouts (hal/xm_padmux.c). XM550 is the
* XM530 die with more DRAM and shares its pad controller. */
enum {
CHIP_XM510 = 0x584D0510, /* "XM" 510 */
CHIP_XM530 = 0x584D0530,
};

#define CMD_I2C_WRITE 0x01
#define CMD_I2C_READ 0x03

Expand Down
Loading
Loading