162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2008 Simtec Electronics 462306a36Sopenharmony_ci * http://armlinux.simtec.co.uk/ 562306a36Sopenharmony_ci * Ben Dooks <ben@simtec.co.uk> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * S3C Platform - GPIO core 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef __PLAT_SAMSUNG_GPIO_CORE_H 1162306a36Sopenharmony_ci#define __PLAT_SAMSUNG_GPIO_CORE_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* Bring in machine-local definitions, especially S3C_GPIO_END */ 1462306a36Sopenharmony_ci#include "gpio-samsung.h" 1562306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define GPIOCON_OFF (0x00) 1862306a36Sopenharmony_ci#define GPIODAT_OFF (0x04) 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define con_4bit_shift(__off) ((__off) * 4) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* Define the core gpiolib support functions that the s3c platforms may 2362306a36Sopenharmony_ci * need to extend or change depending on the hardware and the s3c chip 2462306a36Sopenharmony_ci * selected at build or found at run time. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * These definitions are not intended for driver inclusion, there is 2762306a36Sopenharmony_ci * nothing here that should not live outside the platform and core 2862306a36Sopenharmony_ci * specific code. 2962306a36Sopenharmony_ci*/ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistruct samsung_gpio_chip; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/** 3462306a36Sopenharmony_ci * struct samsung_gpio_pm - power management (suspend/resume) information 3562306a36Sopenharmony_ci * @save: Routine to save the state of the GPIO block 3662306a36Sopenharmony_ci * @resume: Routine to resume the GPIO block. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_cistruct samsung_gpio_pm { 3962306a36Sopenharmony_ci void (*save)(struct samsung_gpio_chip *chip); 4062306a36Sopenharmony_ci void (*resume)(struct samsung_gpio_chip *chip); 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistruct samsung_gpio_cfg; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/** 4662306a36Sopenharmony_ci * struct samsung_gpio_chip - wrapper for specific implementation of gpio 4762306a36Sopenharmony_ci * @chip: The chip structure to be exported via gpiolib. 4862306a36Sopenharmony_ci * @base: The base pointer to the gpio configuration registers. 4962306a36Sopenharmony_ci * @group: The group register number for gpio interrupt support. 5062306a36Sopenharmony_ci * @irq_base: The base irq number. 5162306a36Sopenharmony_ci * @config: special function and pull-resistor control information. 5262306a36Sopenharmony_ci * @lock: Lock for exclusive access to this gpio bank. 5362306a36Sopenharmony_ci * @pm_save: Save information for suspend/resume support. 5462306a36Sopenharmony_ci * @bitmap_gpio_int: Bitmap for representing GPIO interrupt or not. 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * This wrapper provides the necessary information for the Samsung 5762306a36Sopenharmony_ci * specific gpios being registered with gpiolib. 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * The lock protects each gpio bank from multiple access of the shared 6062306a36Sopenharmony_ci * configuration registers, or from reading of data whilst another thread 6162306a36Sopenharmony_ci * is writing to the register set. 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * Each chip has its own lock to avoid any contention between different 6462306a36Sopenharmony_ci * CPU cores trying to get one lock for different GPIO banks, where each 6562306a36Sopenharmony_ci * bank of GPIO has its own register space and configuration registers. 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_cistruct samsung_gpio_chip { 6862306a36Sopenharmony_ci struct gpio_chip chip; 6962306a36Sopenharmony_ci struct samsung_gpio_cfg *config; 7062306a36Sopenharmony_ci struct samsung_gpio_pm *pm; 7162306a36Sopenharmony_ci void __iomem *base; 7262306a36Sopenharmony_ci int irq_base; 7362306a36Sopenharmony_ci int group; 7462306a36Sopenharmony_ci spinlock_t lock; 7562306a36Sopenharmony_ci#ifdef CONFIG_PM 7662306a36Sopenharmony_ci u32 pm_save[4]; 7762306a36Sopenharmony_ci#endif 7862306a36Sopenharmony_ci u32 bitmap_gpio_int; 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci return container_of(gpc, struct samsung_gpio_chip, chip); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/** 8762306a36Sopenharmony_ci * samsung_gpiolib_to_irq - convert gpio pin to irq number 8862306a36Sopenharmony_ci * @chip: The gpio chip that the pin belongs to. 8962306a36Sopenharmony_ci * @offset: The offset of the pin in the chip. 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * This helper returns the irq number calculated from the chip->irq_base and 9262306a36Sopenharmony_ci * the provided offset. 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_ciextern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#ifdef CONFIG_S3C_GPIO_TRACK 9762306a36Sopenharmony_ciextern struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END]; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chip) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci#else 10462306a36Sopenharmony_ci/* machine specific code should provide samsung_gpiolib_getchip */ 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ciextern struct samsung_gpio_chip s3c24xx_gpios[]; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci struct samsung_gpio_chip *chip; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (pin > S3C_GPIO_END) 11362306a36Sopenharmony_ci return NULL; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci chip = &s3c24xx_gpios[pin/32]; 11662306a36Sopenharmony_ci return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { } 12062306a36Sopenharmony_ci#endif 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#ifdef CONFIG_PM 12362306a36Sopenharmony_ciextern struct samsung_gpio_pm samsung_gpio_pm_1bit; 12462306a36Sopenharmony_ciextern struct samsung_gpio_pm samsung_gpio_pm_2bit; 12562306a36Sopenharmony_ciextern struct samsung_gpio_pm samsung_gpio_pm_4bit; 12662306a36Sopenharmony_ci#define __gpio_pm(x) x 12762306a36Sopenharmony_ci#else 12862306a36Sopenharmony_ci#define samsung_gpio_pm_1bit NULL 12962306a36Sopenharmony_ci#define samsung_gpio_pm_2bit NULL 13062306a36Sopenharmony_ci#define samsung_gpio_pm_4bit NULL 13162306a36Sopenharmony_ci#define __gpio_pm(x) NULL 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#endif /* CONFIG_PM */ 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci/* locking wrappers to deal with multiple access to the same gpio bank */ 13662306a36Sopenharmony_ci#define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) 13762306a36Sopenharmony_ci#define samsung_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#endif /* __PLAT_SAMSUNG_GPIO_CORE_H */ 140