Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | /*
* Copyright (c) 2020 ITE Corporation. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief PINMUX driver for the IT8xxx2
*/
#include <errno.h>
#include <device.h>
#include <drivers/pinmux.h>
#include <soc.h>
#include <dt-bindings/pinctrl/it8xxx2-pinctrl.h>
#define DT_DRV_COMPAT ite_it8xxx2_pinmux
#include <logging/log.h>
LOG_MODULE_REGISTER(pinmux_ite_it8xxx2, LOG_LEVEL_ERR);
struct pinmux_it8xxx2_config {
/* gpio port control register (byte mapping to pin) */
uintptr_t reg_gpcr;
/* function 3 general control register */
uintptr_t func3_gcr[8];
/* function 4 general control register */
uintptr_t func4_gcr[8];
/* function 3 enable mask */
uint8_t func3_en_mask[8];
/* function 4 enable mask */
uint8_t func4_en_mask[8];
};
#define DEV_CFG(dev) \
((const struct pinmux_it8xxx2_config * const) \
(dev)->config)
static int pinmux_it8xxx2_set(const struct device *dev,
uint32_t pin, uint32_t func)
{
const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);
volatile uint8_t *reg_gpcr =
(uint8_t *)(pinmux_config->reg_gpcr + pin);
volatile uint8_t *reg_func3_gcr =
(uint8_t *)(pinmux_config->func3_gcr[pin]);
volatile uint8_t *reg_func4_gcr =
(uint8_t *)(pinmux_config->func4_gcr[pin]);
if (pin >= IT8XXX2_PINMUX_PINS) {
return -EINVAL;
}
/* Common settings for alternate function. */
*reg_gpcr &= ~(GPCR_PORT_PIN_MODE_INPUT |
GPCR_PORT_PIN_MODE_OUTPUT);
switch (func) {
case IT8XXX2_PINMUX_FUNC_1:
/* Func1: Alternate function has been set above. */
break;
case IT8XXX2_PINMUX_FUNC_2:
/* Func2: WUI function: turn the pin into an input */
*reg_gpcr |= GPCR_PORT_PIN_MODE_INPUT;
break;
case IT8XXX2_PINMUX_FUNC_3:
/*
* Func3: In addition to the alternate setting above,
* Func3 also need to set the general control.
*/
*reg_func3_gcr |= pinmux_config->func3_en_mask[pin];
break;
case IT8XXX2_PINMUX_FUNC_4:
/*
* Func4: In addition to the alternate setting above,
* Func4 also need to set the general control.
*/
*reg_func4_gcr |= pinmux_config->func4_en_mask[pin];
break;
default:
LOG_ERR("This function is not supported");
return -EINVAL;
}
return 0;
}
static int pinmux_it8xxx2_get(const struct device *dev,
uint32_t pin, uint32_t *func)
{
const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);
volatile uint8_t *reg_gpcr =
(uint8_t *)(pinmux_config->reg_gpcr + pin);
if (pin >= IT8XXX2_PINMUX_PINS || func == NULL) {
return -EINVAL;
}
*func = (*reg_gpcr & (GPCR_PORT_PIN_MODE_INPUT |
GPCR_PORT_PIN_MODE_OUTPUT)) == GPCR_PORT_PIN_MODE_INPUT ?
IT8XXX2_PINMUX_FUNC_2 : IT8XXX2_PINMUX_FUNC_1;
/* TODO: IT8XXX2_PINMUX_FUNC_3 & IT8XXX2_PINMUX_FUNC_4 */
return 0;
}
static int pinmux_it8xxx2_pullup(const struct device *dev,
uint32_t pin, uint8_t func)
{
const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);
volatile uint8_t *reg_gpcr =
(uint8_t *)(pinmux_config->reg_gpcr + pin);
if (func == PINMUX_PULLUP_ENABLE) {
*reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_PULLUP) &
~GPCR_PORT_PIN_MODE_PULLDOWN;
} else if (func == PINMUX_PULLUP_DISABLE) {
*reg_gpcr &= ~(GPCR_PORT_PIN_MODE_PULLUP |
GPCR_PORT_PIN_MODE_PULLDOWN);
} else {
return -EINVAL;
}
return 0;
}
static int pinmux_it8xxx2_input(const struct device *dev,
uint32_t pin, uint8_t func)
{
const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);
volatile uint8_t *reg_gpcr =
(uint8_t *)(pinmux_config->reg_gpcr + pin);
*reg_gpcr &= ~(GPCR_PORT_PIN_MODE_INPUT |
GPCR_PORT_PIN_MODE_OUTPUT);
if (func == PINMUX_INPUT_ENABLED) {
*reg_gpcr |= GPCR_PORT_PIN_MODE_INPUT;
} else if (func == PINMUX_OUTPUT_ENABLED) {
*reg_gpcr |= GPCR_PORT_PIN_MODE_OUTPUT;
} else {
return -EINVAL;
}
return 0;
}
static int pinmux_it8xxx2_init(const struct device *dev)
{
ARG_UNUSED(dev);
/*
* The default value of LPCRSTEN is bit2:1 = 10b(GPD2) in GCR.
* If LPC reset is enabled on GPB7, we have to clear bit2:1
* to 00b.
*/
IT8XXX2_GPIO_GCR &= ~(BIT(1) | BIT(2));
/*
* TODO: If SMBUS3 swaps from H group to F group, we have to
* set SMB3PSEL = 1 in PMER3 register.
*/
/*
* TODO: If UART2 swaps from bit2:1 to bit6:5 in H group, we
* have to set UART1PSEL = 1 in UART1PMR register.
*/
return 0;
}
static const struct pinmux_driver_api pinmux_it8xxx2_driver_api = {
.set = pinmux_it8xxx2_set,
.get = pinmux_it8xxx2_get,
.pullup = pinmux_it8xxx2_pullup,
.input = pinmux_it8xxx2_input,
};
#define PINMUX_ITE_INIT(inst) \
static const struct pinmux_it8xxx2_config pinmux_it8xxx2_cfg_##inst = { \
.reg_gpcr = DT_INST_REG_ADDR(inst), \
.func3_gcr = DT_INST_PROP(inst, func3_gcr), \
.func3_en_mask = DT_INST_PROP(inst, func3_en_mask), \
.func4_gcr = DT_INST_PROP(inst, func4_gcr), \
.func4_en_mask = DT_INST_PROP(inst, func4_en_mask), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, \
&pinmux_it8xxx2_init, \
NULL, NULL, &pinmux_it8xxx2_cfg_##inst, \
PRE_KERNEL_1, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&pinmux_it8xxx2_driver_api);
DT_INST_FOREACH_STATUS_OKAY(PINMUX_ITE_INIT)
|