# IOMUX Usage Instructions

## Overview
>
>This section mainly describes iomux configuration under Linux. For iomux configuration under uboot, please refer to [iomux configuration under uboot](../../advanced_adaptation_guide/new_board_adaptation_doc.md#appendix-a-iomux-pin-configuration)

The K230 IOMUX driver provides pin function control for the Canaan Kendryte K230 SoC. This driver implements the Linux pinctrl subsystem and is used to manage:

- Pin function multiplexing (each pin has 8 function selections)
- Pin configuration (pull-up/pull-down, drive strength, slew rate, etc.)

This document mainly describes the definition of K230 iomux-related registers, device tree configuration, and the usage of the userspace iomux tool.
The main files related to this document are as follows:

| File | Description |
| --- | --- |
| `pinctrl-k230-iomux.c` | Main driver source code implementing pinctrl/pinmux/pinconf operations |
| `dt-bindings/pinctrl/canaan,k230-iomux.h` | Header file containing pin names and function selectors |
| `k230_iomux.py` | Python tool for runtime pin configuration |
| `Documentation/devicetree/bindings/pinctrl/canaan,k230-iomux.yaml` | Device Tree binding schema |

## Register and Function Description

### Registers

K230 has 2 iomux controller modules:

- Main IOMUX: 0x91105000 (64 pins)
- PMU IOMUX: 0x91000080 (8 pins)

Each pin has a 32-bit register at the base address offset `pin * 4`.

The register bit layout is as follows (refer to TRM Section 12.9.2)

| Bit | Field | Type | Description |
| --- | --- | --- | --- |
| 31 | DI | RO | Input data |
| 30:14 | - | RO | Reserved |
| 13:11 | IO_SEL | RW | Function selection (000=func1, and so on) |
| 10 | SL | RW | Slew rate enable |
| 9 | MSC | RW | Voltage control (dual-voltage pad) |
| 8 | IE | RW | Input enable (1=enabled) |
| 7 | OE | RW | Output enable (1=enabled) |
| 6 | PU | RW | Pull-up (1=enabled) |
| 5 | PD | RW | Pull-down (1=enabled) |
| 4:1 | DS | RW | Drive strength selection (0-15) |
| 0 | ST | RW | Schmitt trigger (1=enabled) |

### Function Description

Each pin supports up to 8 functions (IO_SEL[2:0]). The configurable functions of each pin are as follows:

Controller 0 (io0-io63)

| Pin | alt0 | alt1 | alt2 | alt3 | alt4 |
| --- | --- | --- | --- | --- | --- |
| io0 | GPIO0 | BOOT0 | - | TEST_PIN0 | - |
| io1 | GPIO1 | BOOT1 | - | TEST_PIN1 | - |
| io2 | GPIO2 | JTAG_TCK | PULSE_CNTR0 | TEST_PIN2 | - |
| io3 | GPIO3 | JTAG_TDI | PULSE_CNTR1 | UART1_TXD | TEST_PIN0 |
| io4 | GPIO4 | JTAG_TDO | PULSE_CNTR2 | UART1_RXD | TEST_PIN1 |
| io5 | GPIO5 | JTAG_TMS | PULSE_CNTR3 | UART2_TXD | TEST_PIN2 |
| io6 | GPIO6 | JTAG_RST | PULSE_CNTR4 | UART2_RXD | TEST_PIN3 |
| io7 | GPIO7 | PWM2 | I2C4_SCL | TEST_PIN3 | DI0 |
| io8 | GPIO8 | PWM3 | I2C4_SDA | TEST_PIN4 | DI1 |
| io9 | GPIO9 | PWM4 | UART1_TXD | I2C1_SCL | DI2 |
| io10 | GPIO10 | 3D_CTRL_IN | UART1_RXD | I2C1_SDA | DI3 |
| io11 | GPIO11 | 3D_CTRL_OUT1 | UART2_TXD | I2C2_SCL | DO0 |
| io12 | GPIO12 | 3D_CTRL_OUT2 | UART2_RXD | I2C2_SDA | DO1 |
| io13 | GPIO13 | M_CLK1 | - | - | DO2 |
| io14 | GPIO14 | OSPI_CS | TEST_PIN5 | QSPI0_CS0 | DO3 |
| io15 | GPIO15 | OSPI_CLK | TEST_PIN6 | QSPI0_CLK | CO3 |
| io16 | GPIO16 | OSPI_D0 | QSPI1_CS4 | QSPI0_D0 | CO2 |
| io17 | GPIO17 | OSPI_D1 | QSPI1_CS3 | QSPI0_D1 | CO1 |
| io18 | GPIO18 | OSPI_D2 | QSPI1_CS2 | QSPI0_D2 | CO0 |
| io19 | GPIO19 | OSPI_D3 | QSPI1_CS1 | QSPI0_D3 | TEST_PIN4 |
| io20 | GPIO20 | OSPI_D4 | QSPI1_CS0 | PULSE_CNTR0 | TEST_PIN5 |
| io21 | GPIO21 | OSPI_D5 | QSPI1_CLK | PULSE_CNTR1 | TEST_PIN6 |
| io22 | GPIO22 | OSPI_D6 | QSPI1_D0 | PULSE_CNTR2 | TEST_PIN7 |
| io23 | GPIO23 | OSPI_D7 | QSPI1_D1 | PULSE_CNTR3 | TEST_PIN8 |
| io24 | GPIO24 | OSPI_DQS | QSPI1_D2 | PULSE_CNTR4 | TEST_PIN9 |
| io25 | GPIO25 | PWM5 | QSPI1_D3 | PULSE_CNTR5 | TEST_PIN10 |
| io26 | GPIO26 | MMC1_CLK | TEST_PIN7 | PDM_CLK | - |
| io27 | GPIO27 | MMC1_CMD | PULSE_CNTR5 | PDM_IN0 | CI0 |
| io28 | GPIO28 | MMC1_D0 | UART3_TXD | PDM_IN1 | CI1 |
| io29 | GPIO29 | MMC1_D1 | UART3_RXD | 3D_CTRL_IN | CI2 |
| io30 | GPIO30 | MMC1_D2 | UART3_RTS | 3D_CTRL_OUT1 | CI3 |
| io31 | GPIO31 | MMC1_D3 | UART3_CTS | 3D_CTRL_OUT2 | TEST_PIN11 |
| io32 | GPIO32 | I2C0_SCL | IIS_CLK | UART3_TXD | TEST_PIN12 |
| io33 | GPIO33 | I2C0_SDA | IIS_WS | UART3_RXD | TEST_PIN13 |
| io34 | GPIO34 | I2C1_SCL | IIS_D_IN0_PDM_IN3 | UART3_RTS | TEST_PIN14 |
| io35 | GPIO35 | I2C1_SDA | IIS_D_OUT0_PDM_IN1 | UART3_CTS | TEST_PIN15 |
| io36 | GPIO36 | I2C3_SCL | IIS_D_IN1_PDM_IN2 | UART4_TXD | TEST_PIN16 |
| io37 | GPIO37 | I2C3_SDA | IIS_D_OUT1_PDM_IN0 | UART4_RXD | TEST_PIN17 |
| io38 | GPIO38 | UART0_TXD | TEST_PIN8 | QSPI1_CS0 | HSYNC0 |
| io39 | GPIO39 | UART0_RXD | TEST_PIN9 | QSPI1_CLK | VSYNC0 |
| io40 | GPIO40 | UART1_TXD | I2C1_SCL | QSPI1_D0 | TEST_PIN18 |
| io41 | GPIO41 | UART1_RXD | I2C1_SDA | QSPI1_D1 | TEST_PIN19 |
| io42 | GPIO42 | UART1_RTS | PWM0 | QSPI1_D2 | TEST_PIN20 |
| io43 | GPIO43 | UART1_CTS | PWM1 | QSPI1_D3 | TEST_PIN21 |
| io44 | GPIO44 | UART2_TXD | I2C3_SCL | TEST_PIN10 | SPI2AXI_CLK |
| io45 | GPIO45 | UART2_RXD | I2C3_SDA | TEST_PIN11 | SPI2AXI_CS |
| io46 | GPIO46 | UART2_RTS | PWM2 | I2C4_SCL | TEST_PIN22 |
| io47 | GPIO47 | UART2_CTS | PWM3 | I2C4_SDA | TEST_PIN23 |
| io48 | GPIO48 | UART4_TXD | TEST_PIN12 | I2C0_SCL | SPI2AXI_DIN |
| io49 | GPIO49 | UART4_RXD | TEST_PIN13 | I2C0_SDA | SPI2AXI_DOUT |
| io50 | GPIO50 | UART3_TXD | I2C2_SCL | QSPI0_CS4 | TEST_PIN24 |
| io51 | GPIO51 | UART3_RXD | I2C2_SDA | QSPI0_CS3 | TEST_PIN25 |
| io52 | GPIO52 | UART3_RTS | PWM4 | I2C3_SCL | TEST_PIN26 |
| io53 | GPIO53 | UART3_CTS | PWM5 | I2C3_SDA | - |
| io54 | GPIO54 | QSPI0_CS0 | MMC1_CMD | PWM0 | TEST_PIN27 |
| io55 | GPIO55 | QSPI0_CLK | MMC1_CLK | PWM1 | TEST_PIN28 |
| io56 | GPIO56 | QSPI0_D0 | MMC1_D0 | PWM2 | TEST_PIN29 |
| io57 | GPIO57 | QSPI0_D1 | MMC1_D1 | PWM3 | TEST_PIN30 |
| io58 | GPIO58 | QSPI0_D2 | MMC1_D2 | PWM4 | TEST_PIN31 |
| io59 | GPIO59 | QSPI0_D3 | MMC1_D3 | PWM5 | - |
| io60 | GPIO60 | PWM0 | I2C0_SCL | QSPI0_CS2 | HSYNC1 |
| io61 | GPIO61 | PWM1 | I2C0_SDA | QSPI0_CS1 | VSYNC1 |
| io62 | GPIO62 | M_CLK2 | UART3_DE | TEST_PIN14 | - |
| io63 | GPIO63 | M_CLK3 | UART3_RE | TEST_PIN15 | - |

Controller 1 (io0-io7, PMUIOMUX)

| Pin | alt1 | alt2 |
| --- | --- | --- |
| io0 | GPIO64 | INT0 |
| io1 | GPIO65 | INT1 |
| io2 | GPIO66 | INT2 |
| io3 | GPIO67 | INT3 |
| io4 | GPIO68 | INT4 |
| io5 | GPIO69 | INT5 |
| io6 | GPIO70 | OUT1 |
| io7 | GPIO71 | OUT2 |

## Device Tree Configuration

### Example

#### UART0 Configuration

```dts
&iomux {
    uart0_pins: uart0-pins {
        pinmux {
            pins = "io38", "io39";
            function = "alt1";
            bias-disable;
            drive-strength = <8>;
            slew-rate = <1>;
        };
    };
};

&uart0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&uart0_pins>;
};
```

#### I2C0 Configuration

```dts
&iomux {
    i2c0_pins: i2c0-pins {
        pinmux {
            pins = "io32", "io33";
            function = "alt1";
            bias-pull-up;
            drive-strength = <8>;
        };
    };
};

&i2c0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2c0_pins>;
    clock-frequency = <100000>;
};
```

#### PWM Configuration

```dts
&iomux {
    pwm2_pins: pwm2-pins {
        pinmux {
            pins = "io46";
            function = "alt2";  // PWM2 function
            drive-strength = <8>;
        };
    };
};

&pwm0_2 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&pwm2_pins>;
};
```

### Description

```dts
/*arch/riscv/boot/dts/canaan/k230.dtsi*/
iomux: iomux@91105000 {
    compatible = "canaan,k230-iomux";
    reg = <0x0 0x91105000 0x0 0x100>;
    #pinctrl-cells = <1>;
    clocks = <&iomux_pclk_gate>;
    clock-names = "apb";
    status = "okay";
};
pmuiomux: pmuiomux@91000080 {
    compatible = "canaan,k230-iomux";
    reg = <0x0 0x91000080 0x0 0x20>;
    #pinctrl-cells = <1>;
    clocks = <&iomux_pclk_gate>;
    clock-names = "apb";
    status = "okay";
};

uart0_pins: uart0-pins {
    pinmux {
        pins = "io38", "io39";
        function = "alt1";  // UART0_TXD / UART0_RXD
        bias-disable;
        drive-strength = <8>;
        slew-rate = <1>;    // 快速
    };
};
```

Available Pin Names

- Main IOMUX: `io0` to `io63`
- PMU IOMUX: `io0` to `io7` (mapped to pins 64-71)

Available Pin Configuration Properties

- `bias-pull-up` - Enable pull-up resistor
- `bias-pull-down` - Enable pull-down resistor
- `bias-disable` - Disable pull-up/pull-down
- `drive-strength` - Drive strength (0-15, refer to TRM for specific current values)
- `slew-rate` - Slew rate control (0=disable, 1=enable)
- `input-enable` - Enable input buffer
- `output-enable` - Enable output buffer
- `input-schmitt` - Enable Schmitt trigger

Configurable functions can be found in previous sections

For more information, please refer to Documentation/devicetree/bindings/pinctrl/canaan,k230-iomux.yaml

## User-space Companion Tools

k230_iomux.py is a user-space tool for debugging and viewing iomux configurations

### Usage Examples

```bash
# View all pin configurations (controller 0)
python3 k230_iomux.py

# View specific pin
python3 k230_iomux.py --pin io38

# View pin and all available functions
python3 k230_iomux.py --pin io38 --funcs

# Set pin to a specific function
python3 k230_iomux.py --set io38 alt1

# Set pin with configuration options
python3 k230_iomux.py --set io38 alt1 --ie --oe --pu --ds 8

# Set pin using a specific function name
python3 k230_iomux.py --set io38 UART0_TXD

# View the second IOMUX controller (PMUIOMUX)
python3 k230_iomux.py --iomux 1

##### Set pin on the second controller
python3 k230_iomux.py --iomux 1 --set io3 alt1
```

### Usage Instructions

```bash
[root@canaan ~ ]#k230_iomux.py  -h
usage: k230_iomux.py [-h] [--pin PIN] [--funcs] [--set PIN FUNC]
                     [--iomux {0,1}] [--ie] [--no-ie] [--oe] [--no-oe] [--pu]
                     [--pd] [--no-pull] [--ds 1-15] [--sl] [--no-sl] [--st]
                     [--no-st]

K230 IOMUX Pin Configuration Tool

options:
  -h, --help          show this help message and exit
  --pin, -p PIN       Specific pin to view (e.g., io38)
  --funcs, -f         Show all available functions for a pin
  --set, -s PIN FUNC  Set pin to function (e.g., io38 alt1)
  --iomux, -i {0,1}   IOMUX controller index (0=main, 1=pmuiomux)
  --ie                Enable input
  --no-ie             Disable input
  --oe                Enable output
  --no-oe             Disable output
  --pu                Enable pull-up
  --pd                Enable pull-down
  --no-pull           Disable pull-up/down
  --ds 1-15           Drive strength (1-15)
  --sl                Enable slew rate
  --no-sl             Disable slew rate
  --st                Enable schmitt trigger
  --no-st             Disable schmitt trigger

Examples:
  # View all pin configurations (controller 0)
  python3 k230_iomux.py

  # View specific pin
  python3 k230_iomux.py --pin io38

  # View pin with all available functions
  python3 k230_iomux.py --pin io38 --funcs

  # Set pin to alt1 function
  python3 k230_iomux.py --set io38 alt1

  # Set pin with configuration options
  python3 k230_iomux.py --set io38 alt1 --ie --oe --pu --ds 8

  # Set pin using specific function name (must specify pin)
  python3 k230_iomux.py --set io38 UART0_TXD

  # View controller 1 (PMUIOMUX at 0x91000080)
  python3 k230_iomux.py --iomux 1

  # Set pin on controller 1
  python3 k230_iomux.py --iomux 1 --set io3 alt1

[root@canaan ~ ]#



#Command Line Parameters

| Parameter | Description |
| --- | --- |
| `--pin`, `-p` | Specific pin to view (e.g., `io38`) |
| `--funcs`, `-f` | Show all available functions for a pin |
| `--set`, `-s` | Set pin to function (e.g., `io38 alt1`) |
| `--iomux`, `-i` | IOMUX controller index (0=main, 1=pmuiomux) |
| `--ie` | Enable input |
| `--no-ie` | Disable input |
| `--oe` | Enable output |
| `--no-oe` | Disable output |
| `--pu` | Enable pull-up |
| `--pd` | Enable pull-down |
| `--no-pull` | Disable pull-up/down |
| `--ds` | Drive strength (1-15) |
| `--sl` | Enable slew rate |
| `--no-sl` | Disable slew rate |
| `--st` | Enable schmitt trigger |
| `--no-st` | Disable schmitt trigger |

```
