// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
/*
* Copyright (c) 2024 Amlogic, Inc. All rights reserved.
* Author: Xianwei Zhao <xianwei.zhao@amlogic.com>
*/
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <dt-bindings/pinctrl/amlogic,pinctrl.h>
#include "../core.h"
#include "../pinctrl-utils.h"
#include "../pinconf.h"
#define gpio_chip_to_bank(chip) \
container_of(chip, struct aml_gpio_bank, gpio_chip)
#define AML_REG_PULLEN 0
#define AML_REG_PULL 1
#define AML_REG_DIR 2
#define AML_REG_OUT 3
#define AML_REG_IN 4
#define AML_REG_DS 5
#define AML_NUM_REG 6
enum aml_pinconf_drv {
PINCONF_DRV_500UA,
PINCONF_DRV_2500UA,
PINCONF_DRV_3000UA,
PINCONF_DRV_4000UA,
};
struct aml_pio_control {
u32 gpio_offset;
u32 reg_offset[AML_NUM_REG];
u32 bit_offset[AML_NUM_REG];
};
/*
* partial bank(subordinate) pins mux config use other bank(main) mux registgers
* m_bank_id: the main bank which pin_id from 0, but register bit not from bit 0
* m_bit_offs: bit offset the main bank mux register
* sid: start pin_id of subordinate bank
* eid: end pin_id of subordinate bank
*/
struct multi_mux {
unsigned int m_bank_id;
unsigned int m_bit_offs;
unsigned int sid;
unsigned int eid;
};
struct aml_pctl_data {
unsigned int number;
const struct multi_mux *p_mux;
};
struct aml_pmx_func {
const char *name;
const char **groups;
unsigned int ngroups;
};
struct aml_pctl_group {
const char *name;
unsigned int npins;
unsigned int *pins;
unsigned int *func;
};
struct aml_gpio_bank {
struct gpio_chip gpio_chip;
struct aml_pio_control pc;
u32 bank_id;
u32 mux_bit_offs;
unsigned int pin_base;
struct regmap *reg_mux;
struct regmap *reg_gpio;
struct regmap *reg_ds;
const struct multi_mux *p_mux;
};
struct aml_pinctrl {
struct device *dev;
struct pinctrl_dev *pctl;
struct aml_gpio_bank *banks;
int nbanks;
struct aml_pmx_func *functions;
int nfunctions;
struct aml_pctl_group *groups;
int ngroups;
const struct aml_pctl_data *data;
};
static const unsigned int aml_bit_strides[AML_NUM_REG] = {
1, 1, 1, 1, 1, 2
};
static const unsigned int aml_def_regoffs[AML_NUM_REG] = {
3, 4, 2, 1, 0, 7
};
static const char *aml_bank_name[31] = {
"GPIOA", "GPIOB", "GPIOC", "GPIOD", "GPIOE", "GPIOF", "GPIOG",
"GPIOH", "GPIOI", "GPIOJ", "GPIOK", "GPIOL", "GPIOM", "GPION",
"GPIOO", "GPIOP", "GPIOQ", "GPIOR", "GPIOS", "GPIOT", "GP