162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/err.h> 562306a36Sopenharmony_ci#include <linux/io.h> 662306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 962306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h> 1062306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/string_helpers.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "../core.h" 1662306a36Sopenharmony_ci#include "../pinmux.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define BCM4908_NUM_PINS 86 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define BCM4908_TEST_PORT_BLOCK_EN_LSB 0x00 2162306a36Sopenharmony_ci#define BCM4908_TEST_PORT_BLOCK_DATA_MSB 0x04 2262306a36Sopenharmony_ci#define BCM4908_TEST_PORT_BLOCK_DATA_LSB 0x08 2362306a36Sopenharmony_ci#define BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT 12 2462306a36Sopenharmony_ci#define BCM4908_TEST_PORT_COMMAND 0x0c 2562306a36Sopenharmony_ci#define BCM4908_TEST_PORT_CMD_LOAD_MUX_REG 0x00000021 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistruct bcm4908_pinctrl { 2862306a36Sopenharmony_ci struct device *dev; 2962306a36Sopenharmony_ci void __iomem *base; 3062306a36Sopenharmony_ci struct mutex mutex; 3162306a36Sopenharmony_ci struct pinctrl_dev *pctldev; 3262306a36Sopenharmony_ci struct pinctrl_desc pctldesc; 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * Groups 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct bcm4908_pinctrl_pin_setup { 4062306a36Sopenharmony_ci unsigned int number; 4162306a36Sopenharmony_ci unsigned int function; 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_0_pins_a[] = { 4562306a36Sopenharmony_ci { 0, 3 }, 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_1_pins_a[] = { 4962306a36Sopenharmony_ci { 1, 3 }, 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_2_pins_a[] = { 5362306a36Sopenharmony_ci { 2, 3 }, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_3_pins_a[] = { 5762306a36Sopenharmony_ci { 3, 3 }, 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_4_pins_a[] = { 6162306a36Sopenharmony_ci { 4, 3 }, 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_5_pins_a[] = { 6562306a36Sopenharmony_ci { 5, 3 }, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_6_pins_a[] = { 6962306a36Sopenharmony_ci { 6, 3 }, 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_7_pins_a[] = { 7362306a36Sopenharmony_ci { 7, 3 }, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_8_pins_a[] = { 7762306a36Sopenharmony_ci { 8, 3 }, 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_9_pins_a[] = { 8162306a36Sopenharmony_ci { 9, 3 }, 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_10_pins_a[] = { 8562306a36Sopenharmony_ci { 10, 3 }, 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_11_pins_a[] = { 8962306a36Sopenharmony_ci { 11, 3 }, 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_12_pins_a[] = { 9362306a36Sopenharmony_ci { 12, 3 }, 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_13_pins_a[] = { 9762306a36Sopenharmony_ci { 13, 3 }, 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_14_pins_a[] = { 10162306a36Sopenharmony_ci { 14, 3 }, 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_15_pins_a[] = { 10562306a36Sopenharmony_ci { 15, 3 }, 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_16_pins_a[] = { 10962306a36Sopenharmony_ci { 16, 3 }, 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_17_pins_a[] = { 11362306a36Sopenharmony_ci { 17, 3 }, 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_18_pins_a[] = { 11762306a36Sopenharmony_ci { 18, 3 }, 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_19_pins_a[] = { 12162306a36Sopenharmony_ci { 19, 3 }, 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_20_pins_a[] = { 12562306a36Sopenharmony_ci { 20, 3 }, 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_21_pins_a[] = { 12962306a36Sopenharmony_ci { 21, 3 }, 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_22_pins_a[] = { 13362306a36Sopenharmony_ci { 22, 3 }, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_23_pins_a[] = { 13762306a36Sopenharmony_ci { 23, 3 }, 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_24_pins_a[] = { 14162306a36Sopenharmony_ci { 24, 3 }, 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_25_pins_a[] = { 14562306a36Sopenharmony_ci { 25, 3 }, 14662306a36Sopenharmony_ci}; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_26_pins_a[] = { 14962306a36Sopenharmony_ci { 26, 3 }, 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_27_pins_a[] = { 15362306a36Sopenharmony_ci { 27, 3 }, 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_28_pins_a[] = { 15762306a36Sopenharmony_ci { 28, 3 }, 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_29_pins_a[] = { 16162306a36Sopenharmony_ci { 29, 3 }, 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_30_pins_a[] = { 16562306a36Sopenharmony_ci { 30, 3 }, 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_31_pins_a[] = { 16962306a36Sopenharmony_ci { 31, 3 }, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_10_pins_b[] = { 17362306a36Sopenharmony_ci { 8, 2 }, 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_11_pins_b[] = { 17762306a36Sopenharmony_ci { 9, 2 }, 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_12_pins_b[] = { 18162306a36Sopenharmony_ci { 0, 2 }, 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_13_pins_b[] = { 18562306a36Sopenharmony_ci { 1, 2 }, 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup led_31_pins_b[] = { 18962306a36Sopenharmony_ci { 30, 2 }, 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup hs_uart_pins[] = { 19362306a36Sopenharmony_ci { 10, 0 }, /* CTS */ 19462306a36Sopenharmony_ci { 11, 0 }, /* RTS */ 19562306a36Sopenharmony_ci { 12, 0 }, /* RXD */ 19662306a36Sopenharmony_ci { 13, 0 }, /* TXD */ 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup i2c_pins_a[] = { 20062306a36Sopenharmony_ci { 18, 0 }, /* SDA */ 20162306a36Sopenharmony_ci { 19, 0 }, /* SCL */ 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup i2c_pins_b[] = { 20562306a36Sopenharmony_ci { 22, 0 }, /* SDA */ 20662306a36Sopenharmony_ci { 23, 0 }, /* SCL */ 20762306a36Sopenharmony_ci}; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup i2s_pins[] = { 21062306a36Sopenharmony_ci { 27, 0 }, /* MCLK */ 21162306a36Sopenharmony_ci { 28, 0 }, /* LRCK */ 21262306a36Sopenharmony_ci { 29, 0 }, /* SDATA */ 21362306a36Sopenharmony_ci { 30, 0 }, /* SCLK */ 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup nand_ctrl_pins[] = { 21762306a36Sopenharmony_ci { 32, 0 }, 21862306a36Sopenharmony_ci { 33, 0 }, 21962306a36Sopenharmony_ci { 34, 0 }, 22062306a36Sopenharmony_ci { 43, 0 }, 22162306a36Sopenharmony_ci { 44, 0 }, 22262306a36Sopenharmony_ci { 45, 0 }, 22362306a36Sopenharmony_ci { 56, 1 }, 22462306a36Sopenharmony_ci}; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup nand_data_pins[] = { 22762306a36Sopenharmony_ci { 35, 0 }, 22862306a36Sopenharmony_ci { 36, 0 }, 22962306a36Sopenharmony_ci { 37, 0 }, 23062306a36Sopenharmony_ci { 38, 0 }, 23162306a36Sopenharmony_ci { 39, 0 }, 23262306a36Sopenharmony_ci { 40, 0 }, 23362306a36Sopenharmony_ci { 41, 0 }, 23462306a36Sopenharmony_ci { 42, 0 }, 23562306a36Sopenharmony_ci}; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup emmc_ctrl_pins[] = { 23862306a36Sopenharmony_ci { 46, 0 }, 23962306a36Sopenharmony_ci { 47, 0 }, 24062306a36Sopenharmony_ci}; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup usb0_pwr_pins[] = { 24362306a36Sopenharmony_ci { 63, 0 }, 24462306a36Sopenharmony_ci { 64, 0 }, 24562306a36Sopenharmony_ci}; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_pin_setup usb1_pwr_pins[] = { 24862306a36Sopenharmony_ci { 66, 0 }, 24962306a36Sopenharmony_ci { 67, 0 }, 25062306a36Sopenharmony_ci}; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistruct bcm4908_pinctrl_grp { 25362306a36Sopenharmony_ci const char *name; 25462306a36Sopenharmony_ci const struct bcm4908_pinctrl_pin_setup *pins; 25562306a36Sopenharmony_ci const unsigned int num_pins; 25662306a36Sopenharmony_ci}; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_grp bcm4908_pinctrl_grps[] = { 25962306a36Sopenharmony_ci { "led_0_grp_a", led_0_pins_a, ARRAY_SIZE(led_0_pins_a) }, 26062306a36Sopenharmony_ci { "led_1_grp_a", led_1_pins_a, ARRAY_SIZE(led_1_pins_a) }, 26162306a36Sopenharmony_ci { "led_2_grp_a", led_2_pins_a, ARRAY_SIZE(led_2_pins_a) }, 26262306a36Sopenharmony_ci { "led_3_grp_a", led_3_pins_a, ARRAY_SIZE(led_3_pins_a) }, 26362306a36Sopenharmony_ci { "led_4_grp_a", led_4_pins_a, ARRAY_SIZE(led_4_pins_a) }, 26462306a36Sopenharmony_ci { "led_5_grp_a", led_5_pins_a, ARRAY_SIZE(led_5_pins_a) }, 26562306a36Sopenharmony_ci { "led_6_grp_a", led_6_pins_a, ARRAY_SIZE(led_6_pins_a) }, 26662306a36Sopenharmony_ci { "led_7_grp_a", led_7_pins_a, ARRAY_SIZE(led_7_pins_a) }, 26762306a36Sopenharmony_ci { "led_8_grp_a", led_8_pins_a, ARRAY_SIZE(led_8_pins_a) }, 26862306a36Sopenharmony_ci { "led_9_grp_a", led_9_pins_a, ARRAY_SIZE(led_9_pins_a) }, 26962306a36Sopenharmony_ci { "led_10_grp_a", led_10_pins_a, ARRAY_SIZE(led_10_pins_a) }, 27062306a36Sopenharmony_ci { "led_11_grp_a", led_11_pins_a, ARRAY_SIZE(led_11_pins_a) }, 27162306a36Sopenharmony_ci { "led_12_grp_a", led_12_pins_a, ARRAY_SIZE(led_12_pins_a) }, 27262306a36Sopenharmony_ci { "led_13_grp_a", led_13_pins_a, ARRAY_SIZE(led_13_pins_a) }, 27362306a36Sopenharmony_ci { "led_14_grp_a", led_14_pins_a, ARRAY_SIZE(led_14_pins_a) }, 27462306a36Sopenharmony_ci { "led_15_grp_a", led_15_pins_a, ARRAY_SIZE(led_15_pins_a) }, 27562306a36Sopenharmony_ci { "led_16_grp_a", led_16_pins_a, ARRAY_SIZE(led_16_pins_a) }, 27662306a36Sopenharmony_ci { "led_17_grp_a", led_17_pins_a, ARRAY_SIZE(led_17_pins_a) }, 27762306a36Sopenharmony_ci { "led_18_grp_a", led_18_pins_a, ARRAY_SIZE(led_18_pins_a) }, 27862306a36Sopenharmony_ci { "led_19_grp_a", led_19_pins_a, ARRAY_SIZE(led_19_pins_a) }, 27962306a36Sopenharmony_ci { "led_20_grp_a", led_20_pins_a, ARRAY_SIZE(led_20_pins_a) }, 28062306a36Sopenharmony_ci { "led_21_grp_a", led_21_pins_a, ARRAY_SIZE(led_21_pins_a) }, 28162306a36Sopenharmony_ci { "led_22_grp_a", led_22_pins_a, ARRAY_SIZE(led_22_pins_a) }, 28262306a36Sopenharmony_ci { "led_23_grp_a", led_23_pins_a, ARRAY_SIZE(led_23_pins_a) }, 28362306a36Sopenharmony_ci { "led_24_grp_a", led_24_pins_a, ARRAY_SIZE(led_24_pins_a) }, 28462306a36Sopenharmony_ci { "led_25_grp_a", led_25_pins_a, ARRAY_SIZE(led_25_pins_a) }, 28562306a36Sopenharmony_ci { "led_26_grp_a", led_26_pins_a, ARRAY_SIZE(led_26_pins_a) }, 28662306a36Sopenharmony_ci { "led_27_grp_a", led_27_pins_a, ARRAY_SIZE(led_27_pins_a) }, 28762306a36Sopenharmony_ci { "led_28_grp_a", led_28_pins_a, ARRAY_SIZE(led_28_pins_a) }, 28862306a36Sopenharmony_ci { "led_29_grp_a", led_29_pins_a, ARRAY_SIZE(led_29_pins_a) }, 28962306a36Sopenharmony_ci { "led_30_grp_a", led_30_pins_a, ARRAY_SIZE(led_30_pins_a) }, 29062306a36Sopenharmony_ci { "led_31_grp_a", led_31_pins_a, ARRAY_SIZE(led_31_pins_a) }, 29162306a36Sopenharmony_ci { "led_10_grp_b", led_10_pins_b, ARRAY_SIZE(led_10_pins_b) }, 29262306a36Sopenharmony_ci { "led_11_grp_b", led_11_pins_b, ARRAY_SIZE(led_11_pins_b) }, 29362306a36Sopenharmony_ci { "led_12_grp_b", led_12_pins_b, ARRAY_SIZE(led_12_pins_b) }, 29462306a36Sopenharmony_ci { "led_13_grp_b", led_13_pins_b, ARRAY_SIZE(led_13_pins_b) }, 29562306a36Sopenharmony_ci { "led_31_grp_b", led_31_pins_b, ARRAY_SIZE(led_31_pins_b) }, 29662306a36Sopenharmony_ci { "hs_uart_grp", hs_uart_pins, ARRAY_SIZE(hs_uart_pins) }, 29762306a36Sopenharmony_ci { "i2c_grp_a", i2c_pins_a, ARRAY_SIZE(i2c_pins_a) }, 29862306a36Sopenharmony_ci { "i2c_grp_b", i2c_pins_b, ARRAY_SIZE(i2c_pins_b) }, 29962306a36Sopenharmony_ci { "i2s_grp", i2s_pins, ARRAY_SIZE(i2s_pins) }, 30062306a36Sopenharmony_ci { "nand_ctrl_grp", nand_ctrl_pins, ARRAY_SIZE(nand_ctrl_pins) }, 30162306a36Sopenharmony_ci { "nand_data_grp", nand_data_pins, ARRAY_SIZE(nand_data_pins) }, 30262306a36Sopenharmony_ci { "emmc_ctrl_grp", emmc_ctrl_pins, ARRAY_SIZE(emmc_ctrl_pins) }, 30362306a36Sopenharmony_ci { "usb0_pwr_grp", usb0_pwr_pins, ARRAY_SIZE(usb0_pwr_pins) }, 30462306a36Sopenharmony_ci { "usb1_pwr_grp", usb1_pwr_pins, ARRAY_SIZE(usb1_pwr_pins) }, 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci/* 30862306a36Sopenharmony_ci * Functions 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistruct bcm4908_pinctrl_function { 31262306a36Sopenharmony_ci const char *name; 31362306a36Sopenharmony_ci const char * const *groups; 31462306a36Sopenharmony_ci const unsigned int num_groups; 31562306a36Sopenharmony_ci}; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic const char * const led_0_groups[] = { "led_0_grp_a" }; 31862306a36Sopenharmony_cistatic const char * const led_1_groups[] = { "led_1_grp_a" }; 31962306a36Sopenharmony_cistatic const char * const led_2_groups[] = { "led_2_grp_a" }; 32062306a36Sopenharmony_cistatic const char * const led_3_groups[] = { "led_3_grp_a" }; 32162306a36Sopenharmony_cistatic const char * const led_4_groups[] = { "led_4_grp_a" }; 32262306a36Sopenharmony_cistatic const char * const led_5_groups[] = { "led_5_grp_a" }; 32362306a36Sopenharmony_cistatic const char * const led_6_groups[] = { "led_6_grp_a" }; 32462306a36Sopenharmony_cistatic const char * const led_7_groups[] = { "led_7_grp_a" }; 32562306a36Sopenharmony_cistatic const char * const led_8_groups[] = { "led_8_grp_a" }; 32662306a36Sopenharmony_cistatic const char * const led_9_groups[] = { "led_9_grp_a" }; 32762306a36Sopenharmony_cistatic const char * const led_10_groups[] = { "led_10_grp_a", "led_10_grp_b" }; 32862306a36Sopenharmony_cistatic const char * const led_11_groups[] = { "led_11_grp_a", "led_11_grp_b" }; 32962306a36Sopenharmony_cistatic const char * const led_12_groups[] = { "led_12_grp_a", "led_12_grp_b" }; 33062306a36Sopenharmony_cistatic const char * const led_13_groups[] = { "led_13_grp_a", "led_13_grp_b" }; 33162306a36Sopenharmony_cistatic const char * const led_14_groups[] = { "led_14_grp_a" }; 33262306a36Sopenharmony_cistatic const char * const led_15_groups[] = { "led_15_grp_a" }; 33362306a36Sopenharmony_cistatic const char * const led_16_groups[] = { "led_16_grp_a" }; 33462306a36Sopenharmony_cistatic const char * const led_17_groups[] = { "led_17_grp_a" }; 33562306a36Sopenharmony_cistatic const char * const led_18_groups[] = { "led_18_grp_a" }; 33662306a36Sopenharmony_cistatic const char * const led_19_groups[] = { "led_19_grp_a" }; 33762306a36Sopenharmony_cistatic const char * const led_20_groups[] = { "led_20_grp_a" }; 33862306a36Sopenharmony_cistatic const char * const led_21_groups[] = { "led_21_grp_a" }; 33962306a36Sopenharmony_cistatic const char * const led_22_groups[] = { "led_22_grp_a" }; 34062306a36Sopenharmony_cistatic const char * const led_23_groups[] = { "led_23_grp_a" }; 34162306a36Sopenharmony_cistatic const char * const led_24_groups[] = { "led_24_grp_a" }; 34262306a36Sopenharmony_cistatic const char * const led_25_groups[] = { "led_25_grp_a" }; 34362306a36Sopenharmony_cistatic const char * const led_26_groups[] = { "led_26_grp_a" }; 34462306a36Sopenharmony_cistatic const char * const led_27_groups[] = { "led_27_grp_a" }; 34562306a36Sopenharmony_cistatic const char * const led_28_groups[] = { "led_28_grp_a" }; 34662306a36Sopenharmony_cistatic const char * const led_29_groups[] = { "led_29_grp_a" }; 34762306a36Sopenharmony_cistatic const char * const led_30_groups[] = { "led_30_grp_a" }; 34862306a36Sopenharmony_cistatic const char * const led_31_groups[] = { "led_31_grp_a", "led_31_grp_b" }; 34962306a36Sopenharmony_cistatic const char * const hs_uart_groups[] = { "hs_uart_grp" }; 35062306a36Sopenharmony_cistatic const char * const i2c_groups[] = { "i2c_grp_a", "i2c_grp_b" }; 35162306a36Sopenharmony_cistatic const char * const i2s_groups[] = { "i2s_grp" }; 35262306a36Sopenharmony_cistatic const char * const nand_ctrl_groups[] = { "nand_ctrl_grp" }; 35362306a36Sopenharmony_cistatic const char * const nand_data_groups[] = { "nand_data_grp" }; 35462306a36Sopenharmony_cistatic const char * const emmc_ctrl_groups[] = { "emmc_ctrl_grp" }; 35562306a36Sopenharmony_cistatic const char * const usb0_pwr_groups[] = { "usb0_pwr_grp" }; 35662306a36Sopenharmony_cistatic const char * const usb1_pwr_groups[] = { "usb1_pwr_grp" }; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic const struct bcm4908_pinctrl_function bcm4908_pinctrl_functions[] = { 35962306a36Sopenharmony_ci { "led_0", led_0_groups, ARRAY_SIZE(led_0_groups) }, 36062306a36Sopenharmony_ci { "led_1", led_1_groups, ARRAY_SIZE(led_1_groups) }, 36162306a36Sopenharmony_ci { "led_2", led_2_groups, ARRAY_SIZE(led_2_groups) }, 36262306a36Sopenharmony_ci { "led_3", led_3_groups, ARRAY_SIZE(led_3_groups) }, 36362306a36Sopenharmony_ci { "led_4", led_4_groups, ARRAY_SIZE(led_4_groups) }, 36462306a36Sopenharmony_ci { "led_5", led_5_groups, ARRAY_SIZE(led_5_groups) }, 36562306a36Sopenharmony_ci { "led_6", led_6_groups, ARRAY_SIZE(led_6_groups) }, 36662306a36Sopenharmony_ci { "led_7", led_7_groups, ARRAY_SIZE(led_7_groups) }, 36762306a36Sopenharmony_ci { "led_8", led_8_groups, ARRAY_SIZE(led_8_groups) }, 36862306a36Sopenharmony_ci { "led_9", led_9_groups, ARRAY_SIZE(led_9_groups) }, 36962306a36Sopenharmony_ci { "led_10", led_10_groups, ARRAY_SIZE(led_10_groups) }, 37062306a36Sopenharmony_ci { "led_11", led_11_groups, ARRAY_SIZE(led_11_groups) }, 37162306a36Sopenharmony_ci { "led_12", led_12_groups, ARRAY_SIZE(led_12_groups) }, 37262306a36Sopenharmony_ci { "led_13", led_13_groups, ARRAY_SIZE(led_13_groups) }, 37362306a36Sopenharmony_ci { "led_14", led_14_groups, ARRAY_SIZE(led_14_groups) }, 37462306a36Sopenharmony_ci { "led_15", led_15_groups, ARRAY_SIZE(led_15_groups) }, 37562306a36Sopenharmony_ci { "led_16", led_16_groups, ARRAY_SIZE(led_16_groups) }, 37662306a36Sopenharmony_ci { "led_17", led_17_groups, ARRAY_SIZE(led_17_groups) }, 37762306a36Sopenharmony_ci { "led_18", led_18_groups, ARRAY_SIZE(led_18_groups) }, 37862306a36Sopenharmony_ci { "led_19", led_19_groups, ARRAY_SIZE(led_19_groups) }, 37962306a36Sopenharmony_ci { "led_20", led_20_groups, ARRAY_SIZE(led_20_groups) }, 38062306a36Sopenharmony_ci { "led_21", led_21_groups, ARRAY_SIZE(led_21_groups) }, 38162306a36Sopenharmony_ci { "led_22", led_22_groups, ARRAY_SIZE(led_22_groups) }, 38262306a36Sopenharmony_ci { "led_23", led_23_groups, ARRAY_SIZE(led_23_groups) }, 38362306a36Sopenharmony_ci { "led_24", led_24_groups, ARRAY_SIZE(led_24_groups) }, 38462306a36Sopenharmony_ci { "led_25", led_25_groups, ARRAY_SIZE(led_25_groups) }, 38562306a36Sopenharmony_ci { "led_26", led_26_groups, ARRAY_SIZE(led_26_groups) }, 38662306a36Sopenharmony_ci { "led_27", led_27_groups, ARRAY_SIZE(led_27_groups) }, 38762306a36Sopenharmony_ci { "led_28", led_28_groups, ARRAY_SIZE(led_28_groups) }, 38862306a36Sopenharmony_ci { "led_29", led_29_groups, ARRAY_SIZE(led_29_groups) }, 38962306a36Sopenharmony_ci { "led_30", led_30_groups, ARRAY_SIZE(led_30_groups) }, 39062306a36Sopenharmony_ci { "led_31", led_31_groups, ARRAY_SIZE(led_31_groups) }, 39162306a36Sopenharmony_ci { "hs_uart", hs_uart_groups, ARRAY_SIZE(hs_uart_groups) }, 39262306a36Sopenharmony_ci { "i2c", i2c_groups, ARRAY_SIZE(i2c_groups) }, 39362306a36Sopenharmony_ci { "i2s", i2s_groups, ARRAY_SIZE(i2s_groups) }, 39462306a36Sopenharmony_ci { "nand_ctrl", nand_ctrl_groups, ARRAY_SIZE(nand_ctrl_groups) }, 39562306a36Sopenharmony_ci { "nand_data", nand_data_groups, ARRAY_SIZE(nand_data_groups) }, 39662306a36Sopenharmony_ci { "emmc_ctrl", emmc_ctrl_groups, ARRAY_SIZE(emmc_ctrl_groups) }, 39762306a36Sopenharmony_ci { "usb0_pwr", usb0_pwr_groups, ARRAY_SIZE(usb0_pwr_groups) }, 39862306a36Sopenharmony_ci { "usb1_pwr", usb1_pwr_groups, ARRAY_SIZE(usb1_pwr_groups) }, 39962306a36Sopenharmony_ci}; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci/* 40262306a36Sopenharmony_ci * Groups code 40362306a36Sopenharmony_ci */ 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic const struct pinctrl_ops bcm4908_pinctrl_ops = { 40662306a36Sopenharmony_ci .get_groups_count = pinctrl_generic_get_group_count, 40762306a36Sopenharmony_ci .get_group_name = pinctrl_generic_get_group_name, 40862306a36Sopenharmony_ci .get_group_pins = pinctrl_generic_get_group_pins, 40962306a36Sopenharmony_ci .dt_node_to_map = pinconf_generic_dt_node_to_map_group, 41062306a36Sopenharmony_ci .dt_free_map = pinconf_generic_dt_free_map, 41162306a36Sopenharmony_ci}; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci/* 41462306a36Sopenharmony_ci * Functions code 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic int bcm4908_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, 41862306a36Sopenharmony_ci unsigned int func_selector, 41962306a36Sopenharmony_ci unsigned int group_selector) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct bcm4908_pinctrl *bcm4908_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); 42262306a36Sopenharmony_ci const struct bcm4908_pinctrl_grp *group; 42362306a36Sopenharmony_ci struct group_desc *group_desc; 42462306a36Sopenharmony_ci int i; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci group_desc = pinctrl_generic_get_group(pctrl_dev, group_selector); 42762306a36Sopenharmony_ci if (!group_desc) 42862306a36Sopenharmony_ci return -EINVAL; 42962306a36Sopenharmony_ci group = group_desc->data; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci mutex_lock(&bcm4908_pinctrl->mutex); 43262306a36Sopenharmony_ci for (i = 0; i < group->num_pins; i++) { 43362306a36Sopenharmony_ci u32 lsb = 0; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci lsb |= group->pins[i].number; 43662306a36Sopenharmony_ci lsb |= group->pins[i].function << BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci writel(0x0, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_MSB); 43962306a36Sopenharmony_ci writel(lsb, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_LSB); 44062306a36Sopenharmony_ci writel(BCM4908_TEST_PORT_CMD_LOAD_MUX_REG, 44162306a36Sopenharmony_ci bcm4908_pinctrl->base + BCM4908_TEST_PORT_COMMAND); 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci mutex_unlock(&bcm4908_pinctrl->mutex); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci return 0; 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic const struct pinmux_ops bcm4908_pinctrl_pmxops = { 44962306a36Sopenharmony_ci .get_functions_count = pinmux_generic_get_function_count, 45062306a36Sopenharmony_ci .get_function_name = pinmux_generic_get_function_name, 45162306a36Sopenharmony_ci .get_function_groups = pinmux_generic_get_function_groups, 45262306a36Sopenharmony_ci .set_mux = bcm4908_pinctrl_set_mux, 45362306a36Sopenharmony_ci}; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci/* 45662306a36Sopenharmony_ci * Controller code 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic struct pinctrl_desc bcm4908_pinctrl_desc = { 46062306a36Sopenharmony_ci .name = "bcm4908-pinctrl", 46162306a36Sopenharmony_ci .pctlops = &bcm4908_pinctrl_ops, 46262306a36Sopenharmony_ci .pmxops = &bcm4908_pinctrl_pmxops, 46362306a36Sopenharmony_ci}; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic const struct of_device_id bcm4908_pinctrl_of_match_table[] = { 46662306a36Sopenharmony_ci { .compatible = "brcm,bcm4908-pinctrl", }, 46762306a36Sopenharmony_ci { } 46862306a36Sopenharmony_ci}; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic int bcm4908_pinctrl_probe(struct platform_device *pdev) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci struct device *dev = &pdev->dev; 47362306a36Sopenharmony_ci struct bcm4908_pinctrl *bcm4908_pinctrl; 47462306a36Sopenharmony_ci struct pinctrl_desc *pctldesc; 47562306a36Sopenharmony_ci struct pinctrl_pin_desc *pins; 47662306a36Sopenharmony_ci char **pin_names; 47762306a36Sopenharmony_ci int i; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci bcm4908_pinctrl = devm_kzalloc(dev, sizeof(*bcm4908_pinctrl), GFP_KERNEL); 48062306a36Sopenharmony_ci if (!bcm4908_pinctrl) 48162306a36Sopenharmony_ci return -ENOMEM; 48262306a36Sopenharmony_ci pctldesc = &bcm4908_pinctrl->pctldesc; 48362306a36Sopenharmony_ci platform_set_drvdata(pdev, bcm4908_pinctrl); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* Set basic properties */ 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci bcm4908_pinctrl->dev = dev; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci bcm4908_pinctrl->base = devm_platform_ioremap_resource(pdev, 0); 49062306a36Sopenharmony_ci if (IS_ERR(bcm4908_pinctrl->base)) 49162306a36Sopenharmony_ci return PTR_ERR(bcm4908_pinctrl->base); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci mutex_init(&bcm4908_pinctrl->mutex); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci memcpy(pctldesc, &bcm4908_pinctrl_desc, sizeof(*pctldesc)); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* Set pinctrl properties */ 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci pin_names = devm_kasprintf_strarray(dev, "pin", BCM4908_NUM_PINS); 50062306a36Sopenharmony_ci if (IS_ERR(pin_names)) 50162306a36Sopenharmony_ci return PTR_ERR(pin_names); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci pins = devm_kcalloc(dev, BCM4908_NUM_PINS, sizeof(*pins), GFP_KERNEL); 50462306a36Sopenharmony_ci if (!pins) 50562306a36Sopenharmony_ci return -ENOMEM; 50662306a36Sopenharmony_ci for (i = 0; i < BCM4908_NUM_PINS; i++) { 50762306a36Sopenharmony_ci pins[i].number = i; 50862306a36Sopenharmony_ci pins[i].name = pin_names[i]; 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci pctldesc->pins = pins; 51162306a36Sopenharmony_ci pctldesc->npins = BCM4908_NUM_PINS; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci /* Register */ 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci bcm4908_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, bcm4908_pinctrl); 51662306a36Sopenharmony_ci if (IS_ERR(bcm4908_pinctrl->pctldev)) 51762306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(bcm4908_pinctrl->pctldev), 51862306a36Sopenharmony_ci "Failed to register pinctrl\n"); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci /* Groups */ 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_grps); i++) { 52362306a36Sopenharmony_ci const struct bcm4908_pinctrl_grp *group = &bcm4908_pinctrl_grps[i]; 52462306a36Sopenharmony_ci int *pins; 52562306a36Sopenharmony_ci int j; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci pins = devm_kcalloc(dev, group->num_pins, sizeof(*pins), GFP_KERNEL); 52862306a36Sopenharmony_ci if (!pins) 52962306a36Sopenharmony_ci return -ENOMEM; 53062306a36Sopenharmony_ci for (j = 0; j < group->num_pins; j++) 53162306a36Sopenharmony_ci pins[j] = group->pins[j].number; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci pinctrl_generic_add_group(bcm4908_pinctrl->pctldev, group->name, 53462306a36Sopenharmony_ci pins, group->num_pins, (void *)group); 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* Functions */ 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_functions); i++) { 54062306a36Sopenharmony_ci const struct bcm4908_pinctrl_function *function = &bcm4908_pinctrl_functions[i]; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci pinmux_generic_add_function(bcm4908_pinctrl->pctldev, 54362306a36Sopenharmony_ci function->name, 54462306a36Sopenharmony_ci function->groups, 54562306a36Sopenharmony_ci function->num_groups, NULL); 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci return 0; 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic struct platform_driver bcm4908_pinctrl_driver = { 55262306a36Sopenharmony_ci .probe = bcm4908_pinctrl_probe, 55362306a36Sopenharmony_ci .driver = { 55462306a36Sopenharmony_ci .name = "bcm4908-pinctrl", 55562306a36Sopenharmony_ci .of_match_table = bcm4908_pinctrl_of_match_table, 55662306a36Sopenharmony_ci }, 55762306a36Sopenharmony_ci}; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_cimodule_platform_driver(bcm4908_pinctrl_driver); 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ciMODULE_AUTHOR("Rafał Miłecki"); 56262306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 56362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, bcm4908_pinctrl_of_match_table); 564