Path: blob/master/arch/mips/pmc-sierra/msp71xx/gpio.c
15118 views
/*1* Generic PMC MSP71xx GPIO handling. These base gpio are controlled by two2* types of registers. The data register sets the output level when in output3* mode and when in input mode will contain the value at the input. The config4* register sets the various modes for each gpio.5*6* This program is free software; you can redistribute it and/or modify7* it under the terms of the GNU General Public License version 2 as8* published by the Free Software Foundation.9*10* @author Patrick Glass <[email protected]>11*/1213#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/init.h>16#include <linux/gpio.h>17#include <linux/spinlock.h>18#include <linux/io.h>1920#define MSP71XX_CFG_OFFSET(gpio) (4 * (gpio))21#define CONF_MASK 0x0F22#define MSP71XX_GPIO_INPUT 0x0123#define MSP71XX_GPIO_OUTPUT 0x082425#define MSP71XX_GPIO_BASE 0x0B8400000L2627#define to_msp71xx_gpio_chip(c) container_of(c, struct msp71xx_gpio_chip, chip)2829static spinlock_t gpio_lock;3031/*32* struct msp71xx_gpio_chip - container for gpio chip and registers33* @chip: chip structure for the specified gpio bank34* @data_reg: register for reading and writing the gpio pin value35* @config_reg: register to set the mode for the gpio pin bank36* @out_drive_reg: register to set the output drive mode for the gpio pin bank37*/38struct msp71xx_gpio_chip {39struct gpio_chip chip;40void __iomem *data_reg;41void __iomem *config_reg;42void __iomem *out_drive_reg;43};4445/*46* msp71xx_gpio_get() - return the chip's gpio value47* @chip: chip structure which controls the specified gpio48* @offset: gpio whose value will be returned49*50* It will return 0 if gpio value is low and other if high.51*/52static int msp71xx_gpio_get(struct gpio_chip *chip, unsigned offset)53{54struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip);5556return __raw_readl(msp_chip->data_reg) & (1 << offset);57}5859/*60* msp71xx_gpio_set() - set the output value for the gpio61* @chip: chip structure who controls the specified gpio62* @offset: gpio whose value will be assigned63* @value: logic level to assign to the gpio initially64*65* This will set the gpio bit specified to the desired value. It will set the66* gpio pin low if value is 0 otherwise it will be high.67*/68static void msp71xx_gpio_set(struct gpio_chip *chip, unsigned offset, int value)69{70struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip);71unsigned long flags;72u32 data;7374spin_lock_irqsave(&gpio_lock, flags);7576data = __raw_readl(msp_chip->data_reg);77if (value)78data |= (1 << offset);79else80data &= ~(1 << offset);81__raw_writel(data, msp_chip->data_reg);8283spin_unlock_irqrestore(&gpio_lock, flags);84}8586/*87* msp71xx_set_gpio_mode() - declare the mode for a gpio88* @chip: chip structure which controls the specified gpio89* @offset: gpio whose value will be assigned90* @mode: desired configuration for the gpio (see datasheet)91*92* It will set the gpio pin config to the @mode value passed in.93*/94static int msp71xx_set_gpio_mode(struct gpio_chip *chip,95unsigned offset, int mode)96{97struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip);98const unsigned bit_offset = MSP71XX_CFG_OFFSET(offset);99unsigned long flags;100u32 cfg;101102spin_lock_irqsave(&gpio_lock, flags);103104cfg = __raw_readl(msp_chip->config_reg);105cfg &= ~(CONF_MASK << bit_offset);106cfg |= (mode << bit_offset);107__raw_writel(cfg, msp_chip->config_reg);108109spin_unlock_irqrestore(&gpio_lock, flags);110111return 0;112}113114/*115* msp71xx_direction_output() - declare the direction mode for a gpio116* @chip: chip structure which controls the specified gpio117* @offset: gpio whose value will be assigned118* @value: logic level to assign to the gpio initially119*120* This call will set the mode for the @gpio to output. It will set the121* gpio pin low if value is 0 otherwise it will be high.122*/123static int msp71xx_direction_output(struct gpio_chip *chip,124unsigned offset, int value)125{126msp71xx_gpio_set(chip, offset, value);127128return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_OUTPUT);129}130131/*132* msp71xx_direction_input() - declare the direction mode for a gpio133* @chip: chip structure which controls the specified gpio134* @offset: gpio whose to which the value will be assigned135*136* This call will set the mode for the @gpio to input.137*/138static int msp71xx_direction_input(struct gpio_chip *chip, unsigned offset)139{140return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_INPUT);141}142143/*144* msp71xx_set_output_drive() - declare the output drive for the gpio line145* @gpio: gpio pin whose output drive you wish to modify146* @value: zero for active drain 1 for open drain drive147*148* This call will set the output drive mode for the @gpio to output.149*/150int msp71xx_set_output_drive(unsigned gpio, int value)151{152unsigned long flags;153u32 data;154155if (gpio > 15 || gpio < 0)156return -EINVAL;157158spin_lock_irqsave(&gpio_lock, flags);159160data = __raw_readl((void __iomem *)(MSP71XX_GPIO_BASE + 0x190));161if (value)162data |= (1 << gpio);163else164data &= ~(1 << gpio);165__raw_writel(data, (void __iomem *)(MSP71XX_GPIO_BASE + 0x190));166167spin_unlock_irqrestore(&gpio_lock, flags);168169return 0;170}171EXPORT_SYMBOL(msp71xx_set_output_drive);172173#define MSP71XX_GPIO_BANK(name, dr, cr, base_gpio, num_gpio) \174{ \175.chip = { \176.label = name, \177.direction_input = msp71xx_direction_input, \178.direction_output = msp71xx_direction_output, \179.get = msp71xx_gpio_get, \180.set = msp71xx_gpio_set, \181.base = base_gpio, \182.ngpio = num_gpio \183}, \184.data_reg = (void __iomem *)(MSP71XX_GPIO_BASE + dr), \185.config_reg = (void __iomem *)(MSP71XX_GPIO_BASE + cr), \186.out_drive_reg = (void __iomem *)(MSP71XX_GPIO_BASE + 0x190), \187}188189/*190* struct msp71xx_gpio_banks[] - container array of gpio banks191* @chip: chip structure for the specified gpio bank192* @data_reg: register for reading and writing the gpio pin value193* @config_reg: register to set the mode for the gpio pin bank194*195* This array structure defines the gpio banks for the PMC MIPS Processor.196* We specify the bank name, the data register, the config register, base197* starting gpio number, and the number of gpios exposed by the bank.198*/199static struct msp71xx_gpio_chip msp71xx_gpio_banks[] = {200201MSP71XX_GPIO_BANK("GPIO_1_0", 0x170, 0x180, 0, 2),202MSP71XX_GPIO_BANK("GPIO_5_2", 0x174, 0x184, 2, 4),203MSP71XX_GPIO_BANK("GPIO_9_6", 0x178, 0x188, 6, 4),204MSP71XX_GPIO_BANK("GPIO_15_10", 0x17C, 0x18C, 10, 6),205};206207void __init msp71xx_init_gpio(void)208{209int i;210211spin_lock_init(&gpio_lock);212213for (i = 0; i < ARRAY_SIZE(msp71xx_gpio_banks); i++)214gpiochip_add(&msp71xx_gpio_banks[i].chip);215}216217218