1*5e302106SRichard Acayan // SPDX-License-Identifier: GPL-2.0-only 2*5e302106SRichard Acayan /* 3*5e302106SRichard Acayan * This driver is solely based on the limited information in downstream code. 4*5e302106SRichard Acayan * Any verification with schematics would be greatly appreciated. 5*5e302106SRichard Acayan * 6*5e302106SRichard Acayan * Copyright (c) 2023, Richard Acayan. All rights reserved. 7*5e302106SRichard Acayan */ 8*5e302106SRichard Acayan 9*5e302106SRichard Acayan #include <linux/kernel.h> 10*5e302106SRichard Acayan #include <linux/module.h> 11*5e302106SRichard Acayan #include <linux/of.h> 12*5e302106SRichard Acayan #include <linux/platform_device.h> 13*5e302106SRichard Acayan #include <linux/pinctrl/pinctrl.h> 14*5e302106SRichard Acayan 15*5e302106SRichard Acayan #include "pinctrl-lpass-lpi.h" 16*5e302106SRichard Acayan 17*5e302106SRichard Acayan enum lpass_lpi_functions { 18*5e302106SRichard Acayan LPI_MUX_comp_rx, 19*5e302106SRichard Acayan LPI_MUX_dmic1_clk, 20*5e302106SRichard Acayan LPI_MUX_dmic1_data, 21*5e302106SRichard Acayan LPI_MUX_dmic2_clk, 22*5e302106SRichard Acayan LPI_MUX_dmic2_data, 23*5e302106SRichard Acayan LPI_MUX_mclk0, 24*5e302106SRichard Acayan LPI_MUX_pdm_tx, 25*5e302106SRichard Acayan LPI_MUX_pdm_clk, 26*5e302106SRichard Acayan LPI_MUX_pdm_rx, 27*5e302106SRichard Acayan LPI_MUX_pdm_sync, 28*5e302106SRichard Acayan 29*5e302106SRichard Acayan LPI_MUX_gpio, 30*5e302106SRichard Acayan LPI_MUX__, 31*5e302106SRichard Acayan }; 32*5e302106SRichard Acayan 33*5e302106SRichard Acayan static const struct pinctrl_pin_desc sdm660_lpi_pinctrl_pins[] = { 34*5e302106SRichard Acayan PINCTRL_PIN(0, "gpio0"), 35*5e302106SRichard Acayan PINCTRL_PIN(1, "gpio1"), 36*5e302106SRichard Acayan PINCTRL_PIN(2, "gpio2"), 37*5e302106SRichard Acayan PINCTRL_PIN(3, "gpio3"), 38*5e302106SRichard Acayan PINCTRL_PIN(4, "gpio4"), 39*5e302106SRichard Acayan PINCTRL_PIN(5, "gpio5"), 40*5e302106SRichard Acayan PINCTRL_PIN(6, "gpio6"), 41*5e302106SRichard Acayan PINCTRL_PIN(7, "gpio7"), 42*5e302106SRichard Acayan PINCTRL_PIN(8, "gpio8"), 43*5e302106SRichard Acayan PINCTRL_PIN(9, "gpio9"), 44*5e302106SRichard Acayan PINCTRL_PIN(10, "gpio10"), 45*5e302106SRichard Acayan PINCTRL_PIN(11, "gpio11"), 46*5e302106SRichard Acayan PINCTRL_PIN(12, "gpio12"), 47*5e302106SRichard Acayan PINCTRL_PIN(13, "gpio13"), 48*5e302106SRichard Acayan PINCTRL_PIN(14, "gpio14"), 49*5e302106SRichard Acayan PINCTRL_PIN(15, "gpio15"), 50*5e302106SRichard Acayan PINCTRL_PIN(16, "gpio16"), 51*5e302106SRichard Acayan PINCTRL_PIN(17, "gpio17"), 52*5e302106SRichard Acayan PINCTRL_PIN(18, "gpio18"), 53*5e302106SRichard Acayan PINCTRL_PIN(19, "gpio19"), 54*5e302106SRichard Acayan PINCTRL_PIN(20, "gpio20"), 55*5e302106SRichard Acayan PINCTRL_PIN(21, "gpio21"), 56*5e302106SRichard Acayan PINCTRL_PIN(22, "gpio22"), 57*5e302106SRichard Acayan PINCTRL_PIN(23, "gpio23"), 58*5e302106SRichard Acayan PINCTRL_PIN(24, "gpio24"), 59*5e302106SRichard Acayan PINCTRL_PIN(25, "gpio25"), 60*5e302106SRichard Acayan PINCTRL_PIN(26, "gpio26"), 61*5e302106SRichard Acayan PINCTRL_PIN(27, "gpio27"), 62*5e302106SRichard Acayan PINCTRL_PIN(28, "gpio28"), 63*5e302106SRichard Acayan PINCTRL_PIN(29, "gpio29"), 64*5e302106SRichard Acayan PINCTRL_PIN(30, "gpio30"), 65*5e302106SRichard Acayan PINCTRL_PIN(31, "gpio31"), 66*5e302106SRichard Acayan }; 67*5e302106SRichard Acayan 68*5e302106SRichard Acayan static const char * const comp_rx_groups[] = { "gpio22", "gpio24" }; 69*5e302106SRichard Acayan static const char * const dmic1_clk_groups[] = { "gpio26" }; 70*5e302106SRichard Acayan static const char * const dmic1_data_groups[] = { "gpio27" }; 71*5e302106SRichard Acayan static const char * const dmic2_clk_groups[] = { "gpio28" }; 72*5e302106SRichard Acayan static const char * const dmic2_data_groups[] = { "gpio29" }; 73*5e302106SRichard Acayan static const char * const mclk0_groups[] = { "gpio18" }; 74*5e302106SRichard Acayan static const char * const pdm_tx_groups[] = { "gpio20" }; 75*5e302106SRichard Acayan static const char * const pdm_clk_groups[] = { "gpio18" }; 76*5e302106SRichard Acayan static const char * const pdm_rx_groups[] = { "gpio21", "gpio23", "gpio25" }; 77*5e302106SRichard Acayan static const char * const pdm_sync_groups[] = { "gpio19" }; 78*5e302106SRichard Acayan 79*5e302106SRichard Acayan const struct lpi_pingroup sdm660_lpi_pinctrl_groups[] = { 80*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(0, LPI_NO_SLEW, _, _, _, _, 0x0000), 81*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(1, LPI_NO_SLEW, _, _, _, _, 0x1000), 82*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(2, LPI_NO_SLEW, _, _, _, _, 0x2000), 83*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(3, LPI_NO_SLEW, _, _, _, _, 0x2010), 84*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(4, LPI_NO_SLEW, _, _, _, _, 0x3000), 85*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(5, LPI_NO_SLEW, _, _, _, _, 0x3010), 86*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(6, LPI_NO_SLEW, _, _, _, _, 0x4000), 87*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(7, LPI_NO_SLEW, _, _, _, _, 0x4010), 88*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(8, LPI_NO_SLEW, _, _, _, _, 0x5000), 89*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(9, LPI_NO_SLEW, _, _, _, _, 0x5010), 90*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(10, LPI_NO_SLEW, _, _, _, _, 0x5020), 91*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(11, LPI_NO_SLEW, _, _, _, _, 0x5030), 92*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(12, LPI_NO_SLEW, _, _, _, _, 0x6000), 93*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(13, LPI_NO_SLEW, _, _, _, _, 0x6010), 94*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(14, LPI_NO_SLEW, _, _, _, _, 0x7000), 95*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(15, LPI_NO_SLEW, _, _, _, _, 0x7010), 96*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(16, LPI_NO_SLEW, _, _, _, _, 0x5040), 97*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(17, LPI_NO_SLEW, _, _, _, _, 0x5050), 98*5e302106SRichard Acayan 99*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(18, LPI_NO_SLEW, pdm_clk, mclk0, _, _, 0x8000), 100*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(19, LPI_NO_SLEW, pdm_sync, _, _, _, 0x8010), 101*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(20, LPI_NO_SLEW, pdm_tx, _, _, _, 0x8020), 102*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(21, LPI_NO_SLEW, pdm_rx, _, _, _, 0x8030), 103*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(22, LPI_NO_SLEW, comp_rx, _, _, _, 0x8040), 104*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(23, LPI_NO_SLEW, pdm_rx, _, _, _, 0x8050), 105*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(24, LPI_NO_SLEW, comp_rx, _, _, _, 0x8060), 106*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(25, LPI_NO_SLEW, pdm_rx, _, _, _, 0x8070), 107*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(26, LPI_NO_SLEW, dmic1_clk, _, _, _, 0x9000), 108*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(27, LPI_NO_SLEW, dmic1_data, _, _, _, 0x9010), 109*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(28, LPI_NO_SLEW, dmic2_clk, _, _, _, 0xa000), 110*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(29, LPI_NO_SLEW, dmic2_data, _, _, _, 0xa010), 111*5e302106SRichard Acayan 112*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(30, LPI_NO_SLEW, _, _, _, _, 0xb000), 113*5e302106SRichard Acayan LPI_PINGROUP_OFFSET(31, LPI_NO_SLEW, _, _, _, _, 0xb010), 114*5e302106SRichard Acayan }; 115*5e302106SRichard Acayan 116*5e302106SRichard Acayan const struct lpi_function sdm660_lpi_pinctrl_functions[] = { 117*5e302106SRichard Acayan LPI_FUNCTION(comp_rx), 118*5e302106SRichard Acayan LPI_FUNCTION(dmic1_clk), 119*5e302106SRichard Acayan LPI_FUNCTION(dmic1_data), 120*5e302106SRichard Acayan LPI_FUNCTION(dmic2_clk), 121*5e302106SRichard Acayan LPI_FUNCTION(dmic2_data), 122*5e302106SRichard Acayan LPI_FUNCTION(mclk0), 123*5e302106SRichard Acayan LPI_FUNCTION(pdm_tx), 124*5e302106SRichard Acayan LPI_FUNCTION(pdm_clk), 125*5e302106SRichard Acayan LPI_FUNCTION(pdm_rx), 126*5e302106SRichard Acayan LPI_FUNCTION(pdm_sync), 127*5e302106SRichard Acayan }; 128*5e302106SRichard Acayan 129*5e302106SRichard Acayan static const struct lpi_pinctrl_variant_data sdm660_lpi_pinctrl_data = { 130*5e302106SRichard Acayan .pins = sdm660_lpi_pinctrl_pins, 131*5e302106SRichard Acayan .npins = ARRAY_SIZE(sdm660_lpi_pinctrl_pins), 132*5e302106SRichard Acayan .groups = sdm660_lpi_pinctrl_groups, 133*5e302106SRichard Acayan .ngroups = ARRAY_SIZE(sdm660_lpi_pinctrl_groups), 134*5e302106SRichard Acayan .functions = sdm660_lpi_pinctrl_functions, 135*5e302106SRichard Acayan .nfunctions = ARRAY_SIZE(sdm660_lpi_pinctrl_functions), 136*5e302106SRichard Acayan .flags = LPI_FLAG_SLEW_RATE_SAME_REG | LPI_FLAG_USE_PREDEFINED_PIN_OFFSET 137*5e302106SRichard Acayan }; 138*5e302106SRichard Acayan 139*5e302106SRichard Acayan static const struct of_device_id sdm660_lpi_pinctrl_of_match[] = { 140*5e302106SRichard Acayan { 141*5e302106SRichard Acayan .compatible = "qcom,sdm660-lpass-lpi-pinctrl", 142*5e302106SRichard Acayan .data = &sdm660_lpi_pinctrl_data, 143*5e302106SRichard Acayan }, 144*5e302106SRichard Acayan { } 145*5e302106SRichard Acayan }; 146*5e302106SRichard Acayan MODULE_DEVICE_TABLE(of, sdm660_lpi_pinctrl_of_match); 147*5e302106SRichard Acayan 148*5e302106SRichard Acayan static struct platform_driver sdm660_lpi_pinctrl_driver = { 149*5e302106SRichard Acayan .driver = { 150*5e302106SRichard Acayan .name = "qcom-sdm660-lpass-lpi-pinctrl", 151*5e302106SRichard Acayan .of_match_table = sdm660_lpi_pinctrl_of_match, 152*5e302106SRichard Acayan }, 153*5e302106SRichard Acayan .probe = lpi_pinctrl_probe, 154*5e302106SRichard Acayan .remove = lpi_pinctrl_remove, 155*5e302106SRichard Acayan }; 156*5e302106SRichard Acayan module_platform_driver(sdm660_lpi_pinctrl_driver); 157*5e302106SRichard Acayan 158*5e302106SRichard Acayan MODULE_AUTHOR("Richard Acayan <mailingradian@gmail.com>"); 159*5e302106SRichard Acayan MODULE_DESCRIPTION("QTI SDM660 LPI GPIO pin control driver"); 160*5e302106SRichard Acayan MODULE_LICENSE("GPL"); 161