162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// CS42L43 Pinctrl and GPIO driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (c) 2023 Cirrus Logic, Inc. and 662306a36Sopenharmony_ci// Cirrus Logic International Semiconductor Ltd. 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bits.h> 962306a36Sopenharmony_ci#include <linux/build_bug.h> 1062306a36Sopenharmony_ci#include <linux/err.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1362306a36Sopenharmony_ci#include <linux/mfd/cs42l43.h> 1462306a36Sopenharmony_ci#include <linux/mfd/cs42l43-regs.h> 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/of.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1962306a36Sopenharmony_ci#include <linux/regmap.h> 2062306a36Sopenharmony_ci#include <linux/string_helpers.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h> 2362306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h> 2462306a36Sopenharmony_ci#include <linux/pinctrl/pinconf.h> 2562306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 2662306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include "../pinctrl-utils.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define CS42L43_NUM_GPIOS 3 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct cs42l43_pin { 3362306a36Sopenharmony_ci struct gpio_chip gpio_chip; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci struct device *dev; 3662306a36Sopenharmony_ci struct regmap *regmap; 3762306a36Sopenharmony_ci bool shutters_locked; 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct cs42l43_pin_data { 4162306a36Sopenharmony_ci unsigned int reg; 4262306a36Sopenharmony_ci unsigned int shift; 4362306a36Sopenharmony_ci unsigned int mask; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define CS42L43_PIN(_number, _name, _reg, _field) { \ 4762306a36Sopenharmony_ci .number = _number, .name = _name, \ 4862306a36Sopenharmony_ci .drv_data = &((struct cs42l43_pin_data){ \ 4962306a36Sopenharmony_ci .reg = CS42L43_##_reg, \ 5062306a36Sopenharmony_ci .shift = CS42L43_##_field##_DRV_SHIFT, \ 5162306a36Sopenharmony_ci .mask = CS42L43_##_field##_DRV_MASK, \ 5262306a36Sopenharmony_ci }), \ 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic const struct pinctrl_pin_desc cs42l43_pin_pins[] = { 5662306a36Sopenharmony_ci CS42L43_PIN(0, "gpio1", DRV_CTRL4, GPIO1), 5762306a36Sopenharmony_ci CS42L43_PIN(1, "gpio2", DRV_CTRL4, GPIO2), 5862306a36Sopenharmony_ci CS42L43_PIN(2, "gpio3", DRV_CTRL4, GPIO3), 5962306a36Sopenharmony_ci CS42L43_PIN(3, "asp_dout", DRV_CTRL1, ASP_DOUT), 6062306a36Sopenharmony_ci CS42L43_PIN(4, "asp_fsync", DRV_CTRL1, ASP_FSYNC), 6162306a36Sopenharmony_ci CS42L43_PIN(5, "asp_bclk", DRV_CTRL1, ASP_BCLK), 6262306a36Sopenharmony_ci CS42L43_PIN(6, "pdmout2_clk", DRV_CTRL3, PDMOUT2_CLK), 6362306a36Sopenharmony_ci CS42L43_PIN(7, "pdmout2_data", DRV_CTRL3, PDMOUT2_DATA), 6462306a36Sopenharmony_ci CS42L43_PIN(8, "pdmout1_clk", DRV_CTRL3, PDMOUT1_CLK), 6562306a36Sopenharmony_ci CS42L43_PIN(9, "pdmout1_data", DRV_CTRL3, PDMOUT1_DATA), 6662306a36Sopenharmony_ci CS42L43_PIN(10, "i2c_sda", DRV_CTRL3, I2C_SDA), 6762306a36Sopenharmony_ci CS42L43_PIN(11, "i2c_scl", DRV_CTRL_5, I2C_SCL), 6862306a36Sopenharmony_ci CS42L43_PIN(12, "spi_miso", DRV_CTRL3, SPI_MISO), 6962306a36Sopenharmony_ci CS42L43_PIN(13, "spi_sck", DRV_CTRL_5, SPI_SCK), 7062306a36Sopenharmony_ci CS42L43_PIN(14, "spi_ssb", DRV_CTRL_5, SPI_SSB), 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_gpio1_pins[] = { 0 }; 7462306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_gpio2_pins[] = { 1 }; 7562306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_gpio3_pins[] = { 2 }; 7662306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_asp_pins[] = { 3, 4, 5 }; 7762306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_pdmout2_pins[] = { 6, 7 }; 7862306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_pdmout1_pins[] = { 8, 9 }; 7962306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_i2c_pins[] = { 10, 11 }; 8062306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_spi_pins[] = { 12, 13, 14 }; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define CS42L43_PINGROUP(_name) \ 8362306a36Sopenharmony_ci PINCTRL_PINGROUP(#_name, cs42l43_pin_##_name##_pins, \ 8462306a36Sopenharmony_ci ARRAY_SIZE(cs42l43_pin_##_name##_pins)) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic const struct pingroup cs42l43_pin_groups[] = { 8762306a36Sopenharmony_ci CS42L43_PINGROUP(gpio1), 8862306a36Sopenharmony_ci CS42L43_PINGROUP(gpio2), 8962306a36Sopenharmony_ci CS42L43_PINGROUP(gpio3), 9062306a36Sopenharmony_ci CS42L43_PINGROUP(asp), 9162306a36Sopenharmony_ci CS42L43_PINGROUP(pdmout2), 9262306a36Sopenharmony_ci CS42L43_PINGROUP(pdmout1), 9362306a36Sopenharmony_ci CS42L43_PINGROUP(i2c), 9462306a36Sopenharmony_ci CS42L43_PINGROUP(spi), 9562306a36Sopenharmony_ci}; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic int cs42l43_pin_get_groups_count(struct pinctrl_dev *pctldev) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci return ARRAY_SIZE(cs42l43_pin_groups); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic const char *cs42l43_pin_get_group_name(struct pinctrl_dev *pctldev, 10362306a36Sopenharmony_ci unsigned int group_idx) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci return cs42l43_pin_groups[group_idx].name; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic int cs42l43_pin_get_group_pins(struct pinctrl_dev *pctldev, 10962306a36Sopenharmony_ci unsigned int group_idx, 11062306a36Sopenharmony_ci const unsigned int **pins, 11162306a36Sopenharmony_ci unsigned int *num_pins) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci *pins = cs42l43_pin_groups[group_idx].pins; 11462306a36Sopenharmony_ci *num_pins = cs42l43_pin_groups[group_idx].npins; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci return 0; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic const struct pinctrl_ops cs42l43_pin_group_ops = { 12062306a36Sopenharmony_ci .get_groups_count = cs42l43_pin_get_groups_count, 12162306a36Sopenharmony_ci .get_group_name = cs42l43_pin_get_group_name, 12262306a36Sopenharmony_ci .get_group_pins = cs42l43_pin_get_group_pins, 12362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_OF) 12462306a36Sopenharmony_ci .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 12562306a36Sopenharmony_ci .dt_free_map = pinconf_generic_dt_free_map, 12662306a36Sopenharmony_ci#endif 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cienum cs42l43_pin_funcs { 13062306a36Sopenharmony_ci CS42L43_FUNC_GPIO, 13162306a36Sopenharmony_ci CS42L43_FUNC_SPDIF, 13262306a36Sopenharmony_ci CS42L43_FUNC_IRQ, 13362306a36Sopenharmony_ci CS42L43_FUNC_MIC_SHT, 13462306a36Sopenharmony_ci CS42L43_FUNC_SPK_SHT, 13562306a36Sopenharmony_ci CS42L43_FUNC_MAX 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic const char * const cs42l43_pin_funcs[] = { 13962306a36Sopenharmony_ci "gpio", "spdif", "irq", "mic-shutter", "spk-shutter", 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic const char * const cs42l43_pin_gpio_groups[] = { "gpio1", "gpio3" }; 14362306a36Sopenharmony_cistatic const char * const cs42l43_pin_spdif_groups[] = { "gpio3" }; 14462306a36Sopenharmony_cistatic const char * const cs42l43_pin_irq_groups[] = { "gpio1" }; 14562306a36Sopenharmony_cistatic const char * const cs42l43_pin_shutter_groups[] = { "gpio1", "gpio2", "gpio3" }; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic const struct pinfunction cs42l43_pin_func_groups[] = { 14862306a36Sopenharmony_ci PINCTRL_PINFUNCTION("gpio", cs42l43_pin_gpio_groups, 14962306a36Sopenharmony_ci ARRAY_SIZE(cs42l43_pin_gpio_groups)), 15062306a36Sopenharmony_ci PINCTRL_PINFUNCTION("spdif", cs42l43_pin_spdif_groups, 15162306a36Sopenharmony_ci ARRAY_SIZE(cs42l43_pin_spdif_groups)), 15262306a36Sopenharmony_ci PINCTRL_PINFUNCTION("irq", cs42l43_pin_irq_groups, 15362306a36Sopenharmony_ci ARRAY_SIZE(cs42l43_pin_irq_groups)), 15462306a36Sopenharmony_ci PINCTRL_PINFUNCTION("mic-shutter", cs42l43_pin_shutter_groups, 15562306a36Sopenharmony_ci ARRAY_SIZE(cs42l43_pin_shutter_groups)), 15662306a36Sopenharmony_ci PINCTRL_PINFUNCTION("spk-shutter", cs42l43_pin_shutter_groups, 15762306a36Sopenharmony_ci ARRAY_SIZE(cs42l43_pin_shutter_groups)), 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic_assert(ARRAY_SIZE(cs42l43_pin_funcs) == CS42L43_FUNC_MAX); 16162306a36Sopenharmony_cistatic_assert(ARRAY_SIZE(cs42l43_pin_func_groups) == CS42L43_FUNC_MAX); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic int cs42l43_pin_get_func_count(struct pinctrl_dev *pctldev) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci return ARRAY_SIZE(cs42l43_pin_funcs); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic const char *cs42l43_pin_get_func_name(struct pinctrl_dev *pctldev, 16962306a36Sopenharmony_ci unsigned int func_idx) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci return cs42l43_pin_funcs[func_idx]; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic int cs42l43_pin_get_func_groups(struct pinctrl_dev *pctldev, 17562306a36Sopenharmony_ci unsigned int func_idx, 17662306a36Sopenharmony_ci const char * const **groups, 17762306a36Sopenharmony_ci unsigned int * const num_groups) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci *groups = cs42l43_pin_func_groups[func_idx].groups; 18062306a36Sopenharmony_ci *num_groups = cs42l43_pin_func_groups[func_idx].ngroups; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return 0; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic int cs42l43_pin_set_mux(struct pinctrl_dev *pctldev, 18662306a36Sopenharmony_ci unsigned int func_idx, unsigned int group_idx) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); 18962306a36Sopenharmony_ci unsigned int reg, mask, val; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci dev_dbg(priv->dev, "Setting %s to %s\n", 19262306a36Sopenharmony_ci cs42l43_pin_groups[group_idx].name, cs42l43_pin_funcs[func_idx]); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci switch (func_idx) { 19562306a36Sopenharmony_ci case CS42L43_FUNC_MIC_SHT: 19662306a36Sopenharmony_ci reg = CS42L43_SHUTTER_CONTROL; 19762306a36Sopenharmony_ci mask = CS42L43_MIC_SHUTTER_CFG_MASK; 19862306a36Sopenharmony_ci val = 0x2 << (group_idx + CS42L43_MIC_SHUTTER_CFG_SHIFT); 19962306a36Sopenharmony_ci break; 20062306a36Sopenharmony_ci case CS42L43_FUNC_SPK_SHT: 20162306a36Sopenharmony_ci reg = CS42L43_SHUTTER_CONTROL; 20262306a36Sopenharmony_ci mask = CS42L43_SPK_SHUTTER_CFG_MASK; 20362306a36Sopenharmony_ci val = 0x2 << (group_idx + CS42L43_SPK_SHUTTER_CFG_SHIFT); 20462306a36Sopenharmony_ci break; 20562306a36Sopenharmony_ci default: 20662306a36Sopenharmony_ci reg = CS42L43_GPIO_FN_SEL; 20762306a36Sopenharmony_ci mask = BIT(group_idx + CS42L43_GPIO1_FN_SEL_SHIFT); 20862306a36Sopenharmony_ci val = (func_idx == CS42L43_FUNC_GPIO) ? 20962306a36Sopenharmony_ci (0x1 << (group_idx + CS42L43_GPIO1_FN_SEL_SHIFT)) : 0; 21062306a36Sopenharmony_ci break; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (priv->shutters_locked && reg == CS42L43_SHUTTER_CONTROL) { 21462306a36Sopenharmony_ci dev_err(priv->dev, "Shutter configuration not available\n"); 21562306a36Sopenharmony_ci return -EPERM; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci return regmap_update_bits(priv->regmap, reg, mask, val); 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic int cs42l43_gpio_set_direction(struct pinctrl_dev *pctldev, 22262306a36Sopenharmony_ci struct pinctrl_gpio_range *range, 22362306a36Sopenharmony_ci unsigned int offset, bool input) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); 22662306a36Sopenharmony_ci unsigned int shift = offset + CS42L43_GPIO1_DIR_SHIFT; 22762306a36Sopenharmony_ci int ret; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci dev_dbg(priv->dev, "Setting gpio%d to %s\n", 23062306a36Sopenharmony_ci offset + 1, input ? "input" : "output"); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(priv->dev); 23362306a36Sopenharmony_ci if (ret) { 23462306a36Sopenharmony_ci dev_err(priv->dev, "Failed to resume for direction: %d\n", ret); 23562306a36Sopenharmony_ci return ret; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1, 23962306a36Sopenharmony_ci BIT(shift), !!input << shift); 24062306a36Sopenharmony_ci if (ret) 24162306a36Sopenharmony_ci dev_err(priv->dev, "Failed to set gpio%d direction: %d\n", 24262306a36Sopenharmony_ci offset + 1, ret); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci pm_runtime_put(priv->dev); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return ret; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic int cs42l43_gpio_request_enable(struct pinctrl_dev *pctldev, 25062306a36Sopenharmony_ci struct pinctrl_gpio_range *range, 25162306a36Sopenharmony_ci unsigned int offset) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci return cs42l43_pin_set_mux(pctldev, 0, offset); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic void cs42l43_gpio_disable_free(struct pinctrl_dev *pctldev, 25762306a36Sopenharmony_ci struct pinctrl_gpio_range *range, 25862306a36Sopenharmony_ci unsigned int offset) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci cs42l43_gpio_set_direction(pctldev, range, offset, true); 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic const struct pinmux_ops cs42l43_pin_mux_ops = { 26462306a36Sopenharmony_ci .get_functions_count = cs42l43_pin_get_func_count, 26562306a36Sopenharmony_ci .get_function_name = cs42l43_pin_get_func_name, 26662306a36Sopenharmony_ci .get_function_groups = cs42l43_pin_get_func_groups, 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci .set_mux = cs42l43_pin_set_mux, 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci .gpio_request_enable = cs42l43_gpio_request_enable, 27162306a36Sopenharmony_ci .gpio_disable_free = cs42l43_gpio_disable_free, 27262306a36Sopenharmony_ci .gpio_set_direction = cs42l43_gpio_set_direction, 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci .strict = true, 27562306a36Sopenharmony_ci}; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic const unsigned int cs42l43_pin_drv_str_ma[] = { 1, 2, 4, 8, 9, 10, 12, 16 }; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic inline int cs42l43_pin_get_drv_str(struct cs42l43_pin *priv, unsigned int pin) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data; 28262306a36Sopenharmony_ci unsigned int val; 28362306a36Sopenharmony_ci int ret; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci ret = regmap_read(priv->regmap, pdat->reg, &val); 28662306a36Sopenharmony_ci if (ret) 28762306a36Sopenharmony_ci return ret; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci return cs42l43_pin_drv_str_ma[(val & pdat->mask) >> pdat->shift]; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic inline int cs42l43_pin_set_drv_str(struct cs42l43_pin *priv, unsigned int pin, 29362306a36Sopenharmony_ci unsigned int ma) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data; 29662306a36Sopenharmony_ci int i; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cs42l43_pin_drv_str_ma); i++) { 29962306a36Sopenharmony_ci if (ma == cs42l43_pin_drv_str_ma[i]) { 30062306a36Sopenharmony_ci if ((i << pdat->shift) > pdat->mask) 30162306a36Sopenharmony_ci goto err; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci dev_dbg(priv->dev, "Set drive strength for %s to %d mA\n", 30462306a36Sopenharmony_ci cs42l43_pin_pins[pin].name, ma); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci return regmap_update_bits(priv->regmap, pdat->reg, 30762306a36Sopenharmony_ci pdat->mask, i << pdat->shift); 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cierr: 31262306a36Sopenharmony_ci dev_err(priv->dev, "Invalid drive strength for %s: %d mA\n", 31362306a36Sopenharmony_ci cs42l43_pin_pins[pin].name, ma); 31462306a36Sopenharmony_ci return -EINVAL; 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic inline int cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci unsigned int val; 32062306a36Sopenharmony_ci int ret; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (pin >= CS42L43_NUM_GPIOS) 32362306a36Sopenharmony_ci return -ENOTSUPP; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci ret = regmap_read(priv->regmap, CS42L43_GPIO_CTRL2, &val); 32662306a36Sopenharmony_ci if (ret) 32762306a36Sopenharmony_ci return ret; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (val & (CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin)) 33062306a36Sopenharmony_ci return 0; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci return 85; // Debounce is roughly 85uS 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic inline int cs42l43_pin_set_db(struct cs42l43_pin *priv, unsigned int pin, 33662306a36Sopenharmony_ci unsigned int us) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci if (pin >= CS42L43_NUM_GPIOS) 33962306a36Sopenharmony_ci return -ENOTSUPP; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci dev_dbg(priv->dev, "Set debounce %s for %s\n", 34262306a36Sopenharmony_ci str_on_off(us), cs42l43_pin_pins[pin].name); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci return regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL2, 34562306a36Sopenharmony_ci CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin, 34662306a36Sopenharmony_ci !!us << pin); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic int cs42l43_pin_config_get(struct pinctrl_dev *pctldev, 35062306a36Sopenharmony_ci unsigned int pin, unsigned long *config) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); 35362306a36Sopenharmony_ci unsigned int param = pinconf_to_config_param(*config); 35462306a36Sopenharmony_ci int ret; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci switch (param) { 35762306a36Sopenharmony_ci case PIN_CONFIG_DRIVE_STRENGTH: 35862306a36Sopenharmony_ci ret = cs42l43_pin_get_drv_str(priv, pin); 35962306a36Sopenharmony_ci if (ret < 0) 36062306a36Sopenharmony_ci return ret; 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci case PIN_CONFIG_INPUT_DEBOUNCE: 36362306a36Sopenharmony_ci ret = cs42l43_pin_get_db(priv, pin); 36462306a36Sopenharmony_ci if (ret < 0) 36562306a36Sopenharmony_ci return ret; 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci default: 36862306a36Sopenharmony_ci return -ENOTSUPP; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci *config = pinconf_to_config_packed(param, ret); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci return 0; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic int cs42l43_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, 37762306a36Sopenharmony_ci unsigned long *configs, unsigned int num_configs) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); 38062306a36Sopenharmony_ci unsigned int val; 38162306a36Sopenharmony_ci int ret; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci while (num_configs) { 38462306a36Sopenharmony_ci val = pinconf_to_config_argument(*configs); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci switch (pinconf_to_config_param(*configs)) { 38762306a36Sopenharmony_ci case PIN_CONFIG_DRIVE_STRENGTH: 38862306a36Sopenharmony_ci ret = cs42l43_pin_set_drv_str(priv, pin, val); 38962306a36Sopenharmony_ci if (ret) 39062306a36Sopenharmony_ci return ret; 39162306a36Sopenharmony_ci break; 39262306a36Sopenharmony_ci case PIN_CONFIG_INPUT_DEBOUNCE: 39362306a36Sopenharmony_ci ret = cs42l43_pin_set_db(priv, pin, val); 39462306a36Sopenharmony_ci if (ret) 39562306a36Sopenharmony_ci return ret; 39662306a36Sopenharmony_ci break; 39762306a36Sopenharmony_ci default: 39862306a36Sopenharmony_ci return -ENOTSUPP; 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci configs++; 40262306a36Sopenharmony_ci num_configs--; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic int cs42l43_pin_config_group_get(struct pinctrl_dev *pctldev, 40962306a36Sopenharmony_ci unsigned int selector, unsigned long *config) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci int i, ret; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) { 41462306a36Sopenharmony_ci ret = cs42l43_pin_config_get(pctldev, 41562306a36Sopenharmony_ci cs42l43_pin_groups[selector].pins[i], 41662306a36Sopenharmony_ci config); 41762306a36Sopenharmony_ci if (ret) 41862306a36Sopenharmony_ci return ret; 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci return 0; 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_cistatic int cs42l43_pin_config_group_set(struct pinctrl_dev *pctldev, 42562306a36Sopenharmony_ci unsigned int selector, 42662306a36Sopenharmony_ci unsigned long *configs, 42762306a36Sopenharmony_ci unsigned int num_configs) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci int i, ret; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) { 43262306a36Sopenharmony_ci ret = cs42l43_pin_config_set(pctldev, 43362306a36Sopenharmony_ci cs42l43_pin_groups[selector].pins[i], 43462306a36Sopenharmony_ci configs, num_configs); 43562306a36Sopenharmony_ci if (ret) 43662306a36Sopenharmony_ci return ret; 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci return 0; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic const struct pinconf_ops cs42l43_pin_conf_ops = { 44362306a36Sopenharmony_ci .is_generic = true, 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci .pin_config_get = cs42l43_pin_config_get, 44662306a36Sopenharmony_ci .pin_config_set = cs42l43_pin_config_set, 44762306a36Sopenharmony_ci .pin_config_group_get = cs42l43_pin_config_group_get, 44862306a36Sopenharmony_ci .pin_config_group_set = cs42l43_pin_config_group_set, 44962306a36Sopenharmony_ci}; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic struct pinctrl_desc cs42l43_pin_desc = { 45262306a36Sopenharmony_ci .name = "cs42l43-pinctrl", 45362306a36Sopenharmony_ci .owner = THIS_MODULE, 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci .pins = cs42l43_pin_pins, 45662306a36Sopenharmony_ci .npins = ARRAY_SIZE(cs42l43_pin_pins), 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci .pctlops = &cs42l43_pin_group_ops, 45962306a36Sopenharmony_ci .pmxops = &cs42l43_pin_mux_ops, 46062306a36Sopenharmony_ci .confops = &cs42l43_pin_conf_ops, 46162306a36Sopenharmony_ci}; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic int cs42l43_gpio_get(struct gpio_chip *chip, unsigned int offset) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci struct cs42l43_pin *priv = gpiochip_get_data(chip); 46662306a36Sopenharmony_ci unsigned int val; 46762306a36Sopenharmony_ci int ret; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(priv->dev); 47062306a36Sopenharmony_ci if (ret) { 47162306a36Sopenharmony_ci dev_err(priv->dev, "Failed to resume for get: %d\n", ret); 47262306a36Sopenharmony_ci return ret; 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci ret = regmap_read(priv->regmap, CS42L43_GPIO_STS, &val); 47662306a36Sopenharmony_ci if (ret) 47762306a36Sopenharmony_ci dev_err(priv->dev, "Failed to get gpio%d: %d\n", offset + 1, ret); 47862306a36Sopenharmony_ci else 47962306a36Sopenharmony_ci ret = !!(val & BIT(offset + CS42L43_GPIO1_STS_SHIFT)); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci pm_runtime_put(priv->dev); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return ret; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic void cs42l43_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct cs42l43_pin *priv = gpiochip_get_data(chip); 48962306a36Sopenharmony_ci unsigned int shift = offset + CS42L43_GPIO1_LVL_SHIFT; 49062306a36Sopenharmony_ci int ret; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci dev_dbg(priv->dev, "Setting gpio%d to %s\n", 49362306a36Sopenharmony_ci offset + 1, value ? "high" : "low"); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(priv->dev); 49662306a36Sopenharmony_ci if (ret) { 49762306a36Sopenharmony_ci dev_err(priv->dev, "Failed to resume for set: %d\n", ret); 49862306a36Sopenharmony_ci return; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1, 50262306a36Sopenharmony_ci BIT(shift), value << shift); 50362306a36Sopenharmony_ci if (ret) 50462306a36Sopenharmony_ci dev_err(priv->dev, "Failed to set gpio%d: %d\n", offset + 1, ret); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci pm_runtime_put(priv->dev); 50762306a36Sopenharmony_ci} 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_cistatic int cs42l43_gpio_direction_in(struct gpio_chip *chip, unsigned int offset) 51062306a36Sopenharmony_ci{ 51162306a36Sopenharmony_ci return pinctrl_gpio_direction_input(chip->base + offset); 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic int cs42l43_gpio_direction_out(struct gpio_chip *chip, 51562306a36Sopenharmony_ci unsigned int offset, int value) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci cs42l43_gpio_set(chip, offset, value); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci return pinctrl_gpio_direction_output(chip->base + offset); 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_cistatic int cs42l43_gpio_add_pin_ranges(struct gpio_chip *chip) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci struct cs42l43_pin *priv = gpiochip_get_data(chip); 52562306a36Sopenharmony_ci int ret; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci ret = gpiochip_add_pin_range(&priv->gpio_chip, priv->gpio_chip.label, 52862306a36Sopenharmony_ci 0, 0, CS42L43_NUM_GPIOS); 52962306a36Sopenharmony_ci if (ret) 53062306a36Sopenharmony_ci dev_err(priv->dev, "Failed to add GPIO pin range: %d\n", ret); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci return ret; 53362306a36Sopenharmony_ci} 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_cistatic int cs42l43_pin_probe(struct platform_device *pdev) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent); 53862306a36Sopenharmony_ci struct cs42l43_pin *priv; 53962306a36Sopenharmony_ci struct pinctrl_dev *pctldev; 54062306a36Sopenharmony_ci struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev); 54162306a36Sopenharmony_ci int ret; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 54462306a36Sopenharmony_ci if (!priv) 54562306a36Sopenharmony_ci return -ENOMEM; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci priv->dev = &pdev->dev; 54862306a36Sopenharmony_ci priv->regmap = cs42l43->regmap; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci priv->shutters_locked = cs42l43->hw_lock; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci priv->gpio_chip.request = gpiochip_generic_request; 55362306a36Sopenharmony_ci priv->gpio_chip.free = gpiochip_generic_free; 55462306a36Sopenharmony_ci priv->gpio_chip.direction_input = cs42l43_gpio_direction_in; 55562306a36Sopenharmony_ci priv->gpio_chip.direction_output = cs42l43_gpio_direction_out; 55662306a36Sopenharmony_ci priv->gpio_chip.add_pin_ranges = cs42l43_gpio_add_pin_ranges; 55762306a36Sopenharmony_ci priv->gpio_chip.get = cs42l43_gpio_get; 55862306a36Sopenharmony_ci priv->gpio_chip.set = cs42l43_gpio_set; 55962306a36Sopenharmony_ci priv->gpio_chip.label = dev_name(priv->dev); 56062306a36Sopenharmony_ci priv->gpio_chip.parent = priv->dev; 56162306a36Sopenharmony_ci priv->gpio_chip.can_sleep = true; 56262306a36Sopenharmony_ci priv->gpio_chip.base = -1; 56362306a36Sopenharmony_ci priv->gpio_chip.ngpio = CS42L43_NUM_GPIOS; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (is_of_node(fwnode)) { 56662306a36Sopenharmony_ci fwnode = fwnode_get_named_child_node(fwnode, "pinctrl"); 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci if (fwnode && !fwnode->dev) 56962306a36Sopenharmony_ci fwnode->dev = priv->dev; 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci priv->gpio_chip.fwnode = fwnode; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci device_set_node(priv->dev, fwnode); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci devm_pm_runtime_enable(priv->dev); 57762306a36Sopenharmony_ci pm_runtime_idle(priv->dev); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci pctldev = devm_pinctrl_register(priv->dev, &cs42l43_pin_desc, priv); 58062306a36Sopenharmony_ci if (IS_ERR(pctldev)) 58162306a36Sopenharmony_ci return dev_err_probe(priv->dev, PTR_ERR(pctldev), 58262306a36Sopenharmony_ci "Failed to register pinctrl\n"); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci ret = devm_gpiochip_add_data(priv->dev, &priv->gpio_chip, priv); 58562306a36Sopenharmony_ci if (ret) 58662306a36Sopenharmony_ci return dev_err_probe(priv->dev, ret, 58762306a36Sopenharmony_ci "Failed to register gpiochip\n"); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci return 0; 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic const struct platform_device_id cs42l43_pin_id_table[] = { 59362306a36Sopenharmony_ci { "cs42l43-pinctrl", }, 59462306a36Sopenharmony_ci {} 59562306a36Sopenharmony_ci}; 59662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, cs42l43_pin_id_table); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic struct platform_driver cs42l43_pin_driver = { 59962306a36Sopenharmony_ci .driver = { 60062306a36Sopenharmony_ci .name = "cs42l43-pinctrl", 60162306a36Sopenharmony_ci }, 60262306a36Sopenharmony_ci .probe = cs42l43_pin_probe, 60362306a36Sopenharmony_ci .id_table = cs42l43_pin_id_table, 60462306a36Sopenharmony_ci}; 60562306a36Sopenharmony_cimodule_platform_driver(cs42l43_pin_driver); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ciMODULE_DESCRIPTION("CS42L43 Pinctrl Driver"); 60862306a36Sopenharmony_ciMODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>"); 60962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 610