mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-10 23:03:29 +09:00
![Simon Glass](/assets/img/avatar_default.png)
Recent Intel SoCs share a pinctrl mechanism with many common elements. Add an implementation of this core functionality, allowing SoC-specific drivers to avoid adding common code. As well as a pinctrl driver this provides a GPIO driver based on the same code. Once other SoCs use this driver we may consider moving more properties to the device tree (e.g. the community info and pad definitions). Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
307 lines
9.5 KiB
C
307 lines
9.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (C) 2017 Intel Corporation.
|
|
* Copyright 2019 Google LLC
|
|
*
|
|
* Modified from coreboot gpio.h
|
|
*/
|
|
|
|
#ifndef __ASM_INTEL_PINCTRL_H
|
|
#define __ASM_INTEL_PINCTRL_H
|
|
|
|
#include <dm/pinctrl.h>
|
|
|
|
/**
|
|
* struct pad_config - config for a pad
|
|
* @pad: offset of pad within community
|
|
* @pad_config: Pad config data corresponding to DW0, DW1, etc.
|
|
*/
|
|
struct pad_config {
|
|
int pad;
|
|
u32 pad_config[4];
|
|
};
|
|
|
|
#include <asm/arch/gpio.h>
|
|
|
|
/* GPIO community IOSF sideband clock gating */
|
|
#define MISCCFG_GPSIDEDPCGEN BIT(5)
|
|
/* GPIO community RCOMP clock gating */
|
|
#define MISCCFG_GPRCOMPCDLCGEN BIT(4)
|
|
/* GPIO community RTC clock gating */
|
|
#define MISCCFG_GPRTCDLCGEN BIT(3)
|
|
/* GFX controller clock gating */
|
|
#define MISCCFG_GSXSLCGEN BIT(2)
|
|
/* GPIO community partition clock gating */
|
|
#define MISCCFG_GPDPCGEN BIT(1)
|
|
/* GPIO community local clock gating */
|
|
#define MISCCFG_GPDLCGEN BIT(0)
|
|
/* Enable GPIO community power management configuration */
|
|
#define MISCCFG_ENABLE_GPIO_PM_CONFIG (MISCCFG_GPSIDEDPCGEN | \
|
|
MISCCFG_GPRCOMPCDLCGEN | MISCCFG_GPRTCDLCGEN | MISCCFG_GSXSLCGEN \
|
|
| MISCCFG_GPDPCGEN | MISCCFG_GPDLCGEN)
|
|
|
|
/*
|
|
* GPIO numbers may not be contiguous and instead will have a different
|
|
* starting pin number for each pad group.
|
|
*/
|
|
#define INTEL_GPP_BASE(first_of_community, start_of_group, end_of_group,\
|
|
group_pad_base) \
|
|
{ \
|
|
.first_pad = (start_of_group) - (first_of_community), \
|
|
.size = (end_of_group) - (start_of_group) + 1, \
|
|
.acpi_pad_base = (group_pad_base), \
|
|
}
|
|
|
|
/*
|
|
* A pad base of -1 indicates that this group uses contiguous numbering
|
|
* and a pad base should not be used for this group.
|
|
*/
|
|
#define PAD_BASE_NONE -1
|
|
|
|
/* The common/default group numbering is contiguous */
|
|
#define INTEL_GPP(first_of_community, start_of_group, end_of_group) \
|
|
INTEL_GPP_BASE(first_of_community, start_of_group, end_of_group,\
|
|
PAD_BASE_NONE)
|
|
|
|
/**
|
|
* struct reset_mapping - logical to actual value for PADRSTCFG in DW0
|
|
*
|
|
* Note that the values are expected to be within the field placement of the
|
|
* register itself. i.e. if the reset field is at 31:30 then the values within
|
|
* logical and chipset should occupy 31:30.
|
|
*/
|
|
struct reset_mapping {
|
|
u32 logical;
|
|
u32 chipset;
|
|
};
|
|
|
|
/**
|
|
* struct pad_group - describes the groups within each community
|
|
*
|
|
* @first_pad: offset of first pad of the group relative to the community
|
|
* @size: size of the group
|
|
* @acpi_pad_base: starting pin number for the pads in this group when they are
|
|
* used in ACPI. This is only needed if the pins are not contiguous across
|
|
* groups. Most groups will have this set to PAD_BASE_NONE and use
|
|
* contiguous numbering for ACPI.
|
|
*/
|
|
struct pad_group {
|
|
int first_pad;
|
|
uint size;
|
|
int acpi_pad_base;
|
|
};
|
|
|
|
/**
|
|
* struct pad_community - community of pads
|
|
*
|
|
* This describes a community, or each group within a community when multiple
|
|
* groups exist inside a community
|
|
*
|
|
* @name: Community name
|
|
* @acpi_path: ACPI path
|
|
* @num_gpi_regs: number of gpi registers in community
|
|
* @max_pads_per_group: number of pads in each group; number of pads bit-mapped
|
|
* in each GPI status/en and Host Own Reg
|
|
* @first_pad: first pad in community
|
|
* @last_pad: last pad in community
|
|
* @host_own_reg_0: offset to Host Ownership Reg 0
|
|
* @gpi_int_sts_reg_0: offset to GPI Int STS Reg 0
|
|
* @gpi_int_en_reg_0: offset to GPI Int Enable Reg 0
|
|
* @gpi_smi_sts_reg_0: offset to GPI SMI STS Reg 0
|
|
* @gpi_smi_en_reg_0: offset to GPI SMI EN Reg 0
|
|
* @pad_cfg_base: offset to first PAD_GFG_DW0 Reg
|
|
* @gpi_status_offset: specifies offset in struct gpi_status
|
|
* @port: PCR Port ID
|
|
* @reset_map: PADRSTCFG logical to chipset mapping
|
|
* @num_reset_vals: number of values in @reset_map
|
|
* @groups; list of groups for this community
|
|
* @num_groups: number of groups
|
|
*/
|
|
struct pad_community {
|
|
const char *name;
|
|
const char *acpi_path;
|
|
size_t num_gpi_regs;
|
|
size_t max_pads_per_group;
|
|
uint first_pad;
|
|
uint last_pad;
|
|
u16 host_own_reg_0;
|
|
u16 gpi_int_sts_reg_0;
|
|
u16 gpi_int_en_reg_0;
|
|
u16 gpi_smi_sts_reg_0;
|
|
u16 gpi_smi_en_reg_0;
|
|
u16 pad_cfg_base;
|
|
u8 gpi_status_offset;
|
|
u8 port;
|
|
const struct reset_mapping *reset_map;
|
|
size_t num_reset_vals;
|
|
const struct pad_group *groups;
|
|
size_t num_groups;
|
|
};
|
|
|
|
/**
|
|
* struct intel_pinctrl_priv - private data for each pinctrl device
|
|
*
|
|
* @comm: Pad community for this device
|
|
* @num_cfgs: Number of configuration words for each pad
|
|
* @itss: ITSS device (for interrupt handling)
|
|
* @itss_pol_cfg: Use to program Interrupt Polarity Control (IPCx) register
|
|
* Each bit represents IRQx Active High Polarity Disable configuration:
|
|
* when set to 1, the interrupt polarity associated with IRQx is inverted
|
|
* to appear as Active Low to IOAPIC and vice versa
|
|
*/
|
|
struct intel_pinctrl_priv {
|
|
const struct pad_community *comm;
|
|
int num_cfgs;
|
|
struct udevice *itss;
|
|
bool itss_pol_cfg;
|
|
};
|
|
|
|
/* Exported common operations for the pinctrl driver */
|
|
extern const struct pinctrl_ops intel_pinctrl_ops;
|
|
|
|
/* Exported common probe function for the pinctrl driver */
|
|
int intel_pinctrl_probe(struct udevice *dev);
|
|
|
|
/**
|
|
* intel_pinctrl_ofdata_to_platdata() - Handle common platdata setup
|
|
*
|
|
* @dev: Pinctrl device
|
|
* @comm: Pad community for this device
|
|
* @num_cfgs: Number of configuration words for each pad
|
|
* @return 0 if OK, -EDOM if @comm is NULL, other -ve value on other error
|
|
*/
|
|
int intel_pinctrl_ofdata_to_platdata(struct udevice *dev,
|
|
const struct pad_community *comm,
|
|
int num_cfgs);
|
|
|
|
/**
|
|
* pinctrl_route_gpe() - set GPIO groups for the general-purpose-event blocks
|
|
*
|
|
* The values from PMC register GPE_CFG are passed which is then mapped to
|
|
* proper groups for MISCCFG. This basically sets the MISCCFG register bits:
|
|
* dw0 = gpe0_route[11:8]. This is ACPI GPE0b.
|
|
* dw1 = gpe0_route[15:12]. This is ACPI GPE0c.
|
|
* dw2 = gpe0_route[19:16]. This is ACPI GPE0d.
|
|
*
|
|
* @dev: ITSS device
|
|
* @gpe0b: Value for GPE0B
|
|
* @gpe0c: Value for GPE0C
|
|
* @gpe0d: Value for GPE0D
|
|
* @return 0 if OK, -ve on error
|
|
*/
|
|
int pinctrl_route_gpe(struct udevice *dev, uint gpe0b, uint gpe0c, uint gpe0d);
|
|
|
|
/**
|
|
* pinctrl_config_pads() - Configure a list of pads
|
|
*
|
|
* Configures multiple pads using the provided data from the device tree.
|
|
*
|
|
* @dev: pinctrl device (any will do)
|
|
* @pads: Pad data, consisting of a pad number followed by num_cfgs entries
|
|
* containing the data for that pad (num_cfgs is set by the pinctrl device)
|
|
* @pads_count: Number of pads to configure
|
|
* @return 0 if OK, -ve on error
|
|
*/
|
|
int pinctrl_config_pads(struct udevice *dev, u32 *pads, int pads_count);
|
|
|
|
/**
|
|
* pinctrl_gpi_clear_int_cfg() - Set up the interrupts for use
|
|
*
|
|
* This enables the interrupt inputs and clears the status register bits
|
|
*
|
|
* @return 0 if OK, -ve on error
|
|
*/
|
|
int pinctrl_gpi_clear_int_cfg(void);
|
|
|
|
/**
|
|
* pinctrl_config_pads_for_node() - Configure pads
|
|
*
|
|
* Set up the pads using the data in a given node
|
|
*
|
|
* @dev: pinctrl device (any will do)
|
|
* @node: Node containing the 'pads' property with the data in it
|
|
* @return 0 if OK, -ve on error
|
|
*/
|
|
int pinctrl_config_pads_for_node(struct udevice *dev, ofnode node);
|
|
|
|
/**
|
|
* pinctrl_read_pads() - Read pad data from a node
|
|
*
|
|
* @dev: pinctrl device (any will do, it is just used to get config)
|
|
* @node: Node to read pad data from
|
|
* @prop: Property name to use (e.g. "pads")
|
|
* @padsp: Returns a pointer to an allocated array of pad data, in the format:
|
|
* <pad>
|
|
* <pad_config0>
|
|
* <pad_config1>
|
|
* ...
|
|
*
|
|
* The number of pad config values is set by the pinctrl controller.
|
|
* The caller must free this array.
|
|
* @pad_countp: Returns the number of pads read
|
|
* @ereturn 0 if OK, -ve on error
|
|
*/
|
|
int pinctrl_read_pads(struct udevice *dev, ofnode node, const char *prop,
|
|
u32 **padsp, int *pad_countp);
|
|
|
|
/**
|
|
* pinctrl_count_pads() - Count the number of pads in a pad array
|
|
*
|
|
* This used used with of-platdata where the array may be smaller than its
|
|
* maximum size. This function searches for the last pad in the array by finding
|
|
* the first 'zero' record
|
|
*
|
|
* This works out the number of records in the array. Each record has one word
|
|
* for the pad and num_cfgs words for the config.
|
|
*
|
|
* @dev: pinctrl device (any will do)
|
|
* @pads: Array of pad data
|
|
* @size: Size of pad data in bytes
|
|
* @return number of pads represented by the data
|
|
*/
|
|
int pinctrl_count_pads(struct udevice *dev, u32 *pads, int size);
|
|
|
|
/**
|
|
* intel_pinctrl_get_config_reg_addr() - Get address of the pin config registers
|
|
*
|
|
* @dev: Pinctrl device
|
|
* @offset: GPIO offset within this device
|
|
* @return register offset within the GPIO p2sb region
|
|
*/
|
|
u32 intel_pinctrl_get_config_reg_addr(struct udevice *dev, uint offset);
|
|
|
|
/**
|
|
* intel_pinctrl_get_config_reg() - Get the value of a GPIO register
|
|
*
|
|
* @dev: Pinctrl device
|
|
* @offset: GPIO offset within this device
|
|
* @return register value within the GPIO p2sb region
|
|
*/
|
|
u32 intel_pinctrl_get_config_reg(struct udevice *dev, uint offset);
|
|
|
|
/**
|
|
* intel_pinctrl_get_pad() - Get pad information for a pad
|
|
*
|
|
* This is used by the GPIO controller to find the pinctrl used by a pad.
|
|
*
|
|
* @pad: Pad to check
|
|
* @devp: Returns pinctrl device containing that pad
|
|
* @offsetp: Returns offset of pad within that pinctrl device
|
|
*/
|
|
int intel_pinctrl_get_pad(uint pad, struct udevice **devp, uint *offsetp);
|
|
|
|
/**
|
|
* intel_pinctrl_get_acpi_pin() - Get the ACPI pin for a pinctrl pin
|
|
*
|
|
* Maps a pinctrl pin (in terms of its offset within the pins controlled by that
|
|
* pinctrl) to an ACPI GPIO pin-table entry.
|
|
*
|
|
* @dev: Pinctrl device to check
|
|
* @offset: Offset of pin within that device (0 = first)
|
|
* @return associated ACPI GPIO pin-table entry, or standard pin number if the
|
|
* ACPI pad base is not set
|
|
*/
|
|
int intel_pinctrl_get_acpi_pin(struct udevice *dev, uint offset);
|
|
|
|
#endif
|