162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (C) 2020 Daniel Palmer<daniel@thingy.jp> */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/bitops.h> 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci#include <linux/types.h> 762306a36Sopenharmony_ci#include <linux/io.h> 862306a36Sopenharmony_ci#include <linux/of.h> 962306a36Sopenharmony_ci#include <linux/of_irq.h> 1062306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <dt-bindings/gpio/msc313-gpio.h> 1562306a36Sopenharmony_ci#include <dt-bindings/interrupt-controller/arm-gic.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define DRIVER_NAME "gpio-msc313" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define MSC313_GPIO_IN BIT(0) 2062306a36Sopenharmony_ci#define MSC313_GPIO_OUT BIT(4) 2162306a36Sopenharmony_ci#define MSC313_GPIO_OEN BIT(5) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * These bits need to be saved to correctly restore the 2562306a36Sopenharmony_ci * gpio state when resuming from suspend to memory. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci#define MSC313_GPIO_BITSTOSAVE (MSC313_GPIO_OUT | MSC313_GPIO_OEN) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* pad names for fuart, same for all SoCs so far */ 3062306a36Sopenharmony_ci#define MSC313_PINNAME_FUART_RX "fuart_rx" 3162306a36Sopenharmony_ci#define MSC313_PINNAME_FUART_TX "fuart_tx" 3262306a36Sopenharmony_ci#define MSC313_PINNAME_FUART_CTS "fuart_cts" 3362306a36Sopenharmony_ci#define MSC313_PINNAME_FUART_RTS "fuart_rts" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* pad names for sr, mercury5 is different */ 3662306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO2 "sr_io2" 3762306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO3 "sr_io3" 3862306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO4 "sr_io4" 3962306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO5 "sr_io5" 4062306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO6 "sr_io6" 4162306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO7 "sr_io7" 4262306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO8 "sr_io8" 4362306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO9 "sr_io9" 4462306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO10 "sr_io10" 4562306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO11 "sr_io11" 4662306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO12 "sr_io12" 4762306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO13 "sr_io13" 4862306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO14 "sr_io14" 4962306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO15 "sr_io15" 5062306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO16 "sr_io16" 5162306a36Sopenharmony_ci#define MSC313_PINNAME_SR_IO17 "sr_io17" 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* pad names for sd, same for all SoCs so far */ 5462306a36Sopenharmony_ci#define MSC313_PINNAME_SD_CLK "sd_clk" 5562306a36Sopenharmony_ci#define MSC313_PINNAME_SD_CMD "sd_cmd" 5662306a36Sopenharmony_ci#define MSC313_PINNAME_SD_D0 "sd_d0" 5762306a36Sopenharmony_ci#define MSC313_PINNAME_SD_D1 "sd_d1" 5862306a36Sopenharmony_ci#define MSC313_PINNAME_SD_D2 "sd_d2" 5962306a36Sopenharmony_ci#define MSC313_PINNAME_SD_D3 "sd_d3" 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* pad names for i2c1, same for all SoCs so for */ 6262306a36Sopenharmony_ci#define MSC313_PINNAME_I2C1_SCL "i2c1_scl" 6362306a36Sopenharmony_ci#define MSC313_PINNAME_I2C1_SCA "i2c1_sda" 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* pad names for spi0, same for all SoCs so far */ 6662306a36Sopenharmony_ci#define MSC313_PINNAME_SPI0_CZ "spi0_cz" 6762306a36Sopenharmony_ci#define MSC313_PINNAME_SPI0_CK "spi0_ck" 6862306a36Sopenharmony_ci#define MSC313_PINNAME_SPI0_DI "spi0_di" 6962306a36Sopenharmony_ci#define MSC313_PINNAME_SPI0_DO "spi0_do" 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define FUART_NAMES \ 7262306a36Sopenharmony_ci MSC313_PINNAME_FUART_RX, \ 7362306a36Sopenharmony_ci MSC313_PINNAME_FUART_TX, \ 7462306a36Sopenharmony_ci MSC313_PINNAME_FUART_CTS, \ 7562306a36Sopenharmony_ci MSC313_PINNAME_FUART_RTS 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define OFF_FUART_RX 0x50 7862306a36Sopenharmony_ci#define OFF_FUART_TX 0x54 7962306a36Sopenharmony_ci#define OFF_FUART_CTS 0x58 8062306a36Sopenharmony_ci#define OFF_FUART_RTS 0x5c 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define FUART_OFFSETS \ 8362306a36Sopenharmony_ci OFF_FUART_RX, \ 8462306a36Sopenharmony_ci OFF_FUART_TX, \ 8562306a36Sopenharmony_ci OFF_FUART_CTS, \ 8662306a36Sopenharmony_ci OFF_FUART_RTS 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define SR_NAMES \ 8962306a36Sopenharmony_ci MSC313_PINNAME_SR_IO2, \ 9062306a36Sopenharmony_ci MSC313_PINNAME_SR_IO3, \ 9162306a36Sopenharmony_ci MSC313_PINNAME_SR_IO4, \ 9262306a36Sopenharmony_ci MSC313_PINNAME_SR_IO5, \ 9362306a36Sopenharmony_ci MSC313_PINNAME_SR_IO6, \ 9462306a36Sopenharmony_ci MSC313_PINNAME_SR_IO7, \ 9562306a36Sopenharmony_ci MSC313_PINNAME_SR_IO8, \ 9662306a36Sopenharmony_ci MSC313_PINNAME_SR_IO9, \ 9762306a36Sopenharmony_ci MSC313_PINNAME_SR_IO10, \ 9862306a36Sopenharmony_ci MSC313_PINNAME_SR_IO11, \ 9962306a36Sopenharmony_ci MSC313_PINNAME_SR_IO12, \ 10062306a36Sopenharmony_ci MSC313_PINNAME_SR_IO13, \ 10162306a36Sopenharmony_ci MSC313_PINNAME_SR_IO14, \ 10262306a36Sopenharmony_ci MSC313_PINNAME_SR_IO15, \ 10362306a36Sopenharmony_ci MSC313_PINNAME_SR_IO16, \ 10462306a36Sopenharmony_ci MSC313_PINNAME_SR_IO17 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define OFF_SR_IO2 0x88 10762306a36Sopenharmony_ci#define OFF_SR_IO3 0x8c 10862306a36Sopenharmony_ci#define OFF_SR_IO4 0x90 10962306a36Sopenharmony_ci#define OFF_SR_IO5 0x94 11062306a36Sopenharmony_ci#define OFF_SR_IO6 0x98 11162306a36Sopenharmony_ci#define OFF_SR_IO7 0x9c 11262306a36Sopenharmony_ci#define OFF_SR_IO8 0xa0 11362306a36Sopenharmony_ci#define OFF_SR_IO9 0xa4 11462306a36Sopenharmony_ci#define OFF_SR_IO10 0xa8 11562306a36Sopenharmony_ci#define OFF_SR_IO11 0xac 11662306a36Sopenharmony_ci#define OFF_SR_IO12 0xb0 11762306a36Sopenharmony_ci#define OFF_SR_IO13 0xb4 11862306a36Sopenharmony_ci#define OFF_SR_IO14 0xb8 11962306a36Sopenharmony_ci#define OFF_SR_IO15 0xbc 12062306a36Sopenharmony_ci#define OFF_SR_IO16 0xc0 12162306a36Sopenharmony_ci#define OFF_SR_IO17 0xc4 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#define SR_OFFSETS \ 12462306a36Sopenharmony_ci OFF_SR_IO2, \ 12562306a36Sopenharmony_ci OFF_SR_IO3, \ 12662306a36Sopenharmony_ci OFF_SR_IO4, \ 12762306a36Sopenharmony_ci OFF_SR_IO5, \ 12862306a36Sopenharmony_ci OFF_SR_IO6, \ 12962306a36Sopenharmony_ci OFF_SR_IO7, \ 13062306a36Sopenharmony_ci OFF_SR_IO8, \ 13162306a36Sopenharmony_ci OFF_SR_IO9, \ 13262306a36Sopenharmony_ci OFF_SR_IO10, \ 13362306a36Sopenharmony_ci OFF_SR_IO11, \ 13462306a36Sopenharmony_ci OFF_SR_IO12, \ 13562306a36Sopenharmony_ci OFF_SR_IO13, \ 13662306a36Sopenharmony_ci OFF_SR_IO14, \ 13762306a36Sopenharmony_ci OFF_SR_IO15, \ 13862306a36Sopenharmony_ci OFF_SR_IO16, \ 13962306a36Sopenharmony_ci OFF_SR_IO17 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci#define SD_NAMES \ 14262306a36Sopenharmony_ci MSC313_PINNAME_SD_CLK, \ 14362306a36Sopenharmony_ci MSC313_PINNAME_SD_CMD, \ 14462306a36Sopenharmony_ci MSC313_PINNAME_SD_D0, \ 14562306a36Sopenharmony_ci MSC313_PINNAME_SD_D1, \ 14662306a36Sopenharmony_ci MSC313_PINNAME_SD_D2, \ 14762306a36Sopenharmony_ci MSC313_PINNAME_SD_D3 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#define OFF_SD_CLK 0x140 15062306a36Sopenharmony_ci#define OFF_SD_CMD 0x144 15162306a36Sopenharmony_ci#define OFF_SD_D0 0x148 15262306a36Sopenharmony_ci#define OFF_SD_D1 0x14c 15362306a36Sopenharmony_ci#define OFF_SD_D2 0x150 15462306a36Sopenharmony_ci#define OFF_SD_D3 0x154 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#define SD_OFFSETS \ 15762306a36Sopenharmony_ci OFF_SD_CLK, \ 15862306a36Sopenharmony_ci OFF_SD_CMD, \ 15962306a36Sopenharmony_ci OFF_SD_D0, \ 16062306a36Sopenharmony_ci OFF_SD_D1, \ 16162306a36Sopenharmony_ci OFF_SD_D2, \ 16262306a36Sopenharmony_ci OFF_SD_D3 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#define I2C1_NAMES \ 16562306a36Sopenharmony_ci MSC313_PINNAME_I2C1_SCL, \ 16662306a36Sopenharmony_ci MSC313_PINNAME_I2C1_SCA 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#define OFF_I2C1_SCL 0x188 16962306a36Sopenharmony_ci#define OFF_I2C1_SCA 0x18c 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci#define I2C1_OFFSETS \ 17262306a36Sopenharmony_ci OFF_I2C1_SCL, \ 17362306a36Sopenharmony_ci OFF_I2C1_SCA 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#define SPI0_NAMES \ 17662306a36Sopenharmony_ci MSC313_PINNAME_SPI0_CZ, \ 17762306a36Sopenharmony_ci MSC313_PINNAME_SPI0_CK, \ 17862306a36Sopenharmony_ci MSC313_PINNAME_SPI0_DI, \ 17962306a36Sopenharmony_ci MSC313_PINNAME_SPI0_DO 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#define OFF_SPI0_CZ 0x1c0 18262306a36Sopenharmony_ci#define OFF_SPI0_CK 0x1c4 18362306a36Sopenharmony_ci#define OFF_SPI0_DI 0x1c8 18462306a36Sopenharmony_ci#define OFF_SPI0_DO 0x1cc 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci#define SPI0_OFFSETS \ 18762306a36Sopenharmony_ci OFF_SPI0_CZ, \ 18862306a36Sopenharmony_ci OFF_SPI0_CK, \ 18962306a36Sopenharmony_ci OFF_SPI0_DI, \ 19062306a36Sopenharmony_ci OFF_SPI0_DO 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistruct msc313_gpio_data { 19362306a36Sopenharmony_ci const char * const *names; 19462306a36Sopenharmony_ci const unsigned int *offsets; 19562306a36Sopenharmony_ci const unsigned int num; 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci#define MSC313_GPIO_CHIPDATA(_chip) \ 19962306a36Sopenharmony_cistatic const struct msc313_gpio_data _chip##_data = { \ 20062306a36Sopenharmony_ci .names = _chip##_names, \ 20162306a36Sopenharmony_ci .offsets = _chip##_offsets, \ 20262306a36Sopenharmony_ci .num = ARRAY_SIZE(_chip##_offsets), \ 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci#ifdef CONFIG_MACH_INFINITY 20662306a36Sopenharmony_cistatic const char * const msc313_names[] = { 20762306a36Sopenharmony_ci FUART_NAMES, 20862306a36Sopenharmony_ci SR_NAMES, 20962306a36Sopenharmony_ci SD_NAMES, 21062306a36Sopenharmony_ci I2C1_NAMES, 21162306a36Sopenharmony_ci SPI0_NAMES, 21262306a36Sopenharmony_ci}; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic const unsigned int msc313_offsets[] = { 21562306a36Sopenharmony_ci FUART_OFFSETS, 21662306a36Sopenharmony_ci SR_OFFSETS, 21762306a36Sopenharmony_ci SD_OFFSETS, 21862306a36Sopenharmony_ci I2C1_OFFSETS, 21962306a36Sopenharmony_ci SPI0_OFFSETS, 22062306a36Sopenharmony_ci}; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ciMSC313_GPIO_CHIPDATA(msc313); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/* 22562306a36Sopenharmony_ci * Unlike the msc313(e) the ssd20xd have a bunch of pins 22662306a36Sopenharmony_ci * that are actually called gpio probably because they 22762306a36Sopenharmony_ci * have no dedicated function. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO0 "gpio0" 23062306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO1 "gpio1" 23162306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO2 "gpio2" 23262306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO3 "gpio3" 23362306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO4 "gpio4" 23462306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO5 "gpio5" 23562306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO6 "gpio6" 23662306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO7 "gpio7" 23762306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO10 "gpio10" 23862306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO11 "gpio11" 23962306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO12 "gpio12" 24062306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO13 "gpio13" 24162306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO14 "gpio14" 24262306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO85 "gpio85" 24362306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO86 "gpio86" 24462306a36Sopenharmony_ci#define SSD20XD_PINNAME_GPIO90 "gpio90" 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define SSD20XD_GPIO_NAMES SSD20XD_PINNAME_GPIO0, \ 24762306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO1, \ 24862306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO2, \ 24962306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO3, \ 25062306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO4, \ 25162306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO5, \ 25262306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO6, \ 25362306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO7, \ 25462306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO10, \ 25562306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO11, \ 25662306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO12, \ 25762306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO13, \ 25862306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO14, \ 25962306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO85, \ 26062306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO86, \ 26162306a36Sopenharmony_ci SSD20XD_PINNAME_GPIO90 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO0 0x0 26462306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO1 0x4 26562306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO2 0x8 26662306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO3 0xc 26762306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO4 0x10 26862306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO5 0x14 26962306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO6 0x18 27062306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO7 0x1c 27162306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO10 0x28 27262306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO11 0x2c 27362306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO12 0x30 27462306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO13 0x34 27562306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO14 0x38 27662306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO85 0x100 27762306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO86 0x104 27862306a36Sopenharmony_ci#define SSD20XD_GPIO_OFF_GPIO90 0x114 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci#define SSD20XD_GPIO_OFFSETS SSD20XD_GPIO_OFF_GPIO0, \ 28162306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO1, \ 28262306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO2, \ 28362306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO3, \ 28462306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO4, \ 28562306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO5, \ 28662306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO6, \ 28762306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO7, \ 28862306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO10, \ 28962306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO11, \ 29062306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO12, \ 29162306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO13, \ 29262306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO14, \ 29362306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO85, \ 29462306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO86, \ 29562306a36Sopenharmony_ci SSD20XD_GPIO_OFF_GPIO90 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci/* "ttl" pins lcd interface pins */ 29862306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL0 "ttl0" 29962306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL1 "ttl1" 30062306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL2 "ttl2" 30162306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL3 "ttl3" 30262306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL4 "ttl4" 30362306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL5 "ttl5" 30462306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL6 "ttl6" 30562306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL7 "ttl7" 30662306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL8 "ttl8" 30762306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL9 "ttl9" 30862306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL10 "ttl10" 30962306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL11 "ttl11" 31062306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL12 "ttl12" 31162306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL13 "ttl13" 31262306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL14 "ttl14" 31362306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL15 "ttl15" 31462306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL16 "ttl16" 31562306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL17 "ttl17" 31662306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL18 "ttl18" 31762306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL19 "ttl19" 31862306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL20 "ttl20" 31962306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL21 "ttl21" 32062306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL22 "ttl22" 32162306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL23 "ttl23" 32262306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL24 "ttl24" 32362306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL25 "ttl25" 32462306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL26 "ttl26" 32562306a36Sopenharmony_ci#define SSD20XD_PINNAME_TTL27 "ttl27" 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci#define SSD20XD_TTL_PINNAMES SSD20XD_PINNAME_TTL0, \ 32862306a36Sopenharmony_ci SSD20XD_PINNAME_TTL1, \ 32962306a36Sopenharmony_ci SSD20XD_PINNAME_TTL2, \ 33062306a36Sopenharmony_ci SSD20XD_PINNAME_TTL3, \ 33162306a36Sopenharmony_ci SSD20XD_PINNAME_TTL4, \ 33262306a36Sopenharmony_ci SSD20XD_PINNAME_TTL5, \ 33362306a36Sopenharmony_ci SSD20XD_PINNAME_TTL6, \ 33462306a36Sopenharmony_ci SSD20XD_PINNAME_TTL7, \ 33562306a36Sopenharmony_ci SSD20XD_PINNAME_TTL8, \ 33662306a36Sopenharmony_ci SSD20XD_PINNAME_TTL9, \ 33762306a36Sopenharmony_ci SSD20XD_PINNAME_TTL10, \ 33862306a36Sopenharmony_ci SSD20XD_PINNAME_TTL11, \ 33962306a36Sopenharmony_ci SSD20XD_PINNAME_TTL12, \ 34062306a36Sopenharmony_ci SSD20XD_PINNAME_TTL13, \ 34162306a36Sopenharmony_ci SSD20XD_PINNAME_TTL14, \ 34262306a36Sopenharmony_ci SSD20XD_PINNAME_TTL15, \ 34362306a36Sopenharmony_ci SSD20XD_PINNAME_TTL16, \ 34462306a36Sopenharmony_ci SSD20XD_PINNAME_TTL17, \ 34562306a36Sopenharmony_ci SSD20XD_PINNAME_TTL18, \ 34662306a36Sopenharmony_ci SSD20XD_PINNAME_TTL19, \ 34762306a36Sopenharmony_ci SSD20XD_PINNAME_TTL20, \ 34862306a36Sopenharmony_ci SSD20XD_PINNAME_TTL21, \ 34962306a36Sopenharmony_ci SSD20XD_PINNAME_TTL22, \ 35062306a36Sopenharmony_ci SSD20XD_PINNAME_TTL23, \ 35162306a36Sopenharmony_ci SSD20XD_PINNAME_TTL24, \ 35262306a36Sopenharmony_ci SSD20XD_PINNAME_TTL25, \ 35362306a36Sopenharmony_ci SSD20XD_PINNAME_TTL26, \ 35462306a36Sopenharmony_ci SSD20XD_PINNAME_TTL27 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL0 0x80 35762306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL1 0x84 35862306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL2 0x88 35962306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL3 0x8c 36062306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL4 0x90 36162306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL5 0x94 36262306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL6 0x98 36362306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL7 0x9c 36462306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL8 0xa0 36562306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL9 0xa4 36662306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL10 0xa8 36762306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL11 0xac 36862306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL12 0xb0 36962306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL13 0xb4 37062306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL14 0xb8 37162306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL15 0xbc 37262306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL16 0xc0 37362306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL17 0xc4 37462306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL18 0xc8 37562306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL19 0xcc 37662306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL20 0xd0 37762306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL21 0xd4 37862306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL22 0xd8 37962306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL23 0xdc 38062306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL24 0xe0 38162306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL25 0xe4 38262306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL26 0xe8 38362306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSET_TTL27 0xec 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci#define SSD20XD_TTL_OFFSETS SSD20XD_TTL_OFFSET_TTL0, \ 38662306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL1, \ 38762306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL2, \ 38862306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL3, \ 38962306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL4, \ 39062306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL5, \ 39162306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL6, \ 39262306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL7, \ 39362306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL8, \ 39462306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL9, \ 39562306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL10, \ 39662306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL11, \ 39762306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL12, \ 39862306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL13, \ 39962306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL14, \ 40062306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL15, \ 40162306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL16, \ 40262306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL17, \ 40362306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL18, \ 40462306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL19, \ 40562306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL20, \ 40662306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL21, \ 40762306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL22, \ 40862306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL23, \ 40962306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL24, \ 41062306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL25, \ 41162306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL26, \ 41262306a36Sopenharmony_ci SSD20XD_TTL_OFFSET_TTL27 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci/* On the ssd20xd the two normal uarts have dedicated pins */ 41562306a36Sopenharmony_ci#define SSD20XD_PINNAME_UART0_RX "uart0_rx" 41662306a36Sopenharmony_ci#define SSD20XD_PINNAME_UART0_TX "uart0_tx" 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci#define SSD20XD_UART0_NAMES \ 41962306a36Sopenharmony_ci SSD20XD_PINNAME_UART0_RX, \ 42062306a36Sopenharmony_ci SSD20XD_PINNAME_UART0_TX 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci#define SSD20XD_PINNAME_UART1_RX "uart1_rx" 42362306a36Sopenharmony_ci#define SSD20XD_PINNAME_UART1_TX "uart1_tx" 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci#define SSD20XD_UART1_NAMES \ 42662306a36Sopenharmony_ci SSD20XD_PINNAME_UART1_RX, \ 42762306a36Sopenharmony_ci SSD20XD_PINNAME_UART1_TX 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci#define SSD20XD_OFF_UART0_RX 0x60 43062306a36Sopenharmony_ci#define SSD20XD_OFF_UART0_TX 0x64 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci#define SSD20XD_UART0_OFFSETS \ 43362306a36Sopenharmony_ci SSD20XD_OFF_UART0_RX, \ 43462306a36Sopenharmony_ci SSD20XD_OFF_UART0_TX 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci#define SSD20XD_OFF_UART1_RX 0x68 43762306a36Sopenharmony_ci#define SSD20XD_OFF_UART1_TX 0x6c 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci#define SSD20XD_UART1_OFFSETS \ 44062306a36Sopenharmony_ci SSD20XD_OFF_UART1_RX, \ 44162306a36Sopenharmony_ci SSD20XD_OFF_UART1_TX 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci/* 44462306a36Sopenharmony_ci * ssd20x has the same pin names but different ordering 44562306a36Sopenharmony_ci * of the registers that control the gpio. 44662306a36Sopenharmony_ci */ 44762306a36Sopenharmony_ci#define SSD20XD_OFF_SD_D0 0x140 44862306a36Sopenharmony_ci#define SSD20XD_OFF_SD_D1 0x144 44962306a36Sopenharmony_ci#define SSD20XD_OFF_SD_D2 0x148 45062306a36Sopenharmony_ci#define SSD20XD_OFF_SD_D3 0x14c 45162306a36Sopenharmony_ci#define SSD20XD_OFF_SD_CMD 0x150 45262306a36Sopenharmony_ci#define SSD20XD_OFF_SD_CLK 0x154 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci#define SSD20XD_SD_OFFSETS SSD20XD_OFF_SD_CLK, \ 45562306a36Sopenharmony_ci SSD20XD_OFF_SD_CMD, \ 45662306a36Sopenharmony_ci SSD20XD_OFF_SD_D0, \ 45762306a36Sopenharmony_ci SSD20XD_OFF_SD_D1, \ 45862306a36Sopenharmony_ci SSD20XD_OFF_SD_D2, \ 45962306a36Sopenharmony_ci SSD20XD_OFF_SD_D3 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic const char * const ssd20xd_names[] = { 46262306a36Sopenharmony_ci FUART_NAMES, 46362306a36Sopenharmony_ci SD_NAMES, 46462306a36Sopenharmony_ci SSD20XD_UART0_NAMES, 46562306a36Sopenharmony_ci SSD20XD_UART1_NAMES, 46662306a36Sopenharmony_ci SSD20XD_TTL_PINNAMES, 46762306a36Sopenharmony_ci SSD20XD_GPIO_NAMES, 46862306a36Sopenharmony_ci}; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic const unsigned int ssd20xd_offsets[] = { 47162306a36Sopenharmony_ci FUART_OFFSETS, 47262306a36Sopenharmony_ci SSD20XD_SD_OFFSETS, 47362306a36Sopenharmony_ci SSD20XD_UART0_OFFSETS, 47462306a36Sopenharmony_ci SSD20XD_UART1_OFFSETS, 47562306a36Sopenharmony_ci SSD20XD_TTL_OFFSETS, 47662306a36Sopenharmony_ci SSD20XD_GPIO_OFFSETS, 47762306a36Sopenharmony_ci}; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ciMSC313_GPIO_CHIPDATA(ssd20xd); 48062306a36Sopenharmony_ci#endif 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistruct msc313_gpio { 48362306a36Sopenharmony_ci void __iomem *base; 48462306a36Sopenharmony_ci const struct msc313_gpio_data *gpio_data; 48562306a36Sopenharmony_ci u8 *saved; 48662306a36Sopenharmony_ci}; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cistatic void msc313_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 48962306a36Sopenharmony_ci{ 49062306a36Sopenharmony_ci struct msc313_gpio *gpio = gpiochip_get_data(chip); 49162306a36Sopenharmony_ci u8 gpioreg = readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (value) 49462306a36Sopenharmony_ci gpioreg |= MSC313_GPIO_OUT; 49562306a36Sopenharmony_ci else 49662306a36Sopenharmony_ci gpioreg &= ~MSC313_GPIO_OUT; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci writeb_relaxed(gpioreg, gpio->base + gpio->gpio_data->offsets[offset]); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic int msc313_gpio_get(struct gpio_chip *chip, unsigned int offset) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct msc313_gpio *gpio = gpiochip_get_data(chip); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci return readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]) & MSC313_GPIO_IN; 50662306a36Sopenharmony_ci} 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cistatic int msc313_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci struct msc313_gpio *gpio = gpiochip_get_data(chip); 51162306a36Sopenharmony_ci u8 gpioreg = readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci gpioreg |= MSC313_GPIO_OEN; 51462306a36Sopenharmony_ci writeb_relaxed(gpioreg, gpio->base + gpio->gpio_data->offsets[offset]); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci return 0; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistatic int msc313_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct msc313_gpio *gpio = gpiochip_get_data(chip); 52262306a36Sopenharmony_ci u8 gpioreg = readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]); 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci gpioreg &= ~MSC313_GPIO_OEN; 52562306a36Sopenharmony_ci if (value) 52662306a36Sopenharmony_ci gpioreg |= MSC313_GPIO_OUT; 52762306a36Sopenharmony_ci else 52862306a36Sopenharmony_ci gpioreg &= ~MSC313_GPIO_OUT; 52962306a36Sopenharmony_ci writeb_relaxed(gpioreg, gpio->base + gpio->gpio_data->offsets[offset]); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci return 0; 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_cistatic void msc313_gpio_irq_mask(struct irq_data *d) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci irq_chip_mask_parent(d); 53962306a36Sopenharmony_ci gpiochip_disable_irq(gc, d->hwirq); 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic void msc313_gpio_irq_unmask(struct irq_data *d) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci gpiochip_enable_irq(gc, d->hwirq); 54762306a36Sopenharmony_ci irq_chip_unmask_parent(d); 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci/* 55162306a36Sopenharmony_ci * The interrupt handling happens in the parent interrupt controller, 55262306a36Sopenharmony_ci * we don't do anything here. 55362306a36Sopenharmony_ci */ 55462306a36Sopenharmony_cistatic const struct irq_chip msc313_gpio_irqchip = { 55562306a36Sopenharmony_ci .name = "GPIO", 55662306a36Sopenharmony_ci .irq_eoi = irq_chip_eoi_parent, 55762306a36Sopenharmony_ci .irq_mask = msc313_gpio_irq_mask, 55862306a36Sopenharmony_ci .irq_unmask = msc313_gpio_irq_unmask, 55962306a36Sopenharmony_ci .irq_set_type = irq_chip_set_type_parent, 56062306a36Sopenharmony_ci .irq_set_affinity = irq_chip_set_affinity_parent, 56162306a36Sopenharmony_ci .flags = IRQCHIP_IMMUTABLE, 56262306a36Sopenharmony_ci GPIOCHIP_IRQ_RESOURCE_HELPERS, 56362306a36Sopenharmony_ci}; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci/* 56662306a36Sopenharmony_ci * The parent interrupt controller needs the GIC interrupt type set to GIC_SPI 56762306a36Sopenharmony_ci * so we need to provide the fwspec. Essentially gpiochip_populate_parent_fwspec_twocell 56862306a36Sopenharmony_ci * that puts GIC_SPI into the first cell. 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_cistatic int msc313_gpio_populate_parent_fwspec(struct gpio_chip *gc, 57162306a36Sopenharmony_ci union gpio_irq_fwspec *gfwspec, 57262306a36Sopenharmony_ci unsigned int parent_hwirq, 57362306a36Sopenharmony_ci unsigned int parent_type) 57462306a36Sopenharmony_ci{ 57562306a36Sopenharmony_ci struct irq_fwspec *fwspec = &gfwspec->fwspec; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci fwspec->fwnode = gc->irq.parent_domain->fwnode; 57862306a36Sopenharmony_ci fwspec->param_count = 3; 57962306a36Sopenharmony_ci fwspec->param[0] = GIC_SPI; 58062306a36Sopenharmony_ci fwspec->param[1] = parent_hwirq; 58162306a36Sopenharmony_ci fwspec->param[2] = parent_type; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci return 0; 58462306a36Sopenharmony_ci} 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_cistatic int msc313e_gpio_child_to_parent_hwirq(struct gpio_chip *chip, 58762306a36Sopenharmony_ci unsigned int child, 58862306a36Sopenharmony_ci unsigned int child_type, 58962306a36Sopenharmony_ci unsigned int *parent, 59062306a36Sopenharmony_ci unsigned int *parent_type) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci struct msc313_gpio *priv = gpiochip_get_data(chip); 59362306a36Sopenharmony_ci unsigned int offset = priv->gpio_data->offsets[child]; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* 59662306a36Sopenharmony_ci * only the spi0 pins have interrupts on the parent 59762306a36Sopenharmony_ci * on all of the known chips and so far they are all 59862306a36Sopenharmony_ci * mapped to the same place 59962306a36Sopenharmony_ci */ 60062306a36Sopenharmony_ci if (offset >= OFF_SPI0_CZ && offset <= OFF_SPI0_DO) { 60162306a36Sopenharmony_ci *parent_type = child_type; 60262306a36Sopenharmony_ci *parent = ((offset - OFF_SPI0_CZ) >> 2) + 28; 60362306a36Sopenharmony_ci return 0; 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci return -EINVAL; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic int msc313_gpio_probe(struct platform_device *pdev) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci const struct msc313_gpio_data *match_data; 61262306a36Sopenharmony_ci struct msc313_gpio *gpio; 61362306a36Sopenharmony_ci struct gpio_chip *gpiochip; 61462306a36Sopenharmony_ci struct gpio_irq_chip *gpioirqchip; 61562306a36Sopenharmony_ci struct irq_domain *parent_domain; 61662306a36Sopenharmony_ci struct device_node *parent_node; 61762306a36Sopenharmony_ci struct device *dev = &pdev->dev; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci match_data = of_device_get_match_data(dev); 62062306a36Sopenharmony_ci if (!match_data) 62162306a36Sopenharmony_ci return -EINVAL; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci parent_node = of_irq_find_parent(dev->of_node); 62462306a36Sopenharmony_ci if (!parent_node) 62562306a36Sopenharmony_ci return -ENODEV; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci parent_domain = irq_find_host(parent_node); 62862306a36Sopenharmony_ci if (!parent_domain) 62962306a36Sopenharmony_ci return -ENODEV; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL); 63262306a36Sopenharmony_ci if (!gpio) 63362306a36Sopenharmony_ci return -ENOMEM; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci gpio->gpio_data = match_data; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci gpio->saved = devm_kcalloc(dev, gpio->gpio_data->num, sizeof(*gpio->saved), GFP_KERNEL); 63862306a36Sopenharmony_ci if (!gpio->saved) 63962306a36Sopenharmony_ci return -ENOMEM; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci gpio->base = devm_platform_ioremap_resource(pdev, 0); 64262306a36Sopenharmony_ci if (IS_ERR(gpio->base)) 64362306a36Sopenharmony_ci return PTR_ERR(gpio->base); 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci platform_set_drvdata(pdev, gpio); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci gpiochip = devm_kzalloc(dev, sizeof(*gpiochip), GFP_KERNEL); 64862306a36Sopenharmony_ci if (!gpiochip) 64962306a36Sopenharmony_ci return -ENOMEM; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci gpiochip->label = DRIVER_NAME; 65262306a36Sopenharmony_ci gpiochip->parent = dev; 65362306a36Sopenharmony_ci gpiochip->request = gpiochip_generic_request; 65462306a36Sopenharmony_ci gpiochip->free = gpiochip_generic_free; 65562306a36Sopenharmony_ci gpiochip->direction_input = msc313_gpio_direction_input; 65662306a36Sopenharmony_ci gpiochip->direction_output = msc313_gpio_direction_output; 65762306a36Sopenharmony_ci gpiochip->get = msc313_gpio_get; 65862306a36Sopenharmony_ci gpiochip->set = msc313_gpio_set; 65962306a36Sopenharmony_ci gpiochip->base = -1; 66062306a36Sopenharmony_ci gpiochip->ngpio = gpio->gpio_data->num; 66162306a36Sopenharmony_ci gpiochip->names = gpio->gpio_data->names; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci gpioirqchip = &gpiochip->irq; 66462306a36Sopenharmony_ci gpio_irq_chip_set_chip(gpioirqchip, &msc313_gpio_irqchip); 66562306a36Sopenharmony_ci gpioirqchip->fwnode = of_node_to_fwnode(dev->of_node); 66662306a36Sopenharmony_ci gpioirqchip->parent_domain = parent_domain; 66762306a36Sopenharmony_ci gpioirqchip->child_to_parent_hwirq = msc313e_gpio_child_to_parent_hwirq; 66862306a36Sopenharmony_ci gpioirqchip->populate_parent_alloc_arg = msc313_gpio_populate_parent_fwspec; 66962306a36Sopenharmony_ci gpioirqchip->handler = handle_bad_irq; 67062306a36Sopenharmony_ci gpioirqchip->default_type = IRQ_TYPE_NONE; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci return devm_gpiochip_add_data(dev, gpiochip, gpio); 67362306a36Sopenharmony_ci} 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic const struct of_device_id msc313_gpio_of_match[] = { 67662306a36Sopenharmony_ci#ifdef CONFIG_MACH_INFINITY 67762306a36Sopenharmony_ci { 67862306a36Sopenharmony_ci .compatible = "mstar,msc313-gpio", 67962306a36Sopenharmony_ci .data = &msc313_data, 68062306a36Sopenharmony_ci }, 68162306a36Sopenharmony_ci { 68262306a36Sopenharmony_ci .compatible = "sstar,ssd20xd-gpio", 68362306a36Sopenharmony_ci .data = &ssd20xd_data, 68462306a36Sopenharmony_ci }, 68562306a36Sopenharmony_ci#endif 68662306a36Sopenharmony_ci { } 68762306a36Sopenharmony_ci}; 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci/* 69062306a36Sopenharmony_ci * The GPIO controller loses the state of the registers when the 69162306a36Sopenharmony_ci * SoC goes into suspend to memory mode so we need to save some 69262306a36Sopenharmony_ci * of the register bits before suspending and put it back when resuming 69362306a36Sopenharmony_ci */ 69462306a36Sopenharmony_cistatic int __maybe_unused msc313_gpio_suspend(struct device *dev) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci struct msc313_gpio *gpio = dev_get_drvdata(dev); 69762306a36Sopenharmony_ci int i; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci for (i = 0; i < gpio->gpio_data->num; i++) 70062306a36Sopenharmony_ci gpio->saved[i] = readb_relaxed(gpio->base + gpio->gpio_data->offsets[i]) & MSC313_GPIO_BITSTOSAVE; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci return 0; 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_cistatic int __maybe_unused msc313_gpio_resume(struct device *dev) 70662306a36Sopenharmony_ci{ 70762306a36Sopenharmony_ci struct msc313_gpio *gpio = dev_get_drvdata(dev); 70862306a36Sopenharmony_ci int i; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci for (i = 0; i < gpio->gpio_data->num; i++) 71162306a36Sopenharmony_ci writeb_relaxed(gpio->saved[i], gpio->base + gpio->gpio_data->offsets[i]); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci return 0; 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(msc313_gpio_ops, msc313_gpio_suspend, msc313_gpio_resume); 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_cistatic struct platform_driver msc313_gpio_driver = { 71962306a36Sopenharmony_ci .driver = { 72062306a36Sopenharmony_ci .name = DRIVER_NAME, 72162306a36Sopenharmony_ci .of_match_table = msc313_gpio_of_match, 72262306a36Sopenharmony_ci .pm = &msc313_gpio_ops, 72362306a36Sopenharmony_ci }, 72462306a36Sopenharmony_ci .probe = msc313_gpio_probe, 72562306a36Sopenharmony_ci}; 72662306a36Sopenharmony_cibuiltin_platform_driver(msc313_gpio_driver); 727