728 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2020 Daniel Palmer<daniel@thingy.jp> */3 4#include <linux/bitops.h>5#include <linux/kernel.h>6#include <linux/io.h>7#include <linux/of.h>8#include <linux/of_irq.h>9#include <linux/gpio/driver.h>10#include <linux/module.h>11#include <linux/platform_device.h>12#include <linux/property.h>13#include <linux/types.h>14 15#include <dt-bindings/gpio/msc313-gpio.h>16#include <dt-bindings/interrupt-controller/arm-gic.h>17 18#define DRIVER_NAME "gpio-msc313"19 20#define MSC313_GPIO_IN BIT(0)21#define MSC313_GPIO_OUT BIT(4)22#define MSC313_GPIO_OEN BIT(5)23 24/*25 * These bits need to be saved to correctly restore the26 * gpio state when resuming from suspend to memory.27 */28#define MSC313_GPIO_BITSTOSAVE (MSC313_GPIO_OUT | MSC313_GPIO_OEN)29 30/* pad names for fuart, same for all SoCs so far */31#define MSC313_PINNAME_FUART_RX "fuart_rx"32#define MSC313_PINNAME_FUART_TX "fuart_tx"33#define MSC313_PINNAME_FUART_CTS "fuart_cts"34#define MSC313_PINNAME_FUART_RTS "fuart_rts"35 36/* pad names for sr, mercury5 is different */37#define MSC313_PINNAME_SR_IO2 "sr_io2"38#define MSC313_PINNAME_SR_IO3 "sr_io3"39#define MSC313_PINNAME_SR_IO4 "sr_io4"40#define MSC313_PINNAME_SR_IO5 "sr_io5"41#define MSC313_PINNAME_SR_IO6 "sr_io6"42#define MSC313_PINNAME_SR_IO7 "sr_io7"43#define MSC313_PINNAME_SR_IO8 "sr_io8"44#define MSC313_PINNAME_SR_IO9 "sr_io9"45#define MSC313_PINNAME_SR_IO10 "sr_io10"46#define MSC313_PINNAME_SR_IO11 "sr_io11"47#define MSC313_PINNAME_SR_IO12 "sr_io12"48#define MSC313_PINNAME_SR_IO13 "sr_io13"49#define MSC313_PINNAME_SR_IO14 "sr_io14"50#define MSC313_PINNAME_SR_IO15 "sr_io15"51#define MSC313_PINNAME_SR_IO16 "sr_io16"52#define MSC313_PINNAME_SR_IO17 "sr_io17"53 54/* pad names for sd, same for all SoCs so far */55#define MSC313_PINNAME_SD_CLK "sd_clk"56#define MSC313_PINNAME_SD_CMD "sd_cmd"57#define MSC313_PINNAME_SD_D0 "sd_d0"58#define MSC313_PINNAME_SD_D1 "sd_d1"59#define MSC313_PINNAME_SD_D2 "sd_d2"60#define MSC313_PINNAME_SD_D3 "sd_d3"61 62/* pad names for i2c1, same for all SoCs so for */63#define MSC313_PINNAME_I2C1_SCL "i2c1_scl"64#define MSC313_PINNAME_I2C1_SCA "i2c1_sda"65 66/* pad names for spi0, same for all SoCs so far */67#define MSC313_PINNAME_SPI0_CZ "spi0_cz"68#define MSC313_PINNAME_SPI0_CK "spi0_ck"69#define MSC313_PINNAME_SPI0_DI "spi0_di"70#define MSC313_PINNAME_SPI0_DO "spi0_do"71 72#define FUART_NAMES \73 MSC313_PINNAME_FUART_RX, \74 MSC313_PINNAME_FUART_TX, \75 MSC313_PINNAME_FUART_CTS, \76 MSC313_PINNAME_FUART_RTS77 78#define OFF_FUART_RX 0x5079#define OFF_FUART_TX 0x5480#define OFF_FUART_CTS 0x5881#define OFF_FUART_RTS 0x5c82 83#define FUART_OFFSETS \84 OFF_FUART_RX, \85 OFF_FUART_TX, \86 OFF_FUART_CTS, \87 OFF_FUART_RTS88 89#define SR_NAMES \90 MSC313_PINNAME_SR_IO2, \91 MSC313_PINNAME_SR_IO3, \92 MSC313_PINNAME_SR_IO4, \93 MSC313_PINNAME_SR_IO5, \94 MSC313_PINNAME_SR_IO6, \95 MSC313_PINNAME_SR_IO7, \96 MSC313_PINNAME_SR_IO8, \97 MSC313_PINNAME_SR_IO9, \98 MSC313_PINNAME_SR_IO10, \99 MSC313_PINNAME_SR_IO11, \100 MSC313_PINNAME_SR_IO12, \101 MSC313_PINNAME_SR_IO13, \102 MSC313_PINNAME_SR_IO14, \103 MSC313_PINNAME_SR_IO15, \104 MSC313_PINNAME_SR_IO16, \105 MSC313_PINNAME_SR_IO17106 107#define OFF_SR_IO2 0x88108#define OFF_SR_IO3 0x8c109#define OFF_SR_IO4 0x90110#define OFF_SR_IO5 0x94111#define OFF_SR_IO6 0x98112#define OFF_SR_IO7 0x9c113#define OFF_SR_IO8 0xa0114#define OFF_SR_IO9 0xa4115#define OFF_SR_IO10 0xa8116#define OFF_SR_IO11 0xac117#define OFF_SR_IO12 0xb0118#define OFF_SR_IO13 0xb4119#define OFF_SR_IO14 0xb8120#define OFF_SR_IO15 0xbc121#define OFF_SR_IO16 0xc0122#define OFF_SR_IO17 0xc4123 124#define SR_OFFSETS \125 OFF_SR_IO2, \126 OFF_SR_IO3, \127 OFF_SR_IO4, \128 OFF_SR_IO5, \129 OFF_SR_IO6, \130 OFF_SR_IO7, \131 OFF_SR_IO8, \132 OFF_SR_IO9, \133 OFF_SR_IO10, \134 OFF_SR_IO11, \135 OFF_SR_IO12, \136 OFF_SR_IO13, \137 OFF_SR_IO14, \138 OFF_SR_IO15, \139 OFF_SR_IO16, \140 OFF_SR_IO17141 142#define SD_NAMES \143 MSC313_PINNAME_SD_CLK, \144 MSC313_PINNAME_SD_CMD, \145 MSC313_PINNAME_SD_D0, \146 MSC313_PINNAME_SD_D1, \147 MSC313_PINNAME_SD_D2, \148 MSC313_PINNAME_SD_D3149 150#define OFF_SD_CLK 0x140151#define OFF_SD_CMD 0x144152#define OFF_SD_D0 0x148153#define OFF_SD_D1 0x14c154#define OFF_SD_D2 0x150155#define OFF_SD_D3 0x154156 157#define SD_OFFSETS \158 OFF_SD_CLK, \159 OFF_SD_CMD, \160 OFF_SD_D0, \161 OFF_SD_D1, \162 OFF_SD_D2, \163 OFF_SD_D3164 165#define I2C1_NAMES \166 MSC313_PINNAME_I2C1_SCL, \167 MSC313_PINNAME_I2C1_SCA168 169#define OFF_I2C1_SCL 0x188170#define OFF_I2C1_SCA 0x18c171 172#define I2C1_OFFSETS \173 OFF_I2C1_SCL, \174 OFF_I2C1_SCA175 176#define SPI0_NAMES \177 MSC313_PINNAME_SPI0_CZ, \178 MSC313_PINNAME_SPI0_CK, \179 MSC313_PINNAME_SPI0_DI, \180 MSC313_PINNAME_SPI0_DO181 182#define OFF_SPI0_CZ 0x1c0183#define OFF_SPI0_CK 0x1c4184#define OFF_SPI0_DI 0x1c8185#define OFF_SPI0_DO 0x1cc186 187#define SPI0_OFFSETS \188 OFF_SPI0_CZ, \189 OFF_SPI0_CK, \190 OFF_SPI0_DI, \191 OFF_SPI0_DO192 193struct msc313_gpio_data {194 const char * const *names;195 const unsigned int *offsets;196 const unsigned int num;197};198 199#define MSC313_GPIO_CHIPDATA(_chip) \200static const struct msc313_gpio_data _chip##_data = { \201 .names = _chip##_names, \202 .offsets = _chip##_offsets, \203 .num = ARRAY_SIZE(_chip##_offsets), \204}205 206#ifdef CONFIG_MACH_INFINITY207static const char * const msc313_names[] = {208 FUART_NAMES,209 SR_NAMES,210 SD_NAMES,211 I2C1_NAMES,212 SPI0_NAMES,213};214 215static const unsigned int msc313_offsets[] = {216 FUART_OFFSETS,217 SR_OFFSETS,218 SD_OFFSETS,219 I2C1_OFFSETS,220 SPI0_OFFSETS,221};222 223MSC313_GPIO_CHIPDATA(msc313);224 225/*226 * Unlike the msc313(e) the ssd20xd have a bunch of pins227 * that are actually called gpio probably because they228 * have no dedicated function.229 */230#define SSD20XD_PINNAME_GPIO0 "gpio0"231#define SSD20XD_PINNAME_GPIO1 "gpio1"232#define SSD20XD_PINNAME_GPIO2 "gpio2"233#define SSD20XD_PINNAME_GPIO3 "gpio3"234#define SSD20XD_PINNAME_GPIO4 "gpio4"235#define SSD20XD_PINNAME_GPIO5 "gpio5"236#define SSD20XD_PINNAME_GPIO6 "gpio6"237#define SSD20XD_PINNAME_GPIO7 "gpio7"238#define SSD20XD_PINNAME_GPIO10 "gpio10"239#define SSD20XD_PINNAME_GPIO11 "gpio11"240#define SSD20XD_PINNAME_GPIO12 "gpio12"241#define SSD20XD_PINNAME_GPIO13 "gpio13"242#define SSD20XD_PINNAME_GPIO14 "gpio14"243#define SSD20XD_PINNAME_GPIO85 "gpio85"244#define SSD20XD_PINNAME_GPIO86 "gpio86"245#define SSD20XD_PINNAME_GPIO90 "gpio90"246 247#define SSD20XD_GPIO_NAMES SSD20XD_PINNAME_GPIO0, \248 SSD20XD_PINNAME_GPIO1, \249 SSD20XD_PINNAME_GPIO2, \250 SSD20XD_PINNAME_GPIO3, \251 SSD20XD_PINNAME_GPIO4, \252 SSD20XD_PINNAME_GPIO5, \253 SSD20XD_PINNAME_GPIO6, \254 SSD20XD_PINNAME_GPIO7, \255 SSD20XD_PINNAME_GPIO10, \256 SSD20XD_PINNAME_GPIO11, \257 SSD20XD_PINNAME_GPIO12, \258 SSD20XD_PINNAME_GPIO13, \259 SSD20XD_PINNAME_GPIO14, \260 SSD20XD_PINNAME_GPIO85, \261 SSD20XD_PINNAME_GPIO86, \262 SSD20XD_PINNAME_GPIO90263 264#define SSD20XD_GPIO_OFF_GPIO0 0x0265#define SSD20XD_GPIO_OFF_GPIO1 0x4266#define SSD20XD_GPIO_OFF_GPIO2 0x8267#define SSD20XD_GPIO_OFF_GPIO3 0xc268#define SSD20XD_GPIO_OFF_GPIO4 0x10269#define SSD20XD_GPIO_OFF_GPIO5 0x14270#define SSD20XD_GPIO_OFF_GPIO6 0x18271#define SSD20XD_GPIO_OFF_GPIO7 0x1c272#define SSD20XD_GPIO_OFF_GPIO10 0x28273#define SSD20XD_GPIO_OFF_GPIO11 0x2c274#define SSD20XD_GPIO_OFF_GPIO12 0x30275#define SSD20XD_GPIO_OFF_GPIO13 0x34276#define SSD20XD_GPIO_OFF_GPIO14 0x38277#define SSD20XD_GPIO_OFF_GPIO85 0x100278#define SSD20XD_GPIO_OFF_GPIO86 0x104279#define SSD20XD_GPIO_OFF_GPIO90 0x114280 281#define SSD20XD_GPIO_OFFSETS SSD20XD_GPIO_OFF_GPIO0, \282 SSD20XD_GPIO_OFF_GPIO1, \283 SSD20XD_GPIO_OFF_GPIO2, \284 SSD20XD_GPIO_OFF_GPIO3, \285 SSD20XD_GPIO_OFF_GPIO4, \286 SSD20XD_GPIO_OFF_GPIO5, \287 SSD20XD_GPIO_OFF_GPIO6, \288 SSD20XD_GPIO_OFF_GPIO7, \289 SSD20XD_GPIO_OFF_GPIO10, \290 SSD20XD_GPIO_OFF_GPIO11, \291 SSD20XD_GPIO_OFF_GPIO12, \292 SSD20XD_GPIO_OFF_GPIO13, \293 SSD20XD_GPIO_OFF_GPIO14, \294 SSD20XD_GPIO_OFF_GPIO85, \295 SSD20XD_GPIO_OFF_GPIO86, \296 SSD20XD_GPIO_OFF_GPIO90297 298/* "ttl" pins lcd interface pins */299#define SSD20XD_PINNAME_TTL0 "ttl0"300#define SSD20XD_PINNAME_TTL1 "ttl1"301#define SSD20XD_PINNAME_TTL2 "ttl2"302#define SSD20XD_PINNAME_TTL3 "ttl3"303#define SSD20XD_PINNAME_TTL4 "ttl4"304#define SSD20XD_PINNAME_TTL5 "ttl5"305#define SSD20XD_PINNAME_TTL6 "ttl6"306#define SSD20XD_PINNAME_TTL7 "ttl7"307#define SSD20XD_PINNAME_TTL8 "ttl8"308#define SSD20XD_PINNAME_TTL9 "ttl9"309#define SSD20XD_PINNAME_TTL10 "ttl10"310#define SSD20XD_PINNAME_TTL11 "ttl11"311#define SSD20XD_PINNAME_TTL12 "ttl12"312#define SSD20XD_PINNAME_TTL13 "ttl13"313#define SSD20XD_PINNAME_TTL14 "ttl14"314#define SSD20XD_PINNAME_TTL15 "ttl15"315#define SSD20XD_PINNAME_TTL16 "ttl16"316#define SSD20XD_PINNAME_TTL17 "ttl17"317#define SSD20XD_PINNAME_TTL18 "ttl18"318#define SSD20XD_PINNAME_TTL19 "ttl19"319#define SSD20XD_PINNAME_TTL20 "ttl20"320#define SSD20XD_PINNAME_TTL21 "ttl21"321#define SSD20XD_PINNAME_TTL22 "ttl22"322#define SSD20XD_PINNAME_TTL23 "ttl23"323#define SSD20XD_PINNAME_TTL24 "ttl24"324#define SSD20XD_PINNAME_TTL25 "ttl25"325#define SSD20XD_PINNAME_TTL26 "ttl26"326#define SSD20XD_PINNAME_TTL27 "ttl27"327 328#define SSD20XD_TTL_PINNAMES SSD20XD_PINNAME_TTL0, \329 SSD20XD_PINNAME_TTL1, \330 SSD20XD_PINNAME_TTL2, \331 SSD20XD_PINNAME_TTL3, \332 SSD20XD_PINNAME_TTL4, \333 SSD20XD_PINNAME_TTL5, \334 SSD20XD_PINNAME_TTL6, \335 SSD20XD_PINNAME_TTL7, \336 SSD20XD_PINNAME_TTL8, \337 SSD20XD_PINNAME_TTL9, \338 SSD20XD_PINNAME_TTL10, \339 SSD20XD_PINNAME_TTL11, \340 SSD20XD_PINNAME_TTL12, \341 SSD20XD_PINNAME_TTL13, \342 SSD20XD_PINNAME_TTL14, \343 SSD20XD_PINNAME_TTL15, \344 SSD20XD_PINNAME_TTL16, \345 SSD20XD_PINNAME_TTL17, \346 SSD20XD_PINNAME_TTL18, \347 SSD20XD_PINNAME_TTL19, \348 SSD20XD_PINNAME_TTL20, \349 SSD20XD_PINNAME_TTL21, \350 SSD20XD_PINNAME_TTL22, \351 SSD20XD_PINNAME_TTL23, \352 SSD20XD_PINNAME_TTL24, \353 SSD20XD_PINNAME_TTL25, \354 SSD20XD_PINNAME_TTL26, \355 SSD20XD_PINNAME_TTL27356 357#define SSD20XD_TTL_OFFSET_TTL0 0x80358#define SSD20XD_TTL_OFFSET_TTL1 0x84359#define SSD20XD_TTL_OFFSET_TTL2 0x88360#define SSD20XD_TTL_OFFSET_TTL3 0x8c361#define SSD20XD_TTL_OFFSET_TTL4 0x90362#define SSD20XD_TTL_OFFSET_TTL5 0x94363#define SSD20XD_TTL_OFFSET_TTL6 0x98364#define SSD20XD_TTL_OFFSET_TTL7 0x9c365#define SSD20XD_TTL_OFFSET_TTL8 0xa0366#define SSD20XD_TTL_OFFSET_TTL9 0xa4367#define SSD20XD_TTL_OFFSET_TTL10 0xa8368#define SSD20XD_TTL_OFFSET_TTL11 0xac369#define SSD20XD_TTL_OFFSET_TTL12 0xb0370#define SSD20XD_TTL_OFFSET_TTL13 0xb4371#define SSD20XD_TTL_OFFSET_TTL14 0xb8372#define SSD20XD_TTL_OFFSET_TTL15 0xbc373#define SSD20XD_TTL_OFFSET_TTL16 0xc0374#define SSD20XD_TTL_OFFSET_TTL17 0xc4375#define SSD20XD_TTL_OFFSET_TTL18 0xc8376#define SSD20XD_TTL_OFFSET_TTL19 0xcc377#define SSD20XD_TTL_OFFSET_TTL20 0xd0378#define SSD20XD_TTL_OFFSET_TTL21 0xd4379#define SSD20XD_TTL_OFFSET_TTL22 0xd8380#define SSD20XD_TTL_OFFSET_TTL23 0xdc381#define SSD20XD_TTL_OFFSET_TTL24 0xe0382#define SSD20XD_TTL_OFFSET_TTL25 0xe4383#define SSD20XD_TTL_OFFSET_TTL26 0xe8384#define SSD20XD_TTL_OFFSET_TTL27 0xec385 386#define SSD20XD_TTL_OFFSETS SSD20XD_TTL_OFFSET_TTL0, \387 SSD20XD_TTL_OFFSET_TTL1, \388 SSD20XD_TTL_OFFSET_TTL2, \389 SSD20XD_TTL_OFFSET_TTL3, \390 SSD20XD_TTL_OFFSET_TTL4, \391 SSD20XD_TTL_OFFSET_TTL5, \392 SSD20XD_TTL_OFFSET_TTL6, \393 SSD20XD_TTL_OFFSET_TTL7, \394 SSD20XD_TTL_OFFSET_TTL8, \395 SSD20XD_TTL_OFFSET_TTL9, \396 SSD20XD_TTL_OFFSET_TTL10, \397 SSD20XD_TTL_OFFSET_TTL11, \398 SSD20XD_TTL_OFFSET_TTL12, \399 SSD20XD_TTL_OFFSET_TTL13, \400 SSD20XD_TTL_OFFSET_TTL14, \401 SSD20XD_TTL_OFFSET_TTL15, \402 SSD20XD_TTL_OFFSET_TTL16, \403 SSD20XD_TTL_OFFSET_TTL17, \404 SSD20XD_TTL_OFFSET_TTL18, \405 SSD20XD_TTL_OFFSET_TTL19, \406 SSD20XD_TTL_OFFSET_TTL20, \407 SSD20XD_TTL_OFFSET_TTL21, \408 SSD20XD_TTL_OFFSET_TTL22, \409 SSD20XD_TTL_OFFSET_TTL23, \410 SSD20XD_TTL_OFFSET_TTL24, \411 SSD20XD_TTL_OFFSET_TTL25, \412 SSD20XD_TTL_OFFSET_TTL26, \413 SSD20XD_TTL_OFFSET_TTL27414 415/* On the ssd20xd the two normal uarts have dedicated pins */416#define SSD20XD_PINNAME_UART0_RX "uart0_rx"417#define SSD20XD_PINNAME_UART0_TX "uart0_tx"418 419#define SSD20XD_UART0_NAMES \420 SSD20XD_PINNAME_UART0_RX, \421 SSD20XD_PINNAME_UART0_TX422 423#define SSD20XD_PINNAME_UART1_RX "uart1_rx"424#define SSD20XD_PINNAME_UART1_TX "uart1_tx"425 426#define SSD20XD_UART1_NAMES \427 SSD20XD_PINNAME_UART1_RX, \428 SSD20XD_PINNAME_UART1_TX429 430#define SSD20XD_OFF_UART0_RX 0x60431#define SSD20XD_OFF_UART0_TX 0x64432 433#define SSD20XD_UART0_OFFSETS \434 SSD20XD_OFF_UART0_RX, \435 SSD20XD_OFF_UART0_TX436 437#define SSD20XD_OFF_UART1_RX 0x68438#define SSD20XD_OFF_UART1_TX 0x6c439 440#define SSD20XD_UART1_OFFSETS \441 SSD20XD_OFF_UART1_RX, \442 SSD20XD_OFF_UART1_TX443 444/*445 * ssd20x has the same pin names but different ordering446 * of the registers that control the gpio.447 */448#define SSD20XD_OFF_SD_D0 0x140449#define SSD20XD_OFF_SD_D1 0x144450#define SSD20XD_OFF_SD_D2 0x148451#define SSD20XD_OFF_SD_D3 0x14c452#define SSD20XD_OFF_SD_CMD 0x150453#define SSD20XD_OFF_SD_CLK 0x154454 455#define SSD20XD_SD_OFFSETS SSD20XD_OFF_SD_CLK, \456 SSD20XD_OFF_SD_CMD, \457 SSD20XD_OFF_SD_D0, \458 SSD20XD_OFF_SD_D1, \459 SSD20XD_OFF_SD_D2, \460 SSD20XD_OFF_SD_D3461 462static const char * const ssd20xd_names[] = {463 FUART_NAMES,464 SD_NAMES,465 SSD20XD_UART0_NAMES,466 SSD20XD_UART1_NAMES,467 SSD20XD_TTL_PINNAMES,468 SSD20XD_GPIO_NAMES,469};470 471static const unsigned int ssd20xd_offsets[] = {472 FUART_OFFSETS,473 SSD20XD_SD_OFFSETS,474 SSD20XD_UART0_OFFSETS,475 SSD20XD_UART1_OFFSETS,476 SSD20XD_TTL_OFFSETS,477 SSD20XD_GPIO_OFFSETS,478};479 480MSC313_GPIO_CHIPDATA(ssd20xd);481#endif482 483struct msc313_gpio {484 void __iomem *base;485 const struct msc313_gpio_data *gpio_data;486 u8 *saved;487};488 489static void msc313_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)490{491 struct msc313_gpio *gpio = gpiochip_get_data(chip);492 u8 gpioreg = readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]);493 494 if (value)495 gpioreg |= MSC313_GPIO_OUT;496 else497 gpioreg &= ~MSC313_GPIO_OUT;498 499 writeb_relaxed(gpioreg, gpio->base + gpio->gpio_data->offsets[offset]);500}501 502static int msc313_gpio_get(struct gpio_chip *chip, unsigned int offset)503{504 struct msc313_gpio *gpio = gpiochip_get_data(chip);505 506 return readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]) & MSC313_GPIO_IN;507}508 509static int msc313_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)510{511 struct msc313_gpio *gpio = gpiochip_get_data(chip);512 u8 gpioreg = readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]);513 514 gpioreg |= MSC313_GPIO_OEN;515 writeb_relaxed(gpioreg, gpio->base + gpio->gpio_data->offsets[offset]);516 517 return 0;518}519 520static int msc313_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value)521{522 struct msc313_gpio *gpio = gpiochip_get_data(chip);523 u8 gpioreg = readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]);524 525 gpioreg &= ~MSC313_GPIO_OEN;526 if (value)527 gpioreg |= MSC313_GPIO_OUT;528 else529 gpioreg &= ~MSC313_GPIO_OUT;530 writeb_relaxed(gpioreg, gpio->base + gpio->gpio_data->offsets[offset]);531 532 return 0;533}534 535static void msc313_gpio_irq_mask(struct irq_data *d)536{537 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);538 539 irq_chip_mask_parent(d);540 gpiochip_disable_irq(gc, d->hwirq);541}542 543static void msc313_gpio_irq_unmask(struct irq_data *d)544{545 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);546 547 gpiochip_enable_irq(gc, d->hwirq);548 irq_chip_unmask_parent(d);549}550 551/*552 * The interrupt handling happens in the parent interrupt controller,553 * we don't do anything here.554 */555static const struct irq_chip msc313_gpio_irqchip = {556 .name = "GPIO",557 .irq_eoi = irq_chip_eoi_parent,558 .irq_mask = msc313_gpio_irq_mask,559 .irq_unmask = msc313_gpio_irq_unmask,560 .irq_set_type = irq_chip_set_type_parent,561 .irq_set_affinity = irq_chip_set_affinity_parent,562 .flags = IRQCHIP_IMMUTABLE,563 GPIOCHIP_IRQ_RESOURCE_HELPERS,564};565 566/*567 * The parent interrupt controller needs the GIC interrupt type set to GIC_SPI568 * so we need to provide the fwspec. Essentially gpiochip_populate_parent_fwspec_twocell569 * that puts GIC_SPI into the first cell.570 */571static int msc313_gpio_populate_parent_fwspec(struct gpio_chip *gc,572 union gpio_irq_fwspec *gfwspec,573 unsigned int parent_hwirq,574 unsigned int parent_type)575{576 struct irq_fwspec *fwspec = &gfwspec->fwspec;577 578 fwspec->fwnode = gc->irq.parent_domain->fwnode;579 fwspec->param_count = 3;580 fwspec->param[0] = GIC_SPI;581 fwspec->param[1] = parent_hwirq;582 fwspec->param[2] = parent_type;583 584 return 0;585}586 587static int msc313e_gpio_child_to_parent_hwirq(struct gpio_chip *chip,588 unsigned int child,589 unsigned int child_type,590 unsigned int *parent,591 unsigned int *parent_type)592{593 struct msc313_gpio *priv = gpiochip_get_data(chip);594 unsigned int offset = priv->gpio_data->offsets[child];595 596 /*597 * only the spi0 pins have interrupts on the parent598 * on all of the known chips and so far they are all599 * mapped to the same place600 */601 if (offset >= OFF_SPI0_CZ && offset <= OFF_SPI0_DO) {602 *parent_type = child_type;603 *parent = ((offset - OFF_SPI0_CZ) >> 2) + 28;604 return 0;605 }606 607 return -EINVAL;608}609 610static int msc313_gpio_probe(struct platform_device *pdev)611{612 const struct msc313_gpio_data *match_data;613 struct msc313_gpio *gpio;614 struct gpio_chip *gpiochip;615 struct gpio_irq_chip *gpioirqchip;616 struct irq_domain *parent_domain;617 struct device_node *parent_node;618 struct device *dev = &pdev->dev;619 620 match_data = of_device_get_match_data(dev);621 if (!match_data)622 return -EINVAL;623 624 parent_node = of_irq_find_parent(dev->of_node);625 if (!parent_node)626 return -ENODEV;627 628 parent_domain = irq_find_host(parent_node);629 if (!parent_domain)630 return -ENODEV;631 632 gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);633 if (!gpio)634 return -ENOMEM;635 636 gpio->gpio_data = match_data;637 638 gpio->saved = devm_kcalloc(dev, gpio->gpio_data->num, sizeof(*gpio->saved), GFP_KERNEL);639 if (!gpio->saved)640 return -ENOMEM;641 642 gpio->base = devm_platform_ioremap_resource(pdev, 0);643 if (IS_ERR(gpio->base))644 return PTR_ERR(gpio->base);645 646 platform_set_drvdata(pdev, gpio);647 648 gpiochip = devm_kzalloc(dev, sizeof(*gpiochip), GFP_KERNEL);649 if (!gpiochip)650 return -ENOMEM;651 652 gpiochip->label = DRIVER_NAME;653 gpiochip->parent = dev;654 gpiochip->request = gpiochip_generic_request;655 gpiochip->free = gpiochip_generic_free;656 gpiochip->direction_input = msc313_gpio_direction_input;657 gpiochip->direction_output = msc313_gpio_direction_output;658 gpiochip->get = msc313_gpio_get;659 gpiochip->set = msc313_gpio_set;660 gpiochip->base = -1;661 gpiochip->ngpio = gpio->gpio_data->num;662 gpiochip->names = gpio->gpio_data->names;663 664 gpioirqchip = &gpiochip->irq;665 gpio_irq_chip_set_chip(gpioirqchip, &msc313_gpio_irqchip);666 gpioirqchip->fwnode = dev_fwnode(dev);667 gpioirqchip->parent_domain = parent_domain;668 gpioirqchip->child_to_parent_hwirq = msc313e_gpio_child_to_parent_hwirq;669 gpioirqchip->populate_parent_alloc_arg = msc313_gpio_populate_parent_fwspec;670 gpioirqchip->handler = handle_bad_irq;671 gpioirqchip->default_type = IRQ_TYPE_NONE;672 673 return devm_gpiochip_add_data(dev, gpiochip, gpio);674}675 676static const struct of_device_id msc313_gpio_of_match[] = {677#ifdef CONFIG_MACH_INFINITY678 {679 .compatible = "mstar,msc313-gpio",680 .data = &msc313_data,681 },682 {683 .compatible = "sstar,ssd20xd-gpio",684 .data = &ssd20xd_data,685 },686#endif687 { }688};689 690/*691 * The GPIO controller loses the state of the registers when the692 * SoC goes into suspend to memory mode so we need to save some693 * of the register bits before suspending and put it back when resuming694 */695static int __maybe_unused msc313_gpio_suspend(struct device *dev)696{697 struct msc313_gpio *gpio = dev_get_drvdata(dev);698 int i;699 700 for (i = 0; i < gpio->gpio_data->num; i++)701 gpio->saved[i] = readb_relaxed(gpio->base + gpio->gpio_data->offsets[i]) & MSC313_GPIO_BITSTOSAVE;702 703 return 0;704}705 706static int __maybe_unused msc313_gpio_resume(struct device *dev)707{708 struct msc313_gpio *gpio = dev_get_drvdata(dev);709 int i;710 711 for (i = 0; i < gpio->gpio_data->num; i++)712 writeb_relaxed(gpio->saved[i], gpio->base + gpio->gpio_data->offsets[i]);713 714 return 0;715}716 717static SIMPLE_DEV_PM_OPS(msc313_gpio_ops, msc313_gpio_suspend, msc313_gpio_resume);718 719static struct platform_driver msc313_gpio_driver = {720 .driver = {721 .name = DRIVER_NAME,722 .of_match_table = msc313_gpio_of_match,723 .pm = &msc313_gpio_ops,724 },725 .probe = msc313_gpio_probe,726};727builtin_platform_driver(msc313_gpio_driver);728