162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for BCM6368 GPIO unit (pinctrl + GPIO) 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2021 Álvaro Fernández Rojas <noltari@gmail.com> 662306a36Sopenharmony_ci * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/bits.h> 1062306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/of.h> 1362306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 1462306a36Sopenharmony_ci#include <linux/platform_device.h> 1562306a36Sopenharmony_ci#include <linux/regmap.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "../pinctrl-utils.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "pinctrl-bcm63xx.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define BCM6368_NUM_GPIOS 38 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define BCM6368_MODE_REG 0x18 2462306a36Sopenharmony_ci#define BCM6368_BASEMODE_REG 0x38 2562306a36Sopenharmony_ci#define BCM6368_BASEMODE_MASK 0x7 2662306a36Sopenharmony_ci#define BCM6368_BASEMODE_GPIO 0x0 2762306a36Sopenharmony_ci#define BCM6368_BASEMODE_UART1 0x1 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct bcm6368_function { 3062306a36Sopenharmony_ci const char *name; 3162306a36Sopenharmony_ci const char * const *groups; 3262306a36Sopenharmony_ci const unsigned num_groups; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci unsigned dir_out:16; 3562306a36Sopenharmony_ci unsigned basemode:3; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistruct bcm6368_priv { 3962306a36Sopenharmony_ci struct regmap_field *overlays; 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define BCM6368_BASEMODE_PIN(a, b) \ 4362306a36Sopenharmony_ci { \ 4462306a36Sopenharmony_ci .number = a, \ 4562306a36Sopenharmony_ci .name = b, \ 4662306a36Sopenharmony_ci .drv_data = (void *)true \ 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const struct pinctrl_pin_desc bcm6368_pins[] = { 5062306a36Sopenharmony_ci PINCTRL_PIN(0, "gpio0"), 5162306a36Sopenharmony_ci PINCTRL_PIN(1, "gpio1"), 5262306a36Sopenharmony_ci PINCTRL_PIN(2, "gpio2"), 5362306a36Sopenharmony_ci PINCTRL_PIN(3, "gpio3"), 5462306a36Sopenharmony_ci PINCTRL_PIN(4, "gpio4"), 5562306a36Sopenharmony_ci PINCTRL_PIN(5, "gpio5"), 5662306a36Sopenharmony_ci PINCTRL_PIN(6, "gpio6"), 5762306a36Sopenharmony_ci PINCTRL_PIN(7, "gpio7"), 5862306a36Sopenharmony_ci PINCTRL_PIN(8, "gpio8"), 5962306a36Sopenharmony_ci PINCTRL_PIN(9, "gpio9"), 6062306a36Sopenharmony_ci PINCTRL_PIN(10, "gpio10"), 6162306a36Sopenharmony_ci PINCTRL_PIN(11, "gpio11"), 6262306a36Sopenharmony_ci PINCTRL_PIN(12, "gpio12"), 6362306a36Sopenharmony_ci PINCTRL_PIN(13, "gpio13"), 6462306a36Sopenharmony_ci PINCTRL_PIN(14, "gpio14"), 6562306a36Sopenharmony_ci PINCTRL_PIN(15, "gpio15"), 6662306a36Sopenharmony_ci PINCTRL_PIN(16, "gpio16"), 6762306a36Sopenharmony_ci PINCTRL_PIN(17, "gpio17"), 6862306a36Sopenharmony_ci PINCTRL_PIN(18, "gpio18"), 6962306a36Sopenharmony_ci PINCTRL_PIN(19, "gpio19"), 7062306a36Sopenharmony_ci PINCTRL_PIN(20, "gpio20"), 7162306a36Sopenharmony_ci PINCTRL_PIN(21, "gpio21"), 7262306a36Sopenharmony_ci PINCTRL_PIN(22, "gpio22"), 7362306a36Sopenharmony_ci PINCTRL_PIN(23, "gpio23"), 7462306a36Sopenharmony_ci PINCTRL_PIN(24, "gpio24"), 7562306a36Sopenharmony_ci PINCTRL_PIN(25, "gpio25"), 7662306a36Sopenharmony_ci PINCTRL_PIN(26, "gpio26"), 7762306a36Sopenharmony_ci PINCTRL_PIN(27, "gpio27"), 7862306a36Sopenharmony_ci PINCTRL_PIN(28, "gpio28"), 7962306a36Sopenharmony_ci PINCTRL_PIN(29, "gpio29"), 8062306a36Sopenharmony_ci BCM6368_BASEMODE_PIN(30, "gpio30"), 8162306a36Sopenharmony_ci BCM6368_BASEMODE_PIN(31, "gpio31"), 8262306a36Sopenharmony_ci BCM6368_BASEMODE_PIN(32, "gpio32"), 8362306a36Sopenharmony_ci BCM6368_BASEMODE_PIN(33, "gpio33"), 8462306a36Sopenharmony_ci PINCTRL_PIN(34, "gpio34"), 8562306a36Sopenharmony_ci PINCTRL_PIN(35, "gpio35"), 8662306a36Sopenharmony_ci PINCTRL_PIN(36, "gpio36"), 8762306a36Sopenharmony_ci PINCTRL_PIN(37, "gpio37"), 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic unsigned gpio0_pins[] = { 0 }; 9162306a36Sopenharmony_cistatic unsigned gpio1_pins[] = { 1 }; 9262306a36Sopenharmony_cistatic unsigned gpio2_pins[] = { 2 }; 9362306a36Sopenharmony_cistatic unsigned gpio3_pins[] = { 3 }; 9462306a36Sopenharmony_cistatic unsigned gpio4_pins[] = { 4 }; 9562306a36Sopenharmony_cistatic unsigned gpio5_pins[] = { 5 }; 9662306a36Sopenharmony_cistatic unsigned gpio6_pins[] = { 6 }; 9762306a36Sopenharmony_cistatic unsigned gpio7_pins[] = { 7 }; 9862306a36Sopenharmony_cistatic unsigned gpio8_pins[] = { 8 }; 9962306a36Sopenharmony_cistatic unsigned gpio9_pins[] = { 9 }; 10062306a36Sopenharmony_cistatic unsigned gpio10_pins[] = { 10 }; 10162306a36Sopenharmony_cistatic unsigned gpio11_pins[] = { 11 }; 10262306a36Sopenharmony_cistatic unsigned gpio12_pins[] = { 12 }; 10362306a36Sopenharmony_cistatic unsigned gpio13_pins[] = { 13 }; 10462306a36Sopenharmony_cistatic unsigned gpio14_pins[] = { 14 }; 10562306a36Sopenharmony_cistatic unsigned gpio15_pins[] = { 15 }; 10662306a36Sopenharmony_cistatic unsigned gpio16_pins[] = { 16 }; 10762306a36Sopenharmony_cistatic unsigned gpio17_pins[] = { 17 }; 10862306a36Sopenharmony_cistatic unsigned gpio18_pins[] = { 18 }; 10962306a36Sopenharmony_cistatic unsigned gpio19_pins[] = { 19 }; 11062306a36Sopenharmony_cistatic unsigned gpio20_pins[] = { 20 }; 11162306a36Sopenharmony_cistatic unsigned gpio21_pins[] = { 21 }; 11262306a36Sopenharmony_cistatic unsigned gpio22_pins[] = { 22 }; 11362306a36Sopenharmony_cistatic unsigned gpio23_pins[] = { 23 }; 11462306a36Sopenharmony_cistatic unsigned gpio24_pins[] = { 24 }; 11562306a36Sopenharmony_cistatic unsigned gpio25_pins[] = { 25 }; 11662306a36Sopenharmony_cistatic unsigned gpio26_pins[] = { 26 }; 11762306a36Sopenharmony_cistatic unsigned gpio27_pins[] = { 27 }; 11862306a36Sopenharmony_cistatic unsigned gpio28_pins[] = { 28 }; 11962306a36Sopenharmony_cistatic unsigned gpio29_pins[] = { 29 }; 12062306a36Sopenharmony_cistatic unsigned gpio30_pins[] = { 30 }; 12162306a36Sopenharmony_cistatic unsigned gpio31_pins[] = { 31 }; 12262306a36Sopenharmony_cistatic unsigned uart1_grp_pins[] = { 30, 31, 32, 33 }; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic struct pingroup bcm6368_groups[] = { 12562306a36Sopenharmony_ci BCM_PIN_GROUP(gpio0), 12662306a36Sopenharmony_ci BCM_PIN_GROUP(gpio1), 12762306a36Sopenharmony_ci BCM_PIN_GROUP(gpio2), 12862306a36Sopenharmony_ci BCM_PIN_GROUP(gpio3), 12962306a36Sopenharmony_ci BCM_PIN_GROUP(gpio4), 13062306a36Sopenharmony_ci BCM_PIN_GROUP(gpio5), 13162306a36Sopenharmony_ci BCM_PIN_GROUP(gpio6), 13262306a36Sopenharmony_ci BCM_PIN_GROUP(gpio7), 13362306a36Sopenharmony_ci BCM_PIN_GROUP(gpio8), 13462306a36Sopenharmony_ci BCM_PIN_GROUP(gpio9), 13562306a36Sopenharmony_ci BCM_PIN_GROUP(gpio10), 13662306a36Sopenharmony_ci BCM_PIN_GROUP(gpio11), 13762306a36Sopenharmony_ci BCM_PIN_GROUP(gpio12), 13862306a36Sopenharmony_ci BCM_PIN_GROUP(gpio13), 13962306a36Sopenharmony_ci BCM_PIN_GROUP(gpio14), 14062306a36Sopenharmony_ci BCM_PIN_GROUP(gpio15), 14162306a36Sopenharmony_ci BCM_PIN_GROUP(gpio16), 14262306a36Sopenharmony_ci BCM_PIN_GROUP(gpio17), 14362306a36Sopenharmony_ci BCM_PIN_GROUP(gpio18), 14462306a36Sopenharmony_ci BCM_PIN_GROUP(gpio19), 14562306a36Sopenharmony_ci BCM_PIN_GROUP(gpio20), 14662306a36Sopenharmony_ci BCM_PIN_GROUP(gpio21), 14762306a36Sopenharmony_ci BCM_PIN_GROUP(gpio22), 14862306a36Sopenharmony_ci BCM_PIN_GROUP(gpio23), 14962306a36Sopenharmony_ci BCM_PIN_GROUP(gpio24), 15062306a36Sopenharmony_ci BCM_PIN_GROUP(gpio25), 15162306a36Sopenharmony_ci BCM_PIN_GROUP(gpio26), 15262306a36Sopenharmony_ci BCM_PIN_GROUP(gpio27), 15362306a36Sopenharmony_ci BCM_PIN_GROUP(gpio28), 15462306a36Sopenharmony_ci BCM_PIN_GROUP(gpio29), 15562306a36Sopenharmony_ci BCM_PIN_GROUP(gpio30), 15662306a36Sopenharmony_ci BCM_PIN_GROUP(gpio31), 15762306a36Sopenharmony_ci BCM_PIN_GROUP(uart1_grp), 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic const char * const analog_afe_0_groups[] = { 16162306a36Sopenharmony_ci "gpio0", 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic const char * const analog_afe_1_groups[] = { 16562306a36Sopenharmony_ci "gpio1", 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic const char * const sys_irq_groups[] = { 16962306a36Sopenharmony_ci "gpio2", 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic const char * const serial_led_data_groups[] = { 17362306a36Sopenharmony_ci "gpio3", 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic const char * const serial_led_clk_groups[] = { 17762306a36Sopenharmony_ci "gpio4", 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic const char * const inet_led_groups[] = { 18162306a36Sopenharmony_ci "gpio5", 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic const char * const ephy0_led_groups[] = { 18562306a36Sopenharmony_ci "gpio6", 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic const char * const ephy1_led_groups[] = { 18962306a36Sopenharmony_ci "gpio7", 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic const char * const ephy2_led_groups[] = { 19362306a36Sopenharmony_ci "gpio8", 19462306a36Sopenharmony_ci}; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic const char * const ephy3_led_groups[] = { 19762306a36Sopenharmony_ci "gpio9", 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic const char * const robosw_led_data_groups[] = { 20162306a36Sopenharmony_ci "gpio10", 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic const char * const robosw_led_clk_groups[] = { 20562306a36Sopenharmony_ci "gpio11", 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic const char * const robosw_led0_groups[] = { 20962306a36Sopenharmony_ci "gpio12", 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const char * const robosw_led1_groups[] = { 21362306a36Sopenharmony_ci "gpio13", 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic const char * const usb_device_led_groups[] = { 21762306a36Sopenharmony_ci "gpio14", 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic const char * const pci_req1_groups[] = { 22162306a36Sopenharmony_ci "gpio16", 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic const char * const pci_gnt1_groups[] = { 22562306a36Sopenharmony_ci "gpio17", 22662306a36Sopenharmony_ci}; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic const char * const pci_intb_groups[] = { 22962306a36Sopenharmony_ci "gpio18", 23062306a36Sopenharmony_ci}; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic const char * const pci_req0_groups[] = { 23362306a36Sopenharmony_ci "gpio19", 23462306a36Sopenharmony_ci}; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic const char * const pci_gnt0_groups[] = { 23762306a36Sopenharmony_ci "gpio20", 23862306a36Sopenharmony_ci}; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic const char * const pcmcia_cd1_groups[] = { 24162306a36Sopenharmony_ci "gpio22", 24262306a36Sopenharmony_ci}; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic const char * const pcmcia_cd2_groups[] = { 24562306a36Sopenharmony_ci "gpio23", 24662306a36Sopenharmony_ci}; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic const char * const pcmcia_vs1_groups[] = { 24962306a36Sopenharmony_ci "gpio24", 25062306a36Sopenharmony_ci}; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic const char * const pcmcia_vs2_groups[] = { 25362306a36Sopenharmony_ci "gpio25", 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic const char * const ebi_cs2_groups[] = { 25762306a36Sopenharmony_ci "gpio26", 25862306a36Sopenharmony_ci}; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic const char * const ebi_cs3_groups[] = { 26162306a36Sopenharmony_ci "gpio27", 26262306a36Sopenharmony_ci}; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic const char * const spi_cs2_groups[] = { 26562306a36Sopenharmony_ci "gpio28", 26662306a36Sopenharmony_ci}; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic const char * const spi_cs3_groups[] = { 26962306a36Sopenharmony_ci "gpio29", 27062306a36Sopenharmony_ci}; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic const char * const spi_cs4_groups[] = { 27362306a36Sopenharmony_ci "gpio30", 27462306a36Sopenharmony_ci}; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic const char * const spi_cs5_groups[] = { 27762306a36Sopenharmony_ci "gpio31", 27862306a36Sopenharmony_ci}; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic const char * const uart1_groups[] = { 28162306a36Sopenharmony_ci "uart1_grp", 28262306a36Sopenharmony_ci}; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci#define BCM6368_FUN(n, out) \ 28562306a36Sopenharmony_ci { \ 28662306a36Sopenharmony_ci .name = #n, \ 28762306a36Sopenharmony_ci .groups = n##_groups, \ 28862306a36Sopenharmony_ci .num_groups = ARRAY_SIZE(n##_groups), \ 28962306a36Sopenharmony_ci .dir_out = out, \ 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci#define BCM6368_BASEMODE_FUN(n, val, out) \ 29362306a36Sopenharmony_ci { \ 29462306a36Sopenharmony_ci .name = #n, \ 29562306a36Sopenharmony_ci .groups = n##_groups, \ 29662306a36Sopenharmony_ci .num_groups = ARRAY_SIZE(n##_groups), \ 29762306a36Sopenharmony_ci .basemode = BCM6368_BASEMODE_##val, \ 29862306a36Sopenharmony_ci .dir_out = out, \ 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic const struct bcm6368_function bcm6368_funcs[] = { 30262306a36Sopenharmony_ci BCM6368_FUN(analog_afe_0, 1), 30362306a36Sopenharmony_ci BCM6368_FUN(analog_afe_1, 1), 30462306a36Sopenharmony_ci BCM6368_FUN(sys_irq, 1), 30562306a36Sopenharmony_ci BCM6368_FUN(serial_led_data, 1), 30662306a36Sopenharmony_ci BCM6368_FUN(serial_led_clk, 1), 30762306a36Sopenharmony_ci BCM6368_FUN(inet_led, 1), 30862306a36Sopenharmony_ci BCM6368_FUN(ephy0_led, 1), 30962306a36Sopenharmony_ci BCM6368_FUN(ephy1_led, 1), 31062306a36Sopenharmony_ci BCM6368_FUN(ephy2_led, 1), 31162306a36Sopenharmony_ci BCM6368_FUN(ephy3_led, 1), 31262306a36Sopenharmony_ci BCM6368_FUN(robosw_led_data, 1), 31362306a36Sopenharmony_ci BCM6368_FUN(robosw_led_clk, 1), 31462306a36Sopenharmony_ci BCM6368_FUN(robosw_led0, 1), 31562306a36Sopenharmony_ci BCM6368_FUN(robosw_led1, 1), 31662306a36Sopenharmony_ci BCM6368_FUN(usb_device_led, 1), 31762306a36Sopenharmony_ci BCM6368_FUN(pci_req1, 0), 31862306a36Sopenharmony_ci BCM6368_FUN(pci_gnt1, 0), 31962306a36Sopenharmony_ci BCM6368_FUN(pci_intb, 0), 32062306a36Sopenharmony_ci BCM6368_FUN(pci_req0, 0), 32162306a36Sopenharmony_ci BCM6368_FUN(pci_gnt0, 0), 32262306a36Sopenharmony_ci BCM6368_FUN(pcmcia_cd1, 0), 32362306a36Sopenharmony_ci BCM6368_FUN(pcmcia_cd2, 0), 32462306a36Sopenharmony_ci BCM6368_FUN(pcmcia_vs1, 0), 32562306a36Sopenharmony_ci BCM6368_FUN(pcmcia_vs2, 0), 32662306a36Sopenharmony_ci BCM6368_FUN(ebi_cs2, 1), 32762306a36Sopenharmony_ci BCM6368_FUN(ebi_cs3, 1), 32862306a36Sopenharmony_ci BCM6368_FUN(spi_cs2, 1), 32962306a36Sopenharmony_ci BCM6368_FUN(spi_cs3, 1), 33062306a36Sopenharmony_ci BCM6368_FUN(spi_cs4, 1), 33162306a36Sopenharmony_ci BCM6368_FUN(spi_cs5, 1), 33262306a36Sopenharmony_ci BCM6368_BASEMODE_FUN(uart1, UART1, 0x6), 33362306a36Sopenharmony_ci}; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic int bcm6368_pinctrl_get_group_count(struct pinctrl_dev *pctldev) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci return ARRAY_SIZE(bcm6368_groups); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic const char *bcm6368_pinctrl_get_group_name(struct pinctrl_dev *pctldev, 34162306a36Sopenharmony_ci unsigned group) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci return bcm6368_groups[group].name; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic int bcm6368_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, 34762306a36Sopenharmony_ci unsigned group, const unsigned **pins, 34862306a36Sopenharmony_ci unsigned *npins) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci *pins = bcm6368_groups[group].pins; 35162306a36Sopenharmony_ci *npins = bcm6368_groups[group].npins; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci return 0; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic int bcm6368_pinctrl_get_func_count(struct pinctrl_dev *pctldev) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci return ARRAY_SIZE(bcm6368_funcs); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic const char *bcm6368_pinctrl_get_func_name(struct pinctrl_dev *pctldev, 36262306a36Sopenharmony_ci unsigned selector) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci return bcm6368_funcs[selector].name; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic int bcm6368_pinctrl_get_groups(struct pinctrl_dev *pctldev, 36862306a36Sopenharmony_ci unsigned selector, 36962306a36Sopenharmony_ci const char * const **groups, 37062306a36Sopenharmony_ci unsigned * const num_groups) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci *groups = bcm6368_funcs[selector].groups; 37362306a36Sopenharmony_ci *num_groups = bcm6368_funcs[selector].num_groups; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci return 0; 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic int bcm6368_pinctrl_set_mux(struct pinctrl_dev *pctldev, 37962306a36Sopenharmony_ci unsigned selector, unsigned group) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct bcm63xx_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); 38262306a36Sopenharmony_ci struct bcm6368_priv *priv = pc->driver_data; 38362306a36Sopenharmony_ci const struct pingroup *pg = &bcm6368_groups[group]; 38462306a36Sopenharmony_ci const struct bcm6368_function *fun = &bcm6368_funcs[selector]; 38562306a36Sopenharmony_ci int i, pin; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (fun->basemode) { 38862306a36Sopenharmony_ci unsigned int mask = 0; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci for (i = 0; i < pg->npins; i++) { 39162306a36Sopenharmony_ci pin = pg->pins[i]; 39262306a36Sopenharmony_ci if (pin < BCM63XX_BANK_GPIOS) 39362306a36Sopenharmony_ci mask |= BIT(pin); 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci regmap_update_bits(pc->regs, BCM6368_MODE_REG, mask, 0); 39762306a36Sopenharmony_ci regmap_field_write(priv->overlays, fun->basemode); 39862306a36Sopenharmony_ci } else { 39962306a36Sopenharmony_ci pin = pg->pins[0]; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci if (bcm6368_pins[pin].drv_data) 40262306a36Sopenharmony_ci regmap_field_write(priv->overlays, 40362306a36Sopenharmony_ci BCM6368_BASEMODE_GPIO); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci regmap_update_bits(pc->regs, BCM6368_MODE_REG, BIT(pin), 40662306a36Sopenharmony_ci BIT(pin)); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci for (pin = 0; pin < pg->npins; pin++) { 41062306a36Sopenharmony_ci struct pinctrl_gpio_range *range; 41162306a36Sopenharmony_ci int hw_gpio = bcm6368_pins[pin].number; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci range = pinctrl_find_gpio_range_from_pin(pctldev, hw_gpio); 41462306a36Sopenharmony_ci if (range) { 41562306a36Sopenharmony_ci struct gpio_chip *gc = range->gc; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci if (fun->dir_out & BIT(pin)) 41862306a36Sopenharmony_ci gc->direction_output(gc, hw_gpio, 0); 41962306a36Sopenharmony_ci else 42062306a36Sopenharmony_ci gc->direction_input(gc, hw_gpio); 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci return 0; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic int bcm6368_gpio_request_enable(struct pinctrl_dev *pctldev, 42862306a36Sopenharmony_ci struct pinctrl_gpio_range *range, 42962306a36Sopenharmony_ci unsigned offset) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci struct bcm63xx_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); 43262306a36Sopenharmony_ci struct bcm6368_priv *priv = pc->driver_data; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (offset >= BCM63XX_BANK_GPIOS && !bcm6368_pins[offset].drv_data) 43562306a36Sopenharmony_ci return 0; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* disable all functions using this pin */ 43862306a36Sopenharmony_ci if (offset < BCM63XX_BANK_GPIOS) 43962306a36Sopenharmony_ci regmap_update_bits(pc->regs, BCM6368_MODE_REG, BIT(offset), 0); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (bcm6368_pins[offset].drv_data) 44262306a36Sopenharmony_ci regmap_field_write(priv->overlays, BCM6368_BASEMODE_GPIO); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci return 0; 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic const struct pinctrl_ops bcm6368_pctl_ops = { 44862306a36Sopenharmony_ci .dt_free_map = pinctrl_utils_free_map, 44962306a36Sopenharmony_ci .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 45062306a36Sopenharmony_ci .get_group_name = bcm6368_pinctrl_get_group_name, 45162306a36Sopenharmony_ci .get_group_pins = bcm6368_pinctrl_get_group_pins, 45262306a36Sopenharmony_ci .get_groups_count = bcm6368_pinctrl_get_group_count, 45362306a36Sopenharmony_ci}; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic const struct pinmux_ops bcm6368_pmx_ops = { 45662306a36Sopenharmony_ci .get_function_groups = bcm6368_pinctrl_get_groups, 45762306a36Sopenharmony_ci .get_function_name = bcm6368_pinctrl_get_func_name, 45862306a36Sopenharmony_ci .get_functions_count = bcm6368_pinctrl_get_func_count, 45962306a36Sopenharmony_ci .gpio_request_enable = bcm6368_gpio_request_enable, 46062306a36Sopenharmony_ci .set_mux = bcm6368_pinctrl_set_mux, 46162306a36Sopenharmony_ci .strict = true, 46262306a36Sopenharmony_ci}; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic const struct bcm63xx_pinctrl_soc bcm6368_soc = { 46562306a36Sopenharmony_ci .ngpios = BCM6368_NUM_GPIOS, 46662306a36Sopenharmony_ci .npins = ARRAY_SIZE(bcm6368_pins), 46762306a36Sopenharmony_ci .pctl_ops = &bcm6368_pctl_ops, 46862306a36Sopenharmony_ci .pins = bcm6368_pins, 46962306a36Sopenharmony_ci .pmx_ops = &bcm6368_pmx_ops, 47062306a36Sopenharmony_ci}; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_cistatic int bcm6368_pinctrl_probe(struct platform_device *pdev) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci struct reg_field overlays = REG_FIELD(BCM6368_BASEMODE_REG, 0, 15); 47562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 47662306a36Sopenharmony_ci struct bcm63xx_pinctrl *pc; 47762306a36Sopenharmony_ci struct bcm6368_priv *priv; 47862306a36Sopenharmony_ci int err; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 48162306a36Sopenharmony_ci if (!priv) 48262306a36Sopenharmony_ci return -ENOMEM; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci err = bcm63xx_pinctrl_probe(pdev, &bcm6368_soc, (void *) priv); 48562306a36Sopenharmony_ci if (err) 48662306a36Sopenharmony_ci return err; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci pc = platform_get_drvdata(pdev); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci priv->overlays = devm_regmap_field_alloc(dev, pc->regs, overlays); 49162306a36Sopenharmony_ci if (IS_ERR(priv->overlays)) 49262306a36Sopenharmony_ci return PTR_ERR(priv->overlays); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic const struct of_device_id bcm6368_pinctrl_match[] = { 49862306a36Sopenharmony_ci { .compatible = "brcm,bcm6368-pinctrl", }, 49962306a36Sopenharmony_ci { /* sentinel */ } 50062306a36Sopenharmony_ci}; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic struct platform_driver bcm6368_pinctrl_driver = { 50362306a36Sopenharmony_ci .probe = bcm6368_pinctrl_probe, 50462306a36Sopenharmony_ci .driver = { 50562306a36Sopenharmony_ci .name = "bcm6368-pinctrl", 50662306a36Sopenharmony_ci .of_match_table = bcm6368_pinctrl_match, 50762306a36Sopenharmony_ci }, 50862306a36Sopenharmony_ci}; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cibuiltin_platform_driver(bcm6368_pinctrl_driver); 511