@@ -50,8 +50,23 @@ struct aml_pio_control {
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;
+ struct multi_mux multi_data[];
};
struct aml_pmx_func {
@@ -71,10 +86,12 @@ 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 {
@@ -106,13 +123,39 @@ static const char *aml_bank_name[31] = {
"GPIOCC", "TEST_N", "ANALOG"
};
+const struct aml_pctl_data s7_priv_data = {
+ .number = 1,
+ .multi_data[0] = {
+ .m_bank_id = AMLOGIC_GPIO_CC,
+ .m_bit_offs = 24,
+ .sid = (AMLOGIC_GPIO_X << 8) + 16,
+ .eid = (AMLOGIC_GPIO_X << 8) + 19,
+ },
+};
+
+const struct aml_pctl_data s6_priv_data = {
+ .number = 2,
+ .multi_data[0] = {
+ .m_bank_id = AMLOGIC_GPIO_CC,
+ .m_bit_offs = 24,
+ .sid = (AMLOGIC_GPIO_X << 8) + 16,
+ .eid = (AMLOGIC_GPIO_X << 8) + 19,
+ },
+ .multi_data[1] = {
+ .m_bank_id = AMLOGIC_GPIO_F,
+ .m_bit_offs = 4,
+ .sid = (AMLOGIC_GPIO_D << 8) + 6,
+ .eid = (AMLOGIC_GPIO_D << 8) + 6,
+ },
+};
+
static int aml_pmx_calc_reg_and_offset(struct pinctrl_gpio_range *range,
unsigned int pin, unsigned int *reg,
unsigned int *offset)
{
unsigned int shift;
- shift = (pin - range->pin_base) << 2;
+ shift = ((pin - range->pin_base) << 2) + *offset;
*reg = (shift / 32) * 4;
*offset = shift % 32;
@@ -124,9 +167,36 @@ static int aml_pctl_set_function(struct aml_pinctrl *info,
int pin_id, int func)
{
struct aml_gpio_bank *bank = gpio_chip_to_bank(range->gc);
+ unsigned int shift;
int reg;
- int offset;
+ int i;
+ unsigned int offset = bank->mux_bit_offs;
+ const struct multi_mux *p_mux;
+
+ /* peculiar mux reg set */
+ if (bank->p_mux) {
+ p_mux = bank->p_mux;
+ if (pin_id >= p_mux->sid && pin_id <= p_mux->eid) {
+ bank = NULL;
+ for (i = 0; i < info->nbanks; i++) {
+ if (info->banks[i].bank_id == p_mux->m_bank_id) {
+ bank = &info->banks[i];
+ break;
+ }
+ }
+
+ if (!bank || !bank->reg_mux)
+ return -EINVAL;
+
+ shift = (pin_id - p_mux->sid) << 2;
+ reg = (shift / 32) * 4;
+ offset = shift % 32;
+ return regmap_update_bits(bank->reg_mux, reg,
+ 0xf << offset, (func & 0xf) << offset);
+ }
+ }
+ /* normal mux reg set */
if (!bank->reg_mux)
return 0;
@@ -836,12 +906,30 @@ static const struct gpio_chip aml_gpio_template = {
static void init_bank_register_bit(struct aml_pinctrl *info,
struct aml_gpio_bank *bank)
{
+ const struct aml_pctl_data *data = info->data;
+ const struct multi_mux *multi_data;
int i;
for (i = 0; i < AML_NUM_REG; i++) {
bank->pc.reg_offset[i] = aml_def_regoffs[i];
bank->pc.bit_offset[i] = 0;
}
+
+ bank->mux_bit_offs = 0;
+
+ if (data) {
+ for (i = 0; i < data->number; i++) {
+ multi_data = &data->multi_data[i];
+ if (bank->bank_id == multi_data->m_bank_id) {
+ bank->mux_bit_offs = multi_data->m_bit_offs;
+ break;
+ }
+ if (multi_data->sid >> 8 == bank->bank_id) {
+ bank->p_mux = multi_data;
+ break;
+ }
+ }
+ }
}
static int aml_gpiolib_register_bank(struct aml_pinctrl *info,
@@ -1008,6 +1096,8 @@ static int aml_pctl_probe(struct platform_device *pdev)
static const struct of_device_id aml_pctl_of_match[] = {
{ .compatible = "amlogic,pinctrl-a4", },
+ { .compatible = "amlogic,pinctrl-s7", .data = &s7_priv_data, },
+ { .compatible = "amlogic,pinctrl-s6", .data = &s6_priv_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, aml_pctl_dt_match);