linux/drivers/gpio/gpio-winbond.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * GPIO interface for Winbond Super I/O chips
 * Currently, only W83627UHG (Nuvoton NCT6627UD) is supported.
 *
 * Author: Maciej S. Szmigiero <[email protected]>
 */

#define pr_fmt(fmt)

#include <linux/gpio/driver.h>
#include <linux/ioport.h>
#include <linux/isa.h>
#include <linux/module.h>

#define WB_GPIO_DRIVER_NAME

#define WB_SIO_BASE
#define WB_SIO_BASE_HIGH

#define WB_SIO_EXT_ENTER_KEY
#define WB_SIO_EXT_EXIT_KEY

/* global chip registers */

#define WB_SIO_REG_LOGICAL

#define WB_SIO_REG_CHIP_MSB
#define WB_SIO_REG_CHIP_LSB

#define WB_SIO_CHIP_ID_W83627UHG
#define WB_SIO_CHIP_ID_W83627UHG_MASK

#define WB_SIO_REG_DPD
#define WB_SIO_REG_DPD_UARTA
#define WB_SIO_REG_DPD_UARTB

#define WB_SIO_REG_IDPD
#define WB_SIO_REG_IDPD_UARTC
#define WB_SIO_REG_IDPD_UARTD
#define WB_SIO_REG_IDPD_UARTE
#define WB_SIO_REG_IDPD_UARTF

#define WB_SIO_REG_GLOBAL_OPT
#define WB_SIO_REG_GO_ENFDC

#define WB_SIO_REG_OVTGPIO3456
#define WB_SIO_REG_OG3456_G3PP
#define WB_SIO_REG_OG3456_G4PP
#define WB_SIO_REG_OG3456_G5PP
#define WB_SIO_REG_OG3456_G6PP

#define WB_SIO_REG_I2C_PS
#define WB_SIO_REG_I2CPS_I2CFS

#define WB_SIO_REG_GPIO1_MF
#define WB_SIO_REG_G1MF_G1PP
#define WB_SIO_REG_G1MF_G2PP
#define WB_SIO_REG_G1MF_FS_MASK
#define WB_SIO_REG_G1MF_FS_IR_OFF
#define WB_SIO_REG_G1MF_FS_IR
#define WB_SIO_REG_G1MF_FS_GPIO1
#define WB_SIO_REG_G1MF_FS_UARTB

/* not an actual device number, just a value meaning 'no device' */
#define WB_SIO_DEV_NONE

/* registers with offsets >= 0x30 are specific for a particular device */

/* UART B logical device */
#define WB_SIO_DEV_UARTB
#define WB_SIO_UARTB_REG_ENABLE
#define WB_SIO_UARTB_ENABLE_ON

/* UART C logical device */
#define WB_SIO_DEV_UARTC
#define WB_SIO_UARTC_REG_ENABLE
#define WB_SIO_UARTC_ENABLE_ON

/* GPIO3, GPIO4 logical device */
#define WB_SIO_DEV_GPIO34
#define WB_SIO_GPIO34_REG_ENABLE
#define WB_SIO_GPIO34_ENABLE_3
#define WB_SIO_GPIO34_ENABLE_4
#define WB_SIO_GPIO34_REG_IO3
#define WB_SIO_GPIO34_REG_DATA3
#define WB_SIO_GPIO34_REG_INV3
#define WB_SIO_GPIO34_REG_IO4
#define WB_SIO_GPIO34_REG_DATA4
#define WB_SIO_GPIO34_REG_INV4

/* WDTO, PLED, GPIO5, GPIO6 logical device */
#define WB_SIO_DEV_WDGPIO56
#define WB_SIO_WDGPIO56_REG_ENABLE
#define WB_SIO_WDGPIO56_ENABLE_5
#define WB_SIO_WDGPIO56_ENABLE_6
#define WB_SIO_WDGPIO56_REG_IO5
#define WB_SIO_WDGPIO56_REG_DATA5
#define WB_SIO_WDGPIO56_REG_INV5
#define WB_SIO_WDGPIO56_REG_IO6
#define WB_SIO_WDGPIO56_REG_DATA6
#define WB_SIO_WDGPIO56_REG_INV6

/* GPIO1, GPIO2, SUSLED logical device */
#define WB_SIO_DEV_GPIO12
#define WB_SIO_GPIO12_REG_ENABLE
#define WB_SIO_GPIO12_ENABLE_1
#define WB_SIO_GPIO12_ENABLE_2
#define WB_SIO_GPIO12_REG_IO1
#define WB_SIO_GPIO12_REG_DATA1
#define WB_SIO_GPIO12_REG_INV1
#define WB_SIO_GPIO12_REG_IO2
#define WB_SIO_GPIO12_REG_DATA2
#define WB_SIO_GPIO12_REG_INV2

/* UART D logical device */
#define WB_SIO_DEV_UARTD
#define WB_SIO_UARTD_REG_ENABLE
#define WB_SIO_UARTD_ENABLE_ON

/* UART E logical device */
#define WB_SIO_DEV_UARTE
#define WB_SIO_UARTE_REG_ENABLE
#define WB_SIO_UARTE_ENABLE_ON

/*
 * for a description what a particular field of this struct means please see
 * a description of the relevant module parameter at the bottom of this file
 */
struct winbond_gpio_params {};

static struct winbond_gpio_params params;

static int winbond_sio_enter(unsigned long base)
{}

static void winbond_sio_select_logical(unsigned long base, u8 dev)
{}

static void winbond_sio_leave(unsigned long base)
{}

static void winbond_sio_reg_write(unsigned long base, u8 reg, u8 data)
{}

static u8 winbond_sio_reg_read(unsigned long base, u8 reg)
{}

static void winbond_sio_reg_bset(unsigned long base, u8 reg, u8 bit)
{}

static void winbond_sio_reg_bclear(unsigned long base, u8 reg, u8 bit)
{}

static bool winbond_sio_reg_btest(unsigned long base, u8 reg, u8 bit)
{}

/**
 * struct winbond_gpio_port_conflict - possibly conflicting device information
 * @name:	device name (NULL means no conflicting device defined)
 * @dev:	Super I/O logical device number where the testreg register
 *		is located (or WB_SIO_DEV_NONE - don't select any
 *		logical device)
 * @testreg:	register number where the testbit bit is located
 * @testbit:	index of a bit to check whether an actual conflict exists
 * @warnonly:	if set then a conflict isn't fatal (just warn about it),
 *		otherwise disable the particular GPIO port if a conflict
 *		is detected
 */
struct winbond_gpio_port_conflict {};

/**
 * struct winbond_gpio_info - information about a particular GPIO port (device)
 * @dev:		Super I/O logical device number of the registers
 *			specified below
 * @enablereg:		port enable bit register number
 * @enablebit:		index of a port enable bit
 * @outputreg:		output driver mode bit register number
 * @outputppbit:	index of a push-pull output driver mode bit
 * @ioreg:		data direction register number
 * @invreg:		pin data inversion register number
 * @datareg:		pin data register number
 * @conflict:		description of a device that possibly conflicts with
 *			this port
 */
struct winbond_gpio_info {};

static const struct winbond_gpio_info winbond_gpio_infos[6] =;

/* returns whether changing a pin is allowed */
static bool winbond_gpio_get_info(unsigned int *gpio_num,
				  const struct winbond_gpio_info **info)
{}

static int winbond_gpio_get(struct gpio_chip *gc, unsigned int offset)
{}

static int winbond_gpio_direction_in(struct gpio_chip *gc, unsigned int offset)
{}

static int winbond_gpio_direction_out(struct gpio_chip *gc,
				      unsigned int offset,
				      int val)
{}

static void winbond_gpio_set(struct gpio_chip *gc, unsigned int offset,
			     int val)
{}

static struct gpio_chip winbond_gpio_chip =;

static void winbond_gpio_configure_port0_pins(unsigned long base)
{}

static void winbond_gpio_configure_port1_check_i2c(unsigned long base)
{}

static bool winbond_gpio_configure_port(unsigned long base, unsigned int idx)
{}

static int winbond_gpio_configure(unsigned long base)
{}

static int winbond_gpio_check_chip(unsigned long base)
{}

static int winbond_gpio_imatch(struct device *dev, unsigned int id)
{}

static int winbond_gpio_iprobe(struct device *dev, unsigned int id)
{}

static struct isa_driver winbond_gpio_idriver =;

module_isa_driver(winbond_gpio_idriver, 1);

module_param_named(base, params.base, ulong, 0444);
MODULE_PARM_DESC();

/* This parameter sets which GPIO devices (ports) we enable */
module_param_named(gpios, params.gpios, ulong, 0444);
MODULE_PARM_DESC();

/*
 * These two parameters below set how we configure GPIO ports output drivers.
 * It can't be a one bitmask since we need three values per port: push-pull,
 * open-drain and keep as-is (this is the default).
 */
module_param_named(ppgpios, params.ppgpios, ulong, 0444);
MODULE_PARM_DESC();

module_param_named(odgpios, params.odgpios, ulong, 0444);
MODULE_PARM_DESC();

/*
 * GPIO2.0 and GPIO2.1 control a basic PC functionality that we
 * don't allow tinkering with by default (it is very likely that the
 * firmware owns these pins).
 * These two parameters below allow overriding these prohibitions.
 */
module_param_named(pledgpio, params.pledgpio, bool, 0644);
MODULE_PARM_DESC();

module_param_named(beepgpio, params.beepgpio, bool, 0644);
MODULE_PARM_DESC();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();