371 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			371 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0-or-later
 | |
| /*
 | |
|  * maxim-nca9539.c  --  I2C register interface access for nca9539 chip
 | |
|  *
 | |
|  * Copyright (c) 2023-2028 Rockchip Electronics Co., Ltd.
 | |
|  *
 | |
|  * Author: luowei <lw@rock-chips.com>
 | |
|  */
 | |
| 
 | |
| #include "../core.h"
 | |
| 
 | |
| #define REG_NCA9539_INPUT_PORT0 0x00 //Read only default 1111 1111
 | |
| #define REG_NCA9539_INPUT_PORT1 0x01 //Read only default 1111 1111
 | |
| #define REG_NCA9539_OUT_LEVEL_PORT0 0x02 //Read/write default 1111 1111
 | |
| #define REG_NCA9539_OUT_LEVEL_PORT1 0x03 //Read/write default 1111 1111
 | |
| #define REG_NCA9539_INVER_PORT0 0x04 //Read/write default 0000 0000
 | |
| #define REG_NCA9539_INVER_PORT1 0x05 //Read/write default 0000 0000
 | |
| #define REG_NCA9539_DIR_PORT0 0x06 //Read/write byte 1111 1111
 | |
| #define REG_NCA9539_DIR_PORT1 0x07 //Read/write byte 1111 1111
 | |
| 
 | |
| static bool nca9539_volatile_reg(struct device *dev, unsigned int reg)
 | |
| {
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| static struct regmap_config nca9539_regmap_config = {
 | |
| 	.name = "nca9539",
 | |
| 	.reg_bits = 8,
 | |
| 	.val_bits = 8,
 | |
| 	.max_register = 0x0007,
 | |
| 	.volatile_reg = nca9539_volatile_reg,
 | |
| 	.cache_type = REGCACHE_RBTREE,
 | |
| };
 | |
| 
 | |
| static int NCA9539_GPIO0_pins[] = {0};
 | |
| static int NCA9539_GPIO1_pins[] = {1};
 | |
| static int NCA9539_GPIO2_pins[] = {2};
 | |
| static int NCA9539_GPIO3_pins[] = {3};
 | |
| static int NCA9539_GPIO4_pins[] = {4};
 | |
| static int NCA9539_GPIO5_pins[] = {5};
 | |
| static int NCA9539_GPIO6_pins[] = {6};
 | |
| static int NCA9539_GPIO7_pins[] = {7};
 | |
| 
 | |
| static int NCA9539_GPIO8_pins[] = {8};
 | |
| static int NCA9539_GPIO9_pins[] = {9};
 | |
| static int NCA9539_GPIO10_pins[] = {10};
 | |
| static int NCA9539_GPIO11_pins[] = {11};
 | |
| static int NCA9539_GPIO12_pins[] = {12};
 | |
| static int NCA9539_GPIO13_pins[] = {13};
 | |
| static int NCA9539_GPIO14_pins[] = {14};
 | |
| static int NCA9539_GPIO15_pins[] = {15};
 | |
| 
 | |
| 
 | |
| #define GROUP_DESC(nm) \
 | |
| { \
 | |
| 	.name = #nm, \
 | |
| 	.pins = nm ## _pins, \
 | |
| 	.num_pins = ARRAY_SIZE(nm ## _pins), \
 | |
| }
 | |
| 
 | |
| static const char *serdes_gpio_groups[] = {
 | |
| 	"NCA9539_GPIO0", "NCA9539_GPIO1", "NCA9539_GPIO2", "NCA9539_GPIO3",
 | |
| 	"NCA9539_GPIO4", "NCA9539_GPIO5", "NCA9539_GPIO6", "NCA9539_GPIO7",
 | |
| 	"NCA9539_GPIO8", "NCA9539_GPIO9", "NCA9539_GPIO10", "NCA9539_GPIO11",
 | |
| 	"NCA9539_GPIO12", "NCA9539_GPIO13", "NCA9539_GPIO14", "NCA9539_GPIO15",
 | |
| };
 | |
| 
 | |
| /*des -> ser -> soc*/
 | |
| #define FUNCTION_DESC_GPIO_INPUT(id) \
 | |
| { \
 | |
| 	.name = "GPIO"#id"_INPUT", \
 | |
| 	.group_names = serdes_gpio_groups, \
 | |
| 	.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
 | |
| } \
 | |
| 
 | |
| /*soc -> ser -> des*/
 | |
| #define FUNCTION_DESC_GPIO_OUTPUT(id) \
 | |
| { \
 | |
| 	.name = "GPIO"#id"_OUTPUT", \
 | |
| 	.group_names = serdes_gpio_groups, \
 | |
| 	.num_group_names = ARRAY_SIZE(serdes_gpio_groups), \
 | |
| } \
 | |
| 
 | |
| 
 | |
| static struct pinctrl_pin_desc nca9539_pins_desc[] = {
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO0, "NCA9539_GPIO0"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO1, "NCA9539_GPIO1"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO2, "NCA9539_GPIO2"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO3, "NCA9539_GPIO3"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO4, "NCA9539_GPIO4"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO5, "NCA9539_GPIO5"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO6, "NCA9539_GPIO6"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO7, "NCA9539_GPIO7"),
 | |
| 
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO8, "NCA9539_GPIO8"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO9, "NCA9539_GPIO9"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO10, "NCA9539_GPIO10"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO11, "NCA9539_GPIO11"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO12, "NCA9539_GPIO12"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO13, "NCA9539_GPIO13"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO14, "NCA9539_GPIO14"),
 | |
| 	PINCTRL_PIN(NOVO_NCA9539_GPIO15, "NCA9539_GPIO15"),
 | |
| };
 | |
| 
 | |
| static struct group_desc nca9539_groups_desc[] = {
 | |
| 	GROUP_DESC(NCA9539_GPIO0),
 | |
| 	GROUP_DESC(NCA9539_GPIO1),
 | |
| 	GROUP_DESC(NCA9539_GPIO2),
 | |
| 	GROUP_DESC(NCA9539_GPIO3),
 | |
| 	GROUP_DESC(NCA9539_GPIO4),
 | |
| 	GROUP_DESC(NCA9539_GPIO5),
 | |
| 	GROUP_DESC(NCA9539_GPIO6),
 | |
| 	GROUP_DESC(NCA9539_GPIO7),
 | |
| 
 | |
| 	GROUP_DESC(NCA9539_GPIO8),
 | |
| 	GROUP_DESC(NCA9539_GPIO9),
 | |
| 	GROUP_DESC(NCA9539_GPIO10),
 | |
| 	GROUP_DESC(NCA9539_GPIO11),
 | |
| 	GROUP_DESC(NCA9539_GPIO12),
 | |
| 	GROUP_DESC(NCA9539_GPIO13),
 | |
| 	GROUP_DESC(NCA9539_GPIO14),
 | |
| 	GROUP_DESC(NCA9539_GPIO15),
 | |
| };
 | |
| 
 | |
| static struct function_desc nca9539_functions_desc[] = {
 | |
| 	FUNCTION_DESC_GPIO_INPUT(0),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(1),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(2),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(3),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(4),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(5),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(6),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(7),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(8),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(9),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(10),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(11),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(12),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(13),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(14),
 | |
| 	FUNCTION_DESC_GPIO_INPUT(15),
 | |
| 
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(0),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(1),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(2),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(3),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(4),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(5),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(6),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(7),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(8),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(9),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(10),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(11),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(12),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(13),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(14),
 | |
| 	FUNCTION_DESC_GPIO_OUTPUT(15),
 | |
| };
 | |
| 
 | |
| static struct serdes_chip_pinctrl_info nca9539_pinctrl_info = {
 | |
| 	.pins = nca9539_pins_desc,
 | |
| 	.num_pins = ARRAY_SIZE(nca9539_pins_desc),
 | |
| 	.groups = nca9539_groups_desc,
 | |
| 	.num_groups = ARRAY_SIZE(nca9539_groups_desc),
 | |
| 	.functions = nca9539_functions_desc,
 | |
| 	.num_functions = ARRAY_SIZE(nca9539_functions_desc),
 | |
| };
 | |
| 
 | |
| static int nca9539_pinctrl_config_get(struct serdes *serdes,
 | |
| 				      unsigned int pin, unsigned long *config)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_pinctrl_config_set(struct serdes *serdes,
 | |
| 				      unsigned int pin, unsigned long *configs,
 | |
| 				      unsigned int num_configs)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_pinctrl_set_mux(struct serdes *serdes,
 | |
| 				   unsigned int function, unsigned int group)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct serdes_chip_pinctrl_ops nca9539_pinctrl_ops = {
 | |
| 	.pin_config_get = nca9539_pinctrl_config_get,
 | |
| 	.pin_config_set = nca9539_pinctrl_config_set,
 | |
| 	.set_mux = nca9539_pinctrl_set_mux,
 | |
| };
 | |
| 
 | |
| static int nca9539_gpio_direction_input(struct serdes *serdes, int gpio)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_gpio_direction_output(struct serdes *serdes, int gpio, int value)
 | |
| {
 | |
| 	struct device *dev = serdes->dev;
 | |
| 	unsigned char port, pin, dir_reg, level_reg;
 | |
| 	int ret1 = 0, ret2 = 0;
 | |
| 
 | |
| 	port = (gpio / 8) & 0x01;
 | |
| 	pin = (gpio % 8) & 0x7;
 | |
| 	dir_reg = (port == 0) ? REG_NCA9539_DIR_PORT0 : REG_NCA9539_DIR_PORT1;
 | |
| 	level_reg = (port == 0) ? REG_NCA9539_OUT_LEVEL_PORT0 : REG_NCA9539_OUT_LEVEL_PORT1;
 | |
| 
 | |
| 	switch (pin) {
 | |
| 	case 0:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(0), FIELD_PREP(BIT(0), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(0), FIELD_PREP(BIT(0), value & 0x01));
 | |
| 		break;
 | |
| 	case 1:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(1), FIELD_PREP(BIT(1), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(1), FIELD_PREP(BIT(1), value & 0x01));
 | |
| 		break;
 | |
| 	case 2:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(2), FIELD_PREP(BIT(2), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(2), FIELD_PREP(BIT(2), value & 0x01));
 | |
| 		break;
 | |
| 	case 3:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(3), FIELD_PREP(BIT(3), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(3), FIELD_PREP(BIT(3), value & 0x01));
 | |
| 		break;
 | |
| 	case 4:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(4), FIELD_PREP(BIT(4), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(4), FIELD_PREP(BIT(4), value & 0x01));
 | |
| 		break;
 | |
| 	case 5:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(5), FIELD_PREP(BIT(5), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(5), FIELD_PREP(BIT(5), value & 0x01));
 | |
| 		break;
 | |
| 	case 6:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(6), FIELD_PREP(BIT(6), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(6), FIELD_PREP(BIT(6), value & 0x01));
 | |
| 		break;
 | |
| 	case 7:
 | |
| 		ret1 = serdes_set_bits(serdes, dir_reg, BIT(7), FIELD_PREP(BIT(7), 0));
 | |
| 		ret2 = serdes_set_bits(serdes, level_reg, BIT(7), FIELD_PREP(BIT(7), value & 0x01));
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	if (ret1 || ret2)
 | |
| 		dev_err(dev, "%s reg 0x%04x write error, pin=%d\n", __func__, level_reg, pin);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_gpio_get_level(struct serdes *serdes, int gpio)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_gpio_set_level(struct serdes *serdes, int gpio, int value)
 | |
| {
 | |
| 	struct device *dev = serdes->dev;
 | |
| 	unsigned char port, pin, level_reg;
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	port = (gpio / 8) & 0x01;
 | |
| 	pin = (gpio % 8) & 0x7;
 | |
| 	level_reg = (port == 0) ? REG_NCA9539_OUT_LEVEL_PORT0 : REG_NCA9539_OUT_LEVEL_PORT1;
 | |
| 
 | |
| 	switch (pin) {
 | |
| 	case 0:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(0), FIELD_PREP(BIT(0), value & 0x01));
 | |
| 		break;
 | |
| 	case 1:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(1), FIELD_PREP(BIT(1), value & 0x01));
 | |
| 		break;
 | |
| 	case 2:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(2), FIELD_PREP(BIT(2), value & 0x01));
 | |
| 		break;
 | |
| 	case 3:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(3), FIELD_PREP(BIT(3), value & 0x01));
 | |
| 		break;
 | |
| 	case 4:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(4), FIELD_PREP(BIT(4), value & 0x01));
 | |
| 		break;
 | |
| 	case 5:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(5), FIELD_PREP(BIT(5), value & 0x01));
 | |
| 		break;
 | |
| 	case 6:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(6), FIELD_PREP(BIT(6), value & 0x01));
 | |
| 		break;
 | |
| 	case 7:
 | |
| 		ret = serdes_set_bits(serdes, level_reg, BIT(7), FIELD_PREP(BIT(7), value & 0x01));
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	if (ret)
 | |
| 		dev_err(dev, "%s reg 0x%04x write error, pin=%d\n", __func__, level_reg, pin);
 | |
| 
 | |
| 	SERDES_DBG_CHIP("%s: serdes chip %s gpio=%d value=%d\n",
 | |
| 			__func__, serdes->chip_data->name, gpio, value);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_gpio_set_config(struct serdes *serdes, int gpio, unsigned long config)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_gpio_to_irq(struct serdes *serdes, int gpio)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct serdes_chip_gpio_ops nca9539_gpio_ops = {
 | |
| 	.direction_input = nca9539_gpio_direction_input,
 | |
| 	.direction_output = nca9539_gpio_direction_output,
 | |
| 	.get_level = nca9539_gpio_get_level,
 | |
| 	.set_level = nca9539_gpio_set_level,
 | |
| 	.set_config = nca9539_gpio_set_config,
 | |
| 	.to_irq = nca9539_gpio_to_irq,
 | |
| };
 | |
| 
 | |
| static int nca9539_pm_suspend(struct serdes *serdes)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int nca9539_pm_resume(struct serdes *serdes)
 | |
| {
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct serdes_chip_pm_ops nca9539_pm_ops = {
 | |
| 	.suspend = nca9539_pm_suspend,
 | |
| 	.resume = nca9539_pm_resume,
 | |
| };
 | |
| 
 | |
| static int nca9539_irq_lock_handle(struct serdes *serdes)
 | |
| {
 | |
| 	return IRQ_HANDLED;
 | |
| }
 | |
| 
 | |
| static int nca9539_irq_err_handle(struct serdes *serdes)
 | |
| {
 | |
| 	return IRQ_HANDLED;
 | |
| }
 | |
| 
 | |
| static struct serdes_chip_irq_ops nca9539_irq_ops = {
 | |
| 	.lock_handle = nca9539_irq_lock_handle,
 | |
| 	.err_handle = nca9539_irq_err_handle,
 | |
| };
 | |
| 
 | |
| struct serdes_chip_data serdes_nca9539_data = {
 | |
| 	.name		= "nca9539",
 | |
| 	.serdes_type	= TYPE_OTHER,
 | |
| 	.serdes_id	= NOVO_ID_NCA9539,
 | |
| 	.sequence_init = 1,
 | |
| 	.regmap_config	= &nca9539_regmap_config,
 | |
| 	.pinctrl_info	= &nca9539_pinctrl_info,
 | |
| 	.pinctrl_ops	= &nca9539_pinctrl_ops,
 | |
| 	.gpio_ops	= &nca9539_gpio_ops,
 | |
| 	.pm_ops		= &nca9539_pm_ops,
 | |
| 	.irq_ops	= &nca9539_irq_ops,
 | |
| };
 | |
| EXPORT_SYMBOL_GPL(serdes_nca9539_data);
 | |
| 
 | |
| MODULE_LICENSE("GPL");
 |