1 /*
2  * Copyright (c) 2023 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT renesas_rzt2m_pinctrl
8 
9 #include <zephyr/arch/cpu.h>
10 #include <zephyr/drivers/pinctrl.h>
11 #include <soc.h>
12 
13 #define PORT_NSR DT_INST_REG_ADDR_BY_NAME(0, port_nsr)
14 #define PTADR    DT_INST_REG_ADDR_BY_NAME(0, ptadr)
15 
16 /* Port m mode control register */
17 #define PMC(port)        (PORT_NSR + 0x400 + port)
18 /* Port m function control register */
19 #define PFC(port)        (PORT_NSR + 0x600 + (0x4 * port))
20 /* IO Buffer m function switching register */
21 #define DRCTL(port, pin) (PORT_NSR + 0xa00 + (0x8 * port) + pin)
22 /* Port m region select register */
23 #define RSELP(port)      (PTADR + port)
24 
25 #define DRCTL_DRIVE_STRENGTH(val) (val & 0x3)
26 #define DRCTL_PULL_UP_DOWN(val)   ((val & 0x3) << 2)
27 #define DRCTL_SCHMITT(val)        ((val & 0x1) << 4)
28 #define DRCTL_SLEW_RATE(val)      ((val & 0x1) << 5)
29 #define DRCTL_CONFIG(drive, pull, schmitt, slew)                                                   \
30 	(DRCTL_DRIVE_STRENGTH(drive) | DRCTL_PULL_UP_DOWN(pull) | DRCTL_SCHMITT(schmitt) |         \
31 	 DRCTL_SLEW_RATE(slew))
32 #define PFC_FUNC_MASK(pin) (0xf << (pin * 4))
33 
pinctrl_configure_pin(const pinctrl_soc_pin_t * pin)34 static void pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
35 {
36 	uint8_t rselp = sys_read8(RSELP(pin->port));
37 	uint32_t pfc = sys_read32(PFC(pin->port)) & ~(PFC_FUNC_MASK(pin->pin));
38 	uint8_t pmc = sys_read8(PMC(pin->port));
39 
40 	/* Set proper bit in the RSELP register to use as non-safety domain. */
41 	sys_write8(rselp | BIT(pin->pin), RSELP(pin->port));
42 	sys_write8(DRCTL_CONFIG(
43 		pin->drive_strength, (pin->pull_up == 1 ? 1U : (pin->pull_down == 1 ? 2U : 0)),
44 		pin->schmitt_enable, pin->slew_rate),
45 		  DRCTL(pin->port, pin->pin));
46 
47 	/* Select function for the pin. */
48 	sys_write32(pfc | pin->func << (pin->pin * 4), PFC(pin->port));
49 
50 	/* Set proper bit in the PMC register to use the pin as a peripheral IO. */
51 	sys_write8(pmc | BIT(pin->pin), PMC(pin->port));
52 }
53 
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)54 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
55 {
56 	ARG_UNUSED(reg);
57 
58 	for (uint8_t i = 0U; i < pin_cnt; i++) {
59 		pinctrl_configure_pin(pins++);
60 	}
61 
62 	return 0;
63 }
64