// SPDX-License-Identifier: GPL-2.0/* * SP7021 Pin Controller Driver. * Copyright (C) Sunplus Tech / Tibbo Tech. */ #include <linux/cleanup.h>#include <linux/bitfield.h>#include <linux/device.h>#include <linux/err.h>#include <linux/gpio/driver.h>#include <linux/init.h>#include <linux/module.h>#include <linux/of.h>#include <linux/overflow.h>#include <linux/platform_device.h>#include <linux/seq_file.h>#include <linux/slab.h> #include <linux/pinctrl/pinconf.h>#include <linux/pinctrl/pinconf-generic.h>#include <linux/pinctrl/pinmux.h> #include <dt-bindings/pinctrl/sppctl-sp7021.h> #include "../core.h"#include "../pinctrl-utils.h" #include "sppctl.h" struct sppctl_gpio_chip { void __iomem *gpioxt_base; /* MASTER, OE, OUT, IN, I_INV, O_INV, OD */ void __iomem *first_base; /* GPIO_FIRST */ struct gpio_chip chip; spinlock_t lock; /* lock for accessing OE register */}; static inline u32 sppctl_first_readl(struct sppctl_gpio_chip *spp_gchip, u32 off){ return readl(spp_gchip->first_base + SPPCTL_GPIO_OFF_FIRST + off);} static inline void sppctl_first_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off){ writel(val, spp_gchip->first_base + SPPCTL_GPIO_OFF_FIRST + off);} static inline u32 sppctl_gpio_master_readl(struct sppctl_gpio_chip *spp_gchip, u32 off){ return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_MASTER + off);} static inline void sppctl_gpio_master_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off){ writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_MASTER + off);} static inline u32 sppctl_gpio_oe_readl(struct sppctl_gpio_chip *spp_gchip, u32 off){ return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OE + off);} static inline void sppctl_gpio_oe_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off){ writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OE + off);} static inline void sppctl_gpio_out_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off){ writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OUT + off);} static inline u32 sppctl_gpio_in_readl(struct sppctl_gpio_chip *spp_gchip, u32 off){ return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IN + off);} static inline u32 sppctl_gpio_iinv_readl(struct sppctl_gpio_chip *spp_gchip, u32 off){ return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IINV + off);} static inline void sppctl_gpio_iinv_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off){ writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IINV + off);} static inline u32 sppctl_gpio_oinv_readl(struct sppctl_gpio_chip *spp_gchip, u32 off){ return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OINV + off);} static inline void sppctl_gpio_oinv_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off){ writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OINV + off);} static inline u32 sppctl_gpio_od_readl(struct sppctl_gpio_chip *spp_gchip, u32 off){ return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OD + off);} static inline void sppctl_gpio_od_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off){ writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OD + off);} static inline u32 sppctl_get_reg_and_bit_offset(unsigned int offset, u32 *reg_off){ u32 bit_off; /* Each register has 32 bits. */ *reg_off = (offset / 32) * 4; bit_off = offset % 32; return bit_off;} static inline u32 sppctl_get_moon_reg_and_bit_offset(unsigned int offset, u32 *reg_off){ u32 bit_off; /* * Each MOON register has 32 bits. Upper 16-bit word are mask-fields. * The lower 16-bit word are the control-fields. The corresponding * bits in mask-field should be set then you can write something to * control-field. */ *reg_off = (offset / 16) * 4; bit_off = offset % 16; return bit_off;} static inline u32 sppctl_prep_moon_reg_and_offset(unsigned int offset, u32 *reg_off, int val){ u32 bit_off; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, reg_off); if (val) return SPPCTL_SET_MOON_REG_BIT(bit_off); else return SPPCTL_CLR_MOON_REG_BIT(bit_off);} /** * sppctl_func_set() - Set pin of fully-pinmux function. * * Mask-fields and control-fields of fully-pinmux function of SP7021 are * arranged as shown below: * * func# | register | mask-field | control-field * -------+----------+--------------+--------------- * 0 | base[0] | (22 : 16) | ( 6 : 0) * 1 | base[0] | (30 : 24) | (14 : 8) * 2 | base[1] | (22 : 16) | ( 6 : 0) * 3 | baeg[1] | (30 : 24) | (14 : 8) * : | : | : | : * * where mask-fields are used to protect control-fields from write-in * accidentally. Set the corresponding bits in the mask-field before * you write a value into a control-field. * * Control-fields are used to set where the function pin is going to * be routed to. * * Note that mask-fields and control-fields of even number of 'func' * are located at bits (22:16) and (6:0), while odd number of 'func's * are located at bits (30:24) and (14:8). */static void sppctl_func_set(struct sppctl_pdata *pctl, u8 func, u8 val){ u32 reg, offset; /* * Note that upper 16-bit word are mask-fields and lower 16-bit * word are the control-fields. Set corresponding bits in mask- * field before write to a control-field. */ reg = SPPCTL_FULLY_PINMUX_MASK_MASK | val; /* * MUXF_L2SW_CLK_OUT is the first fully-pinmux pin * and its register offset is 0. */ func -= MUXF_L2SW_CLK_OUT; /* * Check if 'func' is an odd number or not. Mask and control- * fields of odd number 'func' is located at upper portion of * a register. Extra shift is needed. */ if (func & BIT(0)) reg <<= SPPCTL_FULLY_PINMUX_UPPER_SHIFT; /* Convert func# to register offset w.r.t. base register. */ offset = func * 2; offset &= GENMASK(31, 2); writel(reg, pctl->moon2_base + offset);} /** * sppctl_gmx_set() - Set pin of group-pinmux. * * Mask-fields and control-fields of group-pinmux function of SP7021 are * arranged as shown below: * * register | mask-fields | control-fields * ----------+--------------+---------------- * base[0] | (31 : 16) | (15 : 0) * base[1] | (31 : 24) | (15 : 0) * base[2] | (31 : 24) | (15 : 0) * : | : | : * * where mask-fields are used to protect control-fields from write-in * accidentally. Set the corresponding bits in the mask-field before * you write a value into a control-field. * * Control-fields are used to set where the function pin is going to * be routed to. A control-field consists of one or more bits. */static void sppctl_gmx_set(struct sppctl_pdata *pctl, u8 reg_off, u8 bit_off, u8 bit_sz, u8 val){ u32 mask, reg; /* * Note that upper 16-bit word are mask-fields and lower 16-bit * word are the control-fields. Set corresponding bits in mask- * field before write to a control-field. */ mask = GENMASK(bit_sz - 1, 0) << SPPCTL_MOON_REG_MASK_SHIFT; reg = (mask | val) << bit_off; writel(reg, pctl->moon1_base + reg_off * 4);} /** * sppctl_first_get() - get bit of FIRST register. * * There are 4 FIRST registers. Each has 32 control-bits. * Totally, there are 4 * 32 = 128 control-bits. * Control-bits are arranged as shown below: * * registers | control-bits * -----------+-------------- * first[0] | (31 : 0) * first[1] | (63 : 32) * first[2] | (95 : 64) * first[3] | (127 : 96) * * Each control-bit sets type of a GPIO pin. * 0: a fully-pinmux pin * 1: a GPIO or IOP pin */static int sppctl_first_get(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off); reg = sppctl_first_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0;} /** * sppctl_master_get() - get bit of MASTER register. * * There are 8 MASTER registers. Each has 16 mask-bits and 16 control-bits. * Upper 16-bit of MASTER registers are mask-bits while lower 16-bit are * control-bits. Totally, there are 128 mask-bits and 128 control-bits. * They are arranged as shown below: * * register | mask-bits | control-bits * -----------+-------------+-------------- * master[0] | (15 : 0) | (15 : 0) * master[1] | (31 : 16) | (31 : 16) * master[2] | (47 : 32) | (47 : 32) * : | : | : * master[7] | (127 : 112) | (127 : 112) * * where mask-bits are used to protect control-bits from write-in * accidentally. Set the corresponding mask-bit before you write * a value into a control-bit. * * Each control-bit sets type of a GPIO pin when FIRST bit is 1. * 0: a IOP pin * 1: a GPIO pin */static int sppctl_master_get(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_master_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0;} static void sppctl_first_master_set(struct gpio_chip *chip, unsigned int offset, enum mux_first_reg first, enum mux_master_reg master){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; enum mux_first_reg val; /* FIRST register */ if (first != mux_f_keep) { bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off); reg = sppctl_first_readl(spp_gchip, reg_off); val = (reg & BIT(bit_off)) ? mux_f_gpio : mux_f_mux; if (first != val) switch (first) { case mux_f_gpio: reg |= BIT(bit_off); sppctl_first_writel(spp_gchip, reg, reg_off); break; case mux_f_mux: reg &= ~BIT(bit_off); sppctl_first_writel(spp_gchip, reg, reg_off); break; case mux_f_keep: break; } } /* MASTER register */ if (master != mux_m_keep) { reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, (master == mux_m_gpio)); sppctl_gpio_master_writel(spp_gchip, reg, reg_off); }} static void sppctl_gpio_input_inv_set(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); sppctl_gpio_iinv_writel(spp_gchip, reg, reg_off);} static void sppctl_gpio_output_inv_set(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); sppctl_gpio_oinv_writel(spp_gchip, reg, reg_off);} static int sppctl_gpio_output_od_get(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_od_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0;} static void sppctl_gpio_output_od_set(struct gpio_chip *chip, unsigned int offset, unsigned int val){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val); sppctl_gpio_od_writel(spp_gchip, reg, reg_off);} static int sppctl_gpio_get_direction(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_oe_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 0 : 1;} static int sppctl_gpio_inv_get(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; unsigned long flags; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); spin_lock_irqsave(&spp_gchip->lock, flags); if (sppctl_gpio_get_direction(chip, offset)) reg = sppctl_gpio_iinv_readl(spp_gchip, reg_off); else reg = sppctl_gpio_oinv_readl(spp_gchip, reg_off); spin_unlock_irqrestore(&spp_gchip->lock, flags); return (reg & BIT(bit_off)) ? 1 : 0;} static int sppctl_gpio_direction_input(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); unsigned long flags; u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 0); spin_lock_irqsave(&spp_gchip->lock, flags); sppctl_gpio_oe_writel(spp_gchip, reg, reg_off); spin_unlock_irqrestore(&spp_gchip->lock, flags); return 0;} static int sppctl_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int val){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); unsigned long flags; u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); spin_lock_irqsave(&spp_gchip->lock, flags); sppctl_gpio_oe_writel(spp_gchip, reg, reg_off); if (val < 0) { spin_unlock_irqrestore(&spp_gchip->lock, flags); return 0; } reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val); sppctl_gpio_out_writel(spp_gchip, reg, reg_off); spin_unlock_irqrestore(&spp_gchip->lock, flags); return 0;} static int sppctl_gpio_get(struct gpio_chip *chip, unsigned int offset){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_in_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0;} static int sppctl_gpio_set(struct gpio_chip *chip, unsigned int offset, int val){ struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val); sppctl_gpio_out_writel(spp_gchip, reg, reg_off); return 0;} static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset, unsigned long config){ enum pin_config_param param = pinconf_to_config_param(config); struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; switch (param) { case PIN_CONFIG_DRIVE_OPEN_DRAIN: reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); sppctl_gpio_od_writel(spp_gchip, reg, reg_off); break; case PIN_CONFIG_INPUT_ENABLE: break; case PIN_CONFIG_LEVEL: return sppctl_gpio_direction_output(chip, offset, 0); case PIN_CONFIG_PERSIST_STATE: return -ENOTSUPP; default: return -EINVAL; } Lines 1–500 of 1129. Load more
// SPDX-License-Identifier: GPL-2.0 /* * SP7021 Pin Controller Driver. * Copyright (C) Sunplus Tech / Tibbo Tech. */ #include <linux/cleanup.h> #include <linux/bitfield.h> #include <linux/device.h> #include <linux/err.h> #include <linux/gpio/driver.h> #include <linux/init.h> #include <linux/module.h> #include <linux/of.h> #include <linux/overflow.h> #include <linux/platform_device.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinmux.h> #include <dt-bindings/pinctrl/sppctl-sp7021.h> #include "../core.h" #include "../pinctrl-utils.h" #include "sppctl.h" struct sppctl_gpio_chip { void __iomem *gpioxt_base; /* MASTER, OE, OUT, IN, I_INV, O_INV, OD */ void __iomem *first_base; /* GPIO_FIRST */ struct gpio_chip chip; spinlock_t lock; /* lock for accessing OE register */ }; static inline u32 sppctl_first_readl(struct sppctl_gpio_chip *spp_gchip, u32 off) { return readl(spp_gchip->first_base + SPPCTL_GPIO_OFF_FIRST + off); } static inline void sppctl_first_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off) { writel(val, spp_gchip->first_base + SPPCTL_GPIO_OFF_FIRST + off); } static inline u32 sppctl_gpio_master_readl(struct sppctl_gpio_chip *spp_gchip, u32 off) { return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_MASTER + off); } static inline void sppctl_gpio_master_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off) { writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_MASTER + off); } static inline u32 sppctl_gpio_oe_readl(struct sppctl_gpio_chip *spp_gchip, u32 off) { return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OE + off); } static inline void sppctl_gpio_oe_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off) { writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OE + off); } static inline void sppctl_gpio_out_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off) { writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OUT + off); } static inline u32 sppctl_gpio_in_readl(struct sppctl_gpio_chip *spp_gchip, u32 off) { return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IN + off); } static inline u32 sppctl_gpio_iinv_readl(struct sppctl_gpio_chip *spp_gchip, u32 off) { return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IINV + off); } static inline void sppctl_gpio_iinv_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off) { writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IINV + off); } static inline u32 sppctl_gpio_oinv_readl(struct sppctl_gpio_chip *spp_gchip, u32 off) { return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OINV + off); } static inline void sppctl_gpio_oinv_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off) { writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OINV + off); } static inline u32 sppctl_gpio_od_readl(struct sppctl_gpio_chip *spp_gchip, u32 off) { return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OD + off); } static inline void sppctl_gpio_od_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off) { writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OD + off); } static inline u32 sppctl_get_reg_and_bit_offset(unsigned int offset, u32 *reg_off) { u32 bit_off; /* Each register has 32 bits. */ *reg_off = (offset / 32) * 4; bit_off = offset % 32; return bit_off; } static inline u32 sppctl_get_moon_reg_and_bit_offset(unsigned int offset, u32 *reg_off) { u32 bit_off; /* * Each MOON register has 32 bits. Upper 16-bit word are mask-fields. * The lower 16-bit word are the control-fields. The corresponding * bits in mask-field should be set then you can write something to * control-field. */ *reg_off = (offset / 16) * 4; bit_off = offset % 16; return bit_off; } static inline u32 sppctl_prep_moon_reg_and_offset(unsigned int offset, u32 *reg_off, int val) { u32 bit_off; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, reg_off); if (val) return SPPCTL_SET_MOON_REG_BIT(bit_off); else return SPPCTL_CLR_MOON_REG_BIT(bit_off); } /** * sppctl_func_set() - Set pin of fully-pinmux function. * * Mask-fields and control-fields of fully-pinmux function of SP7021 are * arranged as shown below: * * func# | register | mask-field | control-field * -------+----------+--------------+--------------- * 0 | base[0] | (22 : 16) | ( 6 : 0) * 1 | base[0] | (30 : 24) | (14 : 8) * 2 | base[1] | (22 : 16) | ( 6 : 0) * 3 | baeg[1] | (30 : 24) | (14 : 8) * : | : | : | : * * where mask-fields are used to protect control-fields from write-in * accidentally. Set the corresponding bits in the mask-field before * you write a value into a control-field. * * Control-fields are used to set where the function pin is going to * be routed to. * * Note that mask-fields and control-fields of even number of 'func' * are located at bits (22:16) and (6:0), while odd number of 'func's * are located at bits (30:24) and (14:8). */ static void sppctl_func_set(struct sppctl_pdata *pctl, u8 func, u8 val) { u32 reg, offset; /* * Note that upper 16-bit word are mask-fields and lower 16-bit * word are the control-fields. Set corresponding bits in mask- * field before write to a control-field. */ reg = SPPCTL_FULLY_PINMUX_MASK_MASK | val; /* * MUXF_L2SW_CLK_OUT is the first fully-pinmux pin * and its register offset is 0. */ func -= MUXF_L2SW_CLK_OUT; /* * Check if 'func' is an odd number or not. Mask and control- * fields of odd number 'func' is located at upper portion of * a register. Extra shift is needed. */ if (func & BIT(0)) reg <<= SPPCTL_FULLY_PINMUX_UPPER_SHIFT; /* Convert func# to register offset w.r.t. base register. */ offset = func * 2; offset &= GENMASK(31, 2); writel(reg, pctl->moon2_base + offset); } /** * sppctl_gmx_set() - Set pin of group-pinmux. * * Mask-fields and control-fields of group-pinmux function of SP7021 are * arranged as shown below: * * register | mask-fields | control-fields * ----------+--------------+---------------- * base[0] | (31 : 16) | (15 : 0) * base[1] | (31 : 24) | (15 : 0) * base[2] | (31 : 24) | (15 : 0) * : | : | : * * where mask-fields are used to protect control-fields from write-in * accidentally. Set the corresponding bits in the mask-field before * you write a value into a control-field. * * Control-fields are used to set where the function pin is going to * be routed to. A control-field consists of one or more bits. */ static void sppctl_gmx_set(struct sppctl_pdata *pctl, u8 reg_off, u8 bit_off, u8 bit_sz, u8 val) { u32 mask, reg; /* * Note that upper 16-bit word are mask-fields and lower 16-bit * word are the control-fields. Set corresponding bits in mask- * field before write to a control-field. */ mask = GENMASK(bit_sz - 1, 0) << SPPCTL_MOON_REG_MASK_SHIFT; reg = (mask | val) << bit_off; writel(reg, pctl->moon1_base + reg_off * 4); } /** * sppctl_first_get() - get bit of FIRST register. * * There are 4 FIRST registers. Each has 32 control-bits. * Totally, there are 4 * 32 = 128 control-bits. * Control-bits are arranged as shown below: * * registers | control-bits * -----------+-------------- * first[0] | (31 : 0) * first[1] | (63 : 32) * first[2] | (95 : 64) * first[3] | (127 : 96) * * Each control-bit sets type of a GPIO pin. * 0: a fully-pinmux pin * 1: a GPIO or IOP pin */ static int sppctl_first_get(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off); reg = sppctl_first_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0; } /** * sppctl_master_get() - get bit of MASTER register. * * There are 8 MASTER registers. Each has 16 mask-bits and 16 control-bits. * Upper 16-bit of MASTER registers are mask-bits while lower 16-bit are * control-bits. Totally, there are 128 mask-bits and 128 control-bits. * They are arranged as shown below: * * register | mask-bits | control-bits * -----------+-------------+-------------- * master[0] | (15 : 0) | (15 : 0) * master[1] | (31 : 16) | (31 : 16) * master[2] | (47 : 32) | (47 : 32) * : | : | : * master[7] | (127 : 112) | (127 : 112) * * where mask-bits are used to protect control-bits from write-in * accidentally. Set the corresponding mask-bit before you write * a value into a control-bit. * * Each control-bit sets type of a GPIO pin when FIRST bit is 1. * 0: a IOP pin * 1: a GPIO pin */ static int sppctl_master_get(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_master_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0; } static void sppctl_first_master_set(struct gpio_chip *chip, unsigned int offset, enum mux_first_reg first, enum mux_master_reg master) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; enum mux_first_reg val; /* FIRST register */ if (first != mux_f_keep) { bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off); reg = sppctl_first_readl(spp_gchip, reg_off); val = (reg & BIT(bit_off)) ? mux_f_gpio : mux_f_mux; if (first != val) switch (first) { case mux_f_gpio: reg |= BIT(bit_off); sppctl_first_writel(spp_gchip, reg, reg_off); break; case mux_f_mux: reg &= ~BIT(bit_off); sppctl_first_writel(spp_gchip, reg, reg_off); break; case mux_f_keep: break; } } /* MASTER register */ if (master != mux_m_keep) { reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, (master == mux_m_gpio)); sppctl_gpio_master_writel(spp_gchip, reg, reg_off); } } static void sppctl_gpio_input_inv_set(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); sppctl_gpio_iinv_writel(spp_gchip, reg, reg_off); } static void sppctl_gpio_output_inv_set(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); sppctl_gpio_oinv_writel(spp_gchip, reg, reg_off); } static int sppctl_gpio_output_od_get(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_od_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0; } static void sppctl_gpio_output_od_set(struct gpio_chip *chip, unsigned int offset, unsigned int val) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val); sppctl_gpio_od_writel(spp_gchip, reg, reg_off); } static int sppctl_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_oe_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 0 : 1; } static int sppctl_gpio_inv_get(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; unsigned long flags; bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off); spin_lock_irqsave(&spp_gchip->lock, flags); if (sppctl_gpio_get_direction(chip, offset)) reg = sppctl_gpio_iinv_readl(spp_gchip, reg_off); else reg = sppctl_gpio_oinv_readl(spp_gchip, reg_off); spin_unlock_irqrestore(&spp_gchip->lock, flags); return (reg & BIT(bit_off)) ? 1 : 0; } static int sppctl_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); unsigned long flags; u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 0); spin_lock_irqsave(&spp_gchip->lock, flags); sppctl_gpio_oe_writel(spp_gchip, reg, reg_off); spin_unlock_irqrestore(&spp_gchip->lock, flags); return 0; } static int sppctl_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int val) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); unsigned long flags; u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); spin_lock_irqsave(&spp_gchip->lock, flags); sppctl_gpio_oe_writel(spp_gchip, reg, reg_off); if (val < 0) { spin_unlock_irqrestore(&spp_gchip->lock, flags); return 0; } reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val); sppctl_gpio_out_writel(spp_gchip, reg, reg_off); spin_unlock_irqrestore(&spp_gchip->lock, flags); return 0; } static int sppctl_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, bit_off, reg; bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off); reg = sppctl_gpio_in_readl(spp_gchip, reg_off); return (reg & BIT(bit_off)) ? 1 : 0; } static int sppctl_gpio_set(struct gpio_chip *chip, unsigned int offset, int val) { struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val); sppctl_gpio_out_writel(spp_gchip, reg, reg_off); return 0; } static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset, unsigned long config) { enum pin_config_param param = pinconf_to_config_param(config); struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip); u32 reg_off, reg; switch (param) { case PIN_CONFIG_DRIVE_OPEN_DRAIN: reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1); sppctl_gpio_od_writel(spp_gchip, reg, reg_off); break; case PIN_CONFIG_INPUT_ENABLE: break; case PIN_CONFIG_LEVEL: return sppctl_gpio_direction_output(chip, offset, 0); case PIN_CONFIG_PERSIST_STATE: return -ENOTSUPP; default: return -EINVAL; }