mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-11 22:03:15 +00:00
32b2ea9818
Some pins in rockchip are routed via Top GRF and PMU GRF instead of direct regmap. Add support to handle all these routing paths so that the SoC pinctrl drivers will use them accordingly. Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com> Signed-off-by: Jagan Teki <jagan@edgeble.ai> Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
352 lines
9.4 KiB
C
352 lines
9.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
/*
|
|
* (C) Copyright 2019 Rockchip Electronics Co., Ltd
|
|
*/
|
|
|
|
#ifndef __DRIVERS_PINCTRL_ROCKCHIP_H
|
|
#define __DRIVERS_PINCTRL_ROCKCHIP_H
|
|
|
|
#include <linux/bitops.h>
|
|
#include <linux/types.h>
|
|
|
|
#define RK_GENMASK_VAL(h, l, v) \
|
|
(GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l))))
|
|
|
|
/**
|
|
* Encode variants of iomux registers into a type variable
|
|
*/
|
|
#define IOMUX_GPIO_ONLY BIT(0)
|
|
#define IOMUX_WIDTH_4BIT BIT(1)
|
|
#define IOMUX_SOURCE_PMU BIT(2)
|
|
#define IOMUX_UNROUTED BIT(3)
|
|
#define IOMUX_WIDTH_3BIT BIT(4)
|
|
#define IOMUX_8WIDTH_2BIT BIT(5)
|
|
#define IOMUX_L_SOURCE_PMU BIT(6)
|
|
|
|
/**
|
|
* Defined some common pins constants
|
|
*/
|
|
#define ROCKCHIP_PULL_BITS_PER_PIN 2
|
|
#define ROCKCHIP_PULL_PINS_PER_REG 8
|
|
#define ROCKCHIP_PULL_BANK_STRIDE 16
|
|
#define ROCKCHIP_DRV_BITS_PER_PIN 2
|
|
#define ROCKCHIP_DRV_PINS_PER_REG 8
|
|
#define ROCKCHIP_DRV_BANK_STRIDE 16
|
|
#define ROCKCHIP_DRV_3BITS_PER_PIN 3
|
|
|
|
/**
|
|
* @type: iomux variant using IOMUX_* constants
|
|
* @offset: if initialized to -1 it will be autocalculated, by specifying
|
|
* an initial offset value the relevant source offset can be reset
|
|
* to a new value for autocalculating the following iomux registers.
|
|
*/
|
|
struct rockchip_iomux {
|
|
int type;
|
|
int offset;
|
|
};
|
|
|
|
/**
|
|
* enum type index corresponding to rockchip_perpin_drv_list arrays index.
|
|
*/
|
|
enum rockchip_pin_drv_type {
|
|
DRV_TYPE_IO_DEFAULT = 0,
|
|
DRV_TYPE_IO_1V8_OR_3V0,
|
|
DRV_TYPE_IO_1V8_ONLY,
|
|
DRV_TYPE_IO_1V8_3V0_AUTO,
|
|
DRV_TYPE_IO_3V3_ONLY,
|
|
DRV_TYPE_MAX
|
|
};
|
|
|
|
/**
|
|
* enum type index corresponding to rockchip_pull_list arrays index.
|
|
*/
|
|
enum rockchip_pin_pull_type {
|
|
PULL_TYPE_IO_DEFAULT = 0,
|
|
PULL_TYPE_IO_1V8_ONLY,
|
|
PULL_TYPE_MAX
|
|
};
|
|
|
|
/**
|
|
* Rockchip pinctrl route type
|
|
*
|
|
* DEFAULT : Same regmap as pin iomux
|
|
* TOPGRF : Mux route setting in topgrf
|
|
* PMUGRF : Mux route setting in pmugrf
|
|
* INVALID : Nnot need to set mux route
|
|
*/
|
|
enum rockchip_pin_route_type {
|
|
ROUTE_TYPE_DEFAULT = 0,
|
|
ROUTE_TYPE_TOPGRF = 1,
|
|
ROUTE_TYPE_PMUGRF = 2,
|
|
|
|
ROUTE_TYPE_INVALID = -1,
|
|
};
|
|
|
|
/**
|
|
* @drv_type: drive strength variant using rockchip_perpin_drv_type
|
|
* @offset: if initialized to -1 it will be autocalculated, by specifying
|
|
* an initial offset value the relevant source offset can be reset
|
|
* to a new value for autocalculating the following drive strength
|
|
* registers. if used chips own cal_drv func instead to calculate
|
|
* registers offset, the variant could be ignored.
|
|
*/
|
|
struct rockchip_drv {
|
|
enum rockchip_pin_drv_type drv_type;
|
|
int offset;
|
|
};
|
|
|
|
/**
|
|
* @priv: common pinctrl private basedata
|
|
* @pin_base: first pin number
|
|
* @nr_pins: number of pins in this bank
|
|
* @name: name of the bank
|
|
* @bank_num: number of the bank, to account for holes
|
|
* @iomux: array describing the 4 iomux sources of the bank
|
|
* @drv: array describing the 4 drive strength sources of the bank
|
|
* @pull_type: array describing the 4 pull type sources of the bank
|
|
* @recalced_mask: bits describing the mux recalced pins of per bank
|
|
* @route_mask: bits describing the routing pins of per bank
|
|
*/
|
|
struct rockchip_pin_bank {
|
|
struct rockchip_pinctrl_priv *priv;
|
|
u32 pin_base;
|
|
u8 nr_pins;
|
|
char *name;
|
|
u8 bank_num;
|
|
struct rockchip_iomux iomux[4];
|
|
struct rockchip_drv drv[4];
|
|
enum rockchip_pin_pull_type pull_type[4];
|
|
u32 recalced_mask;
|
|
u32 route_mask;
|
|
};
|
|
|
|
#define PIN_BANK(id, pins, label) \
|
|
{ \
|
|
.bank_num = id, \
|
|
.nr_pins = pins, \
|
|
.name = label, \
|
|
.iomux = { \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
}, \
|
|
}
|
|
|
|
#define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3) \
|
|
{ \
|
|
.bank_num = id, \
|
|
.nr_pins = pins, \
|
|
.name = label, \
|
|
.iomux = { \
|
|
{ .type = iom0, .offset = -1 }, \
|
|
{ .type = iom1, .offset = -1 }, \
|
|
{ .type = iom2, .offset = -1 }, \
|
|
{ .type = iom3, .offset = -1 }, \
|
|
}, \
|
|
}
|
|
|
|
#define PIN_BANK_IOMUX_FLAGS_OFFSET(id, pins, label, iom0, iom1, iom2, \
|
|
iom3, offset0, offset1, offset2, \
|
|
offset3) \
|
|
{ \
|
|
.bank_num = id, \
|
|
.nr_pins = pins, \
|
|
.name = label, \
|
|
.iomux = { \
|
|
{ .type = iom0, .offset = offset0 }, \
|
|
{ .type = iom1, .offset = offset1 }, \
|
|
{ .type = iom2, .offset = offset2 }, \
|
|
{ .type = iom3, .offset = offset3 }, \
|
|
}, \
|
|
}
|
|
|
|
#define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
|
|
{ \
|
|
.bank_num = id, \
|
|
.nr_pins = pins, \
|
|
.name = label, \
|
|
.iomux = { \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
}, \
|
|
.drv = { \
|
|
{ .drv_type = type0, .offset = -1 }, \
|
|
{ .drv_type = type1, .offset = -1 }, \
|
|
{ .drv_type = type2, .offset = -1 }, \
|
|
{ .drv_type = type3, .offset = -1 }, \
|
|
}, \
|
|
}
|
|
|
|
#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1, \
|
|
drv2, drv3, pull0, pull1, \
|
|
pull2, pull3) \
|
|
{ \
|
|
.bank_num = id, \
|
|
.nr_pins = pins, \
|
|
.name = label, \
|
|
.iomux = { \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
{ .offset = -1 }, \
|
|
}, \
|
|
.drv = { \
|
|
{ .drv_type = drv0, .offset = -1 }, \
|
|
{ .drv_type = drv1, .offset = -1 }, \
|
|
{ .drv_type = drv2, .offset = -1 }, \
|
|
{ .drv_type = drv3, .offset = -1 }, \
|
|
}, \
|
|
.pull_type[0] = pull0, \
|
|
.pull_type[1] = pull1, \
|
|
.pull_type[2] = pull2, \
|
|
.pull_type[3] = pull3, \
|
|
}
|
|
|
|
#define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1, \
|
|
iom2, iom3, drv0, drv1, drv2, \
|
|
drv3, offset0, offset1, \
|
|
offset2, offset3) \
|
|
{ \
|
|
.bank_num = id, \
|
|
.nr_pins = pins, \
|
|
.name = label, \
|
|
.iomux = { \
|
|
{ .type = iom0, .offset = -1 }, \
|
|
{ .type = iom1, .offset = -1 }, \
|
|
{ .type = iom2, .offset = -1 }, \
|
|
{ .type = iom3, .offset = -1 }, \
|
|
}, \
|
|
.drv = { \
|
|
{ .drv_type = drv0, .offset = offset0 }, \
|
|
{ .drv_type = drv1, .offset = offset1 }, \
|
|
{ .drv_type = drv2, .offset = offset2 }, \
|
|
{ .drv_type = drv3, .offset = offset3 }, \
|
|
}, \
|
|
}
|
|
|
|
#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins, \
|
|
label, iom0, iom1, iom2, \
|
|
iom3, drv0, drv1, drv2, \
|
|
drv3, offset0, offset1, \
|
|
offset2, offset3, pull0, \
|
|
pull1, pull2, pull3) \
|
|
{ \
|
|
.bank_num = id, \
|
|
.nr_pins = pins, \
|
|
.name = label, \
|
|
.iomux = { \
|
|
{ .type = iom0, .offset = -1 }, \
|
|
{ .type = iom1, .offset = -1 }, \
|
|
{ .type = iom2, .offset = -1 }, \
|
|
{ .type = iom3, .offset = -1 }, \
|
|
}, \
|
|
.drv = { \
|
|
{ .drv_type = drv0, .offset = offset0 }, \
|
|
{ .drv_type = drv1, .offset = offset1 }, \
|
|
{ .drv_type = drv2, .offset = offset2 }, \
|
|
{ .drv_type = drv3, .offset = offset3 }, \
|
|
}, \
|
|
.pull_type[0] = pull0, \
|
|
.pull_type[1] = pull1, \
|
|
.pull_type[2] = pull2, \
|
|
.pull_type[3] = pull3, \
|
|
}
|
|
|
|
#define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG) \
|
|
{ \
|
|
.bank_num = ID, \
|
|
.pin = PIN, \
|
|
.func = FUNC, \
|
|
.route_offset = REG, \
|
|
.route_val = VAL, \
|
|
.route_type = FLAG, \
|
|
}
|
|
|
|
#define MR_DEFAULT(ID, PIN, FUNC, REG, VAL) \
|
|
PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_DEFAULT)
|
|
|
|
#define MR_TOPGRF(ID, PIN, FUNC, REG, VAL) \
|
|
PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_TOPGRF)
|
|
|
|
#define MR_PMUGRF(ID, PIN, FUNC, REG, VAL) \
|
|
PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF)
|
|
|
|
/**
|
|
* struct rockchip_mux_recalced_data: recalculate a pin iomux data.
|
|
* @num: bank number.
|
|
* @pin: pin number.
|
|
* @reg: register offset.
|
|
* @bit: index at register.
|
|
* @mask: mask bit
|
|
*/
|
|
struct rockchip_mux_recalced_data {
|
|
u8 num;
|
|
u8 pin;
|
|
u32 reg;
|
|
u8 bit;
|
|
u8 mask;
|
|
};
|
|
|
|
/**
|
|
* struct rockchip_mux_route_data: route a pin iomux data.
|
|
* @bank_num: bank number.
|
|
* @pin: index at register or used to calc index.
|
|
* @func: the min pin.
|
|
* @route_type: the register type.
|
|
* @route_offset: the max pin.
|
|
* @route_val: the register offset.
|
|
*/
|
|
struct rockchip_mux_route_data {
|
|
u8 bank_num;
|
|
u8 pin;
|
|
u8 func;
|
|
enum rockchip_pin_route_type route_type : 8;
|
|
u32 route_offset;
|
|
u32 route_val;
|
|
};
|
|
|
|
/**
|
|
*/
|
|
struct rockchip_pin_ctrl {
|
|
struct rockchip_pin_bank *pin_banks;
|
|
u32 nr_banks;
|
|
u32 nr_pins;
|
|
int grf_mux_offset;
|
|
int pmu_mux_offset;
|
|
int grf_drv_offset;
|
|
int pmu_drv_offset;
|
|
struct rockchip_mux_recalced_data *iomux_recalced;
|
|
u32 niomux_recalced;
|
|
struct rockchip_mux_route_data *iomux_routes;
|
|
u32 niomux_routes;
|
|
|
|
int (*set_mux)(struct rockchip_pin_bank *bank,
|
|
int pin, int mux);
|
|
int (*set_pull)(struct rockchip_pin_bank *bank,
|
|
int pin_num, int pull);
|
|
int (*set_drive)(struct rockchip_pin_bank *bank,
|
|
int pin_num, int strength);
|
|
int (*set_schmitt)(struct rockchip_pin_bank *bank,
|
|
int pin_num, int enable);
|
|
};
|
|
|
|
/**
|
|
*/
|
|
struct rockchip_pinctrl_priv {
|
|
struct rockchip_pin_ctrl *ctrl;
|
|
struct regmap *regmap_base;
|
|
struct regmap *regmap_pmu;
|
|
};
|
|
|
|
extern const struct pinctrl_ops rockchip_pinctrl_ops;
|
|
int rockchip_pinctrl_probe(struct udevice *dev);
|
|
void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
|
|
int *reg, u8 *bit, int *mask);
|
|
int rockchip_get_mux_data(int mux_type, int pin, u8 *bit, int *mask);
|
|
int rockchip_translate_drive_value(int type, int strength);
|
|
int rockchip_translate_pull_value(int type, int pull);
|
|
|
|
#endif /* __DRIVERS_PINCTRL_ROCKCHIP_H */
|