All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 05/10] superio: Add SMSC SIO1007 driver
Date: Fri, 18 Dec 2015 19:52:07 -0700	[thread overview]
Message-ID: <CAPnjgZ2OwQR5dOLWWnZLuA7+Rd9je65Fp2QneVyyo=2P4iLpCg@mail.gmail.com> (raw)
In-Reply-To: <1449831353-933-6-git-send-email-bmeng.cn@gmail.com>

Hi Bin,

On 11 December 2015 at 03:55, Bin Meng <bmeng.cn@gmail.com> wrote:
> The SMSC SIO1007 superio chipset integrates two ns16550 compatible
> serial ports for legacy applications, 16 GPIO pins and some other
> functionalities like power management.
>
> This adds a simple driver to enable serial port and handle GPIO.
>
> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
> ---
>
>  drivers/misc/Makefile       |   1 +
>  drivers/misc/smsc_sio1007.c | 126 ++++++++++++++++++++++++++++++++++++++++++++
>  include/smsc_sio1007.h      | 115 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 242 insertions(+)
>  create mode 100644 drivers/misc/smsc_sio1007.c
>  create mode 100644 include/smsc_sio1007.h
>
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index aa137f5..6952f8ce 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -29,6 +29,7 @@ ifdef CONFIG_DM_I2C
>  obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
>  endif
>  obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
> +obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
>  obj-$(CONFIG_STATUS_LED) += status_led.o
>  obj-$(CONFIG_SANDBOX) += swap_case.o
>  obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
> diff --git a/drivers/misc/smsc_sio1007.c b/drivers/misc/smsc_sio1007.c
> new file mode 100644
> index 0000000..79e9e15
> --- /dev/null
> +++ b/drivers/misc/smsc_sio1007.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <errno.h>
> +#include <smsc_sio1007.h>
> +
> +static inline u8 sio1007_read(int port, int reg)
> +{
> +       outb(reg, port);
> +
> +       return inb(port + 1);
> +}
> +
> +static inline void sio1007_write(int port, int reg, int val)
> +{
> +       outb(reg, port);
> +       outb(val, port + 1);
> +}
> +
> +static inline void sio1007_clrsetbits(int port, int reg, u8 clr, u8 set)
> +{
> +       sio1007_write(port, reg, (sio1007_read(port, reg) & ~clr) | set);
> +}
> +
> +void sio1007_enable_serial(int port, int num, int iobase, int irq)
> +{
> +       if (num < 0 || num > SIO1007_UART_NUM)
> +               return;
> +
> +       /* enter configuration state */
> +       outb(0x55, port);
> +
> +       /* power on serial port and set up its i/o base & irq */
> +       if (!num) {
> +               sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART1_POWER_ON);
> +               sio1007_clrsetbits(port, UART1_IOBASE, 0xfe, iobase >> 2);
> +               sio1007_clrsetbits(port, UART_IRQ, 0xf0, irq << 4);
> +       } else {
> +               sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART2_POWER_ON);
> +               sio1007_clrsetbits(port, UART2_IOBASE, 0xfe, iobase >> 2);
> +               sio1007_clrsetbits(port, UART_IRQ, 0x0f, irq);
> +       }
> +
> +       /* exit configuration state */
> +       outb(0xaa, port);
> +}
> +
> +void sio1007_enable_runtime(int port, int iobase)
> +{
> +       /* enter configuration state */
> +       outb(0x55, port);
> +
> +       /* set i/o base for the runtime register block */
> +       sio1007_clrsetbits(port, RTR_IOBASE_LOW, 0, iobase >> 4);
> +       sio1007_clrsetbits(port, RTR_IOBASE_HIGH, 0, iobase >> 12);
> +       /* turn on address decoding for this block */
> +       sio1007_clrsetbits(port, DEV_ACTIVATE, 0, RTR_EN);
> +
> +       /* exit configuration state */
> +       outb(0xaa, port);
> +}
> +
> +void sio1007_gpio_config(int port, int gpio, int dir, int pol, int type)
> +{
> +       int reg = GPIO0_DIR;
> +
> +       if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
> +               return;
> +       if (gpio >= GPIO_NUM_PER_GROUP) {
> +               reg = GPIO1_DIR;
> +               gpio -= GPIO_NUM_PER_GROUP;
> +       }
> +
> +       /* enter configuration state */
> +       outb(0x55, port);
> +
> +       /* set gpio pin direction, polority and type */
> +       sio1007_clrsetbits(port, reg, 1 << gpio, dir << gpio);
> +       sio1007_clrsetbits(port, reg + 1, 1 << gpio, pol << gpio);
> +       sio1007_clrsetbits(port, reg + 2, 1 << gpio, type << gpio);
> +
> +       /* exit configuration state */
> +       outb(0xaa, port);
> +}
> +
> +int sio1007_gpio_get_value(int port, int gpio)
> +{
> +       int reg = GPIO0_DATA;
> +       int val;
> +
> +       if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
> +               return -EINVAL;
> +       if (gpio >= GPIO_NUM_PER_GROUP) {
> +               reg = GPIO1_DATA;
> +               gpio -= GPIO_NUM_PER_GROUP;
> +       }
> +
> +       val = inb(port + reg);
> +       if (val & (1 << gpio))
> +               return 1;
> +       else
> +               return 0;
> +}
> +
> +void sio1007_gpio_set_value(int port, int gpio, int val)
> +{
> +       int reg = GPIO0_DATA;
> +       u8 data;
> +
> +       if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
> +               return;
> +       if (gpio >= GPIO_NUM_PER_GROUP) {
> +               reg = GPIO1_DATA;
> +               gpio -= GPIO_NUM_PER_GROUP;
> +       }
> +
> +       data = inb(port + reg);
> +       data &= ~(1 << gpio);
> +       data |= (val << gpio);
> +       outb(data, port + reg);
> +}

This should be modeled as a GPIO driver in the GPIO uclass.

> diff --git a/include/smsc_sio1007.h b/include/smsc_sio1007.h
> new file mode 100644
> index 0000000..eff57a7
> --- /dev/null
> +++ b/include/smsc_sio1007.h
> @@ -0,0 +1,115 @@
> +/*
> + * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef _SMSC_SIO1007_H_
> +#define _SMSC_SIO1007_H_
> +
> +/*
> + * The I/O base address of SIO1007 at power-up is determined by the SYSOPT0
> + * and SYSOPT1 pins at the deasserting edge of PCIRST#. The combination of
> + * SYSOPT0 and SYSOPT1 determines one of the following addresses.
> + */
> +#define SIO1007_IOPORT0                0x002e
> +#define SIO1007_IOPORT1                0x004e
> +#define SIO1007_IOPORT2                0x162e
> +#define SIO1007_IOPORT3                0x164e
> +
> +/* SIO1007 registers */
> +
> +#define DEV_POWER_CTRL         0x02
> +#define UART1_POWER_ON         (1 << 3)
> +#define UART2_POWER_ON         (1 << 7)
> +
> +#define UART1_IOBASE           0x24
> +#define UART2_IOBASE           0x25
> +#define UART_IRQ               0x28
> +
> +#define RTR_IOBASE_HIGH                0x21
> +#define RTR_IOBASE_LOW         0x30
> +
> +#define GPIO0_DIR              0x31
> +#define GPIO1_DIR              0x35
> +#define GPIO_DIR_INPUT         0
> +#define GPIO_DIR_OUTPUT                1
> +
> +#define GPIO0_POL              0x32
> +#define GPIO1_POL              0x36
> +#define GPIO_POL_NO_INVERT     0
> +#define GPIO_POL_INVERT                1
> +
> +#define GPIO0_TYPE             0x33
> +#define GPIO1_TYPE             0x37
> +#define GPIO_TYPE_PUSH_PULL    0
> +#define GPIO_TYPE_OPEN_DRAIN   1
> +
> +#define DEV_ACTIVATE           0x3a
> +#define RTR_EN                 (1 << 1)
> +
> +/* Runtime register offset */
> +
> +#define GPIO0_DATA             0xc
> +#define GPIO1_DATA             0xe
> +
> +/* Number of serial ports supported */
> +#define SIO1007_UART_NUM       2
> +
> +/* Number of gpio pins supported */
> +#define GPIO_NUM_PER_GROUP     8
> +#define GPIO_GROUP_NUM         2
> +#define SIO1007_GPIO_NUM       (GPIO_NUM_PER_GROUP * GPIO_GROUP_NUM)
> +
> +/**
> + * Configure the I/O port address of the specified serial device and
> + * enable the serial device.
> + *
> + * @port:      SIO1007 I/O port address
> + * @num:       serial device number (0 or 1)
> + * @iobase:    processor I/O port address to assign to this serial device
> + * @irq:       processor IRQ number to assign to this serial device
> + */
> +void sio1007_enable_serial(int port, int num, int iobase, int irq);

I wonder if we need a parent device which provides access to these
features, and then a GPIO child device?

> +
> +/**
> + * Configure the I/O port address of the runtime register block and
> + * enable the address decoding.
> + *
> + * @port:      SIO1007 I/O port address
> + * @iobase:    processor I/O port address to assign to the runtime registers
> + */
> +void sio1007_enable_runtime(int port, int iobase);
> +
> +/**
> + * Configure the direction/polority/type of a specified GPIO pin
> + *
> + * @port:      SIO1007 I/O port address
> + * @gpio:      GPIO number (0-7 for GP10-GP17, 8-15 for GP30-GP37)
> + * @dir:       GPIO_DIR_INPUT or GPIO_DIR_OUTPUT
> + * @pol:       GPIO_POL_NO_INVERT or GPIO_POL_INVERT
> + * @type:      GPIO_TYPE_PUSH_PULL or GPIO_TYPE_OPEN_DRAIN
> + */
> +void sio1007_gpio_config(int port, int gpio, int dir, int pol, int type);
> +
> +/**
> + * Get a GPIO pin value.
> + * This will work whether the GPIO is an input or an output.
> + *
> + * @port:      runtime register block I/O port address
> + * @gpio:      GPIO number (0-7 for GP10-GP17, 8-15 for GP30-GP37)
> + * @return:    0 if low, 1 if high, -EINVAL if gpio number is invalid
> + */
> +int sio1007_gpio_get_value(int port, int gpio);
> +
> +/**
> + * Set a GPIO pin value.
> + * This will only work when the GPIO is configured as an output.
> + *
> + * @port:      runtime register block I/O port address
> + * @gpio:      GPIO number (0-7 for GP10-GP17, 8-15 for GP30-GP37)
> + * @val:       0 if low, 1 if high
> + */
> +void sio1007_gpio_set_value(int port, int gpio, int val);
> +
> +#endif /* _SMSC_SIO1007_H_ */
> --
> 1.8.2.1
>


Regards,
Simon

  reply	other threads:[~2015-12-19  2:52 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-11 10:55 [U-Boot] [PATCH 00/10] x86: ivybridge: Add Intel FSP support Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 01/10] fdtdec: Add compatible string for Intel IvyBridge FSP Bin Meng
2015-12-19  2:51   ` Simon Glass
2015-12-21  2:33     ` Bin Meng
2016-02-06  4:29       ` Bin Meng
2016-02-19 20:56         ` Simon Glass
2015-12-21  7:50     ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 02/10] x86: ivybridge: Add FSP support Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  2:27     ` Bin Meng
2015-12-23 16:44       ` Simon Glass
2015-12-23 22:48         ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 03/10] tools: microcode-tool: Support parsing header file with a license block Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  7:50     ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 04/10] x86: ivybridge: Add microcode blobs for all the steppings Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  7:50     ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 05/10] superio: Add SMSC SIO1007 driver Bin Meng
2015-12-19  2:52   ` Simon Glass [this message]
2015-12-21  2:42     ` Bin Meng
2016-01-06  0:24       ` Simon Glass
2016-01-26  8:29         ` Bin Meng
2016-01-26 17:03           ` Simon Glass
2015-12-11 10:55 ` [U-Boot] [PATCH 06/10] x86: ivybridge: Do not require HAVE_INTEL_ME Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  7:50     ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 07/10] x86: fsp: Make sure HOB list is not overwritten by U-Boot Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  2:36     ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 08/10] x86: fsp: Always use hex numbers in the hob command output Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  7:50     ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 09/10] x86: ivybridge: Add macros for LPC decode ranges Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  7:50     ` Bin Meng
2015-12-11 10:55 ` [U-Boot] [PATCH 10/10] x86: Add Intel Cougar Canyon 2 board Bin Meng
2015-12-19  2:52   ` Simon Glass
2015-12-21  2:34     ` Bin Meng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAPnjgZ2OwQR5dOLWWnZLuA7+Rd9je65Fp2QneVyyo=2P4iLpCg@mail.gmail.com' \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.