^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * driver/mfd/asic3.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Compaq ASIC3 support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2001 Compaq Computer Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright 2004-2005 Phil Blundell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2007-2008 OpenedHand Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Authors: Phil Blundell <pb@handhelds.org>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Samuel Ortiz <sameo@openedhand.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mfd/asic3.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/mfd/ds1wm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/mfd/tmio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/mmc/host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ASIC3_CLOCK_SPI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ASIC3_CLOCK_OWM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ASIC3_CLOCK_PWM0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ASIC3_CLOCK_PWM1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ASIC3_CLOCK_LED0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ASIC3_CLOCK_LED1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ASIC3_CLOCK_LED2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ASIC3_CLOCK_SD_HOST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ASIC3_CLOCK_SD_BUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ASIC3_CLOCK_SMBUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ASIC3_CLOCK_EX0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ASIC3_CLOCK_EX1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct asic3_clk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned int cdex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define INIT_CDEX(_name, _rate) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [ASIC3_CLOCK_##_name] = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .cdex = CLOCK_CDEX_##_name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .rate = _rate, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static struct asic3_clk asic3_clk_init[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) INIT_CDEX(SPI, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) INIT_CDEX(OWM, 5000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) INIT_CDEX(PWM0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) INIT_CDEX(PWM1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) INIT_CDEX(LED0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) INIT_CDEX(LED1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) INIT_CDEX(LED2, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) INIT_CDEX(SD_HOST, 24576000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) INIT_CDEX(SD_BUS, 12288000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) INIT_CDEX(SMBUS, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) INIT_CDEX(EX0, 32768),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) INIT_CDEX(EX1, 24576000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct asic3 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) void __iomem *mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned int bus_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned int irq_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned int irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) raw_spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u16 irq_bothedge[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct gpio_chip gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) void __iomem *tmio_cnf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) iowrite16(value, asic->mapping +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) (reg >> asic->bus_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) EXPORT_SYMBOL_GPL(asic3_write_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u32 asic3_read_register(struct asic3 *asic, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return ioread16(asic->mapping +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) (reg >> asic->bus_shift));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) EXPORT_SYMBOL_GPL(asic3_read_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) val = asic3_read_register(asic, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) val |= bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) val &= ~bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) asic3_write_register(asic, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define MAX_ASIC_ISR_LOOPS 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define ASIC3_GPIO_BASE_INCR \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void asic3_irq_flip_edge(struct asic3 *asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u32 base, int bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u16 edge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) edge = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) base + ASIC3_GPIO_EDGE_TRIGGER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) edge ^= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) asic3_write_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) base + ASIC3_GPIO_EDGE_TRIGGER, edge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static void asic3_irq_demux(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct asic3 *asic = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct irq_data *data = irq_desc_get_irq_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int iter, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) data->chip->irq_ack(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) status = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ASIC3_OFFSET(INTR, P_INT_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Check all ten register bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if ((status & 0x3ff) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Handle GPIO IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (bank = 0; bank < ASIC3_NUM_GPIO_BANKS; bank++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (status & (1 << bank)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned long base, istat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) base = ASIC3_GPIO_A_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) + bank * ASIC3_GPIO_BASE_INCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) istat = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ASIC3_GPIO_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* Clearing IntStatus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) asic3_write_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ASIC3_GPIO_INT_STATUS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int bit = (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) unsigned int irqnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (!(istat & bit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) irqnr = asic->irq_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) (ASIC3_GPIOS_PER_BANK * bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) generic_handle_irq(irqnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (asic->irq_bothedge[bank] & bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) asic3_irq_flip_edge(asic, base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* Handle remaining IRQs in the status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* They start at bit 4 and go up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (status & (1 << (i - ASIC3_NUM_GPIOS + 4)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) generic_handle_irq(asic->irq_base + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (iter >= MAX_ASIC_ISR_LOOPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dev_err(asic->dev, "interrupt processing overrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static inline int asic3_irq_to_bank(struct asic3 *asic, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) n = (irq - asic->irq_base) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return (n * (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static inline int asic3_irq_to_index(struct asic3 *asic, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return (irq - asic->irq_base) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static void asic3_mask_gpio_irq(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct asic3 *asic = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u32 val, bank, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) bank = asic3_irq_to_bank(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) index = asic3_irq_to_index(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) val |= 1 << index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static void asic3_mask_irq(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct asic3 *asic = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) regval = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ASIC3_INTR_BASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ASIC3_INTR_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) regval &= ~(ASIC3_INTMASK_MASK0 <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) asic3_write_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ASIC3_INTR_BASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ASIC3_INTR_INT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void asic3_unmask_gpio_irq(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct asic3 *asic = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) u32 val, bank, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) bank = asic3_irq_to_bank(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) index = asic3_irq_to_index(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) val &= ~(1 << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static void asic3_unmask_irq(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct asic3 *asic = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) regval = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ASIC3_INTR_BASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ASIC3_INTR_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) regval |= (ASIC3_INTMASK_MASK0 <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) asic3_write_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ASIC3_INTR_BASE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ASIC3_INTR_INT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct asic3 *asic = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) u32 bank, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u16 trigger, level, edge, bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) bank = asic3_irq_to_bank(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) index = asic3_irq_to_index(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) bit = 1<<index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) level = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) bank + ASIC3_GPIO_LEVEL_TRIGGER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) edge = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) bank + ASIC3_GPIO_EDGE_TRIGGER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) trigger = asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) bank + ASIC3_GPIO_TRIGGER_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (type == IRQ_TYPE_EDGE_RISING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) trigger |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) edge |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) } else if (type == IRQ_TYPE_EDGE_FALLING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) trigger |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) edge &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) } else if (type == IRQ_TYPE_EDGE_BOTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) trigger |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (asic3_gpio_get(&asic->gpio, data->irq - asic->irq_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) edge &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) edge |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } else if (type == IRQ_TYPE_LEVEL_LOW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) trigger &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) level &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) } else if (type == IRQ_TYPE_LEVEL_HIGH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) trigger &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) level |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * if type == IRQ_TYPE_NONE, we should mask interrupts, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * be careful to not unmask them if mask was also called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * Probably need internal state for mask.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dev_notice(asic->dev, "irq type not changed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) asic3_write_register(asic, bank + ASIC3_GPIO_LEVEL_TRIGGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) asic3_write_register(asic, bank + ASIC3_GPIO_EDGE_TRIGGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) edge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) asic3_write_register(asic, bank + ASIC3_GPIO_TRIGGER_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static int asic3_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct asic3 *asic = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) u32 bank, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) u16 bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) bank = asic3_irq_to_bank(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) index = asic3_irq_to_index(asic, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) bit = 1<<index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) asic3_set_register(asic, bank + ASIC3_GPIO_SLEEP_MASK, bit, !on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static struct irq_chip asic3_gpio_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) .name = "ASIC3-GPIO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) .irq_ack = asic3_mask_gpio_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .irq_mask = asic3_mask_gpio_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .irq_unmask = asic3_unmask_gpio_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .irq_set_type = asic3_gpio_irq_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .irq_set_wake = asic3_gpio_irq_set_wake,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static struct irq_chip asic3_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .name = "ASIC3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .irq_ack = asic3_mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .irq_mask = asic3_mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .irq_unmask = asic3_unmask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int __init asic3_irq_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct asic3 *asic = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) unsigned long clksel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) unsigned int irq, irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ret = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) asic->irq_nr = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* turn on clock to IRQ controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) clksel |= CLOCK_SEL_CX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) clksel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) irq_base = asic->irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (irq < asic->irq_base + ASIC3_NUM_GPIOS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) irq_set_chip(irq, &asic3_gpio_irq_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) irq_set_chip(irq, &asic3_irq_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) irq_set_chip_data(irq, asic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) irq_set_handler(irq, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ASIC3_INTMASK_GINTMASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) irq_set_chained_handler_and_data(asic->irq_nr, asic3_irq_demux, asic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) irq_set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static void asic3_irq_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct asic3 *asic = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) unsigned int irq, irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) irq_base = asic->irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) irq_set_chip_and_handler(irq, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) irq_set_chip_data(irq, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) irq_set_chained_handler(asic->irq_nr, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* GPIOs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static int asic3_gpio_direction(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) unsigned offset, int out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) u32 mask = ASIC3_GPIO_TO_MASK(offset), out_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) unsigned int gpio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct asic3 *asic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) asic = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) gpio_base = ASIC3_GPIO_TO_BASE(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (gpio_base > ASIC3_GPIO_D_BASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) gpio_base, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_DIRECTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Input is 0, Output is 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) out_reg |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) out_reg &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) asic3_write_register(asic, gpio_base + ASIC3_GPIO_DIRECTION, out_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static int asic3_gpio_direction_input(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return asic3_gpio_direction(chip, offset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static int asic3_gpio_direction_output(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return asic3_gpio_direction(chip, offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int asic3_gpio_get(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) unsigned int gpio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) u32 mask = ASIC3_GPIO_TO_MASK(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct asic3 *asic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) asic = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) gpio_base = ASIC3_GPIO_TO_BASE(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (gpio_base > ASIC3_GPIO_D_BASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) gpio_base, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return !!(asic3_read_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) gpio_base + ASIC3_GPIO_STATUS) & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static void asic3_gpio_set(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) u32 mask, out_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) unsigned int gpio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct asic3 *asic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) asic = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) gpio_base = ASIC3_GPIO_TO_BASE(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (gpio_base > ASIC3_GPIO_D_BASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) gpio_base, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) mask = ASIC3_GPIO_TO_MASK(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) out_reg |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) out_reg &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) asic3_write_register(asic, gpio_base + ASIC3_GPIO_OUT, out_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct asic3 *asic = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return asic->irq_base + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static __init int asic3_gpio_probe(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) u16 *gpio_config, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct asic3 *asic = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u16 alt_reg[ASIC3_NUM_GPIO_BANKS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) u16 out_reg[ASIC3_NUM_GPIO_BANKS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) u16 dir_reg[ASIC3_NUM_GPIO_BANKS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) memset(alt_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) memset(out_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) memset(dir_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /* Enable all GPIOs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, MASK), 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, MASK), 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, MASK), 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, MASK), 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) u8 alt, pin, dir, init, bank_num, bit_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) u16 config = gpio_config[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) pin = ASIC3_CONFIG_GPIO_PIN(config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) alt = ASIC3_CONFIG_GPIO_ALT(config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dir = ASIC3_CONFIG_GPIO_DIR(config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) init = ASIC3_CONFIG_GPIO_INIT(config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) bank_num = ASIC3_GPIO_TO_BANK(pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) bit_num = ASIC3_GPIO_TO_BIT(pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) alt_reg[bank_num] |= (alt << bit_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) out_reg[bank_num] |= (init << bit_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) dir_reg[bank_num] |= (dir << bit_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) for (i = 0; i < ASIC3_NUM_GPIO_BANKS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) asic3_write_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ASIC3_BANK_TO_BASE(i) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ASIC3_GPIO_DIRECTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) dir_reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) asic3_write_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ASIC3_BANK_TO_BASE(i) + ASIC3_GPIO_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) out_reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) asic3_write_register(asic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) ASIC3_BANK_TO_BASE(i) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ASIC3_GPIO_ALT_FUNCTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) alt_reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return gpiochip_add_data(&asic->gpio, asic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static int asic3_gpio_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct asic3 *asic = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) gpiochip_remove(&asic->gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static void asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) u32 cdex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (clk->enabled++ == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) cdex |= clk->cdex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) u32 cdex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) WARN_ON(clk->enabled == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) raw_spin_lock_irqsave(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (--clk->enabled == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) cdex &= ~clk->cdex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) raw_spin_unlock_irqrestore(&asic->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* MFD cells (SPI, PWM, LED, DS1WM, MMC) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static struct ds1wm_driver_data ds1wm_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) .active_high = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .reset_recover_delay = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static struct resource ds1wm_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) .start = ASIC3_OWM_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) .end = ASIC3_OWM_BASE + 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .start = ASIC3_IRQ_OWM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) .end = ASIC3_IRQ_OWM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) static int ds1wm_enable(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /* Turn on external clocks and the OWM clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* Reset and enable DS1WM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ASIC3_EXTCF_OWM_RESET, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ASIC3_EXTCF_OWM_RESET, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) ASIC3_EXTCF_OWM_EN, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static int ds1wm_disable(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ASIC3_EXTCF_OWM_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static const struct mfd_cell asic3_cell_ds1wm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .name = "ds1wm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .enable = ds1wm_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .disable = ds1wm_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) .platform_data = &ds1wm_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) .pdata_size = sizeof(ds1wm_pdata),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .num_resources = ARRAY_SIZE(ds1wm_resources),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .resources = ds1wm_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static void asic3_mmc_pwr(struct platform_device *pdev, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static struct tmio_mmc_data asic3_mmc_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .hclk = 24576000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .set_pwr = asic3_mmc_pwr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) .set_clk_div = asic3_mmc_clk_div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) static struct resource asic3_mmc_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) .start = ASIC3_SD_CTRL_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) .end = ASIC3_SD_CTRL_BASE + 0x3ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .start = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .end = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) .flags = IORESOURCE_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static int asic3_mmc_enable(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* Not sure if it must be done bit by bit, but leaving as-is */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ASIC3_SDHWCTRL_LEVCD, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ASIC3_SDHWCTRL_LEVWP, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ASIC3_SDHWCTRL_SUSPEND, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ASIC3_SDHWCTRL_PCLR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* CLK32 used for card detection and for interruption detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * when HCLK is stopped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* HCLK 24.576 MHz, BCLK 12.288 MHz: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) CLOCK_SEL_CX | CLOCK_SEL_SD_HCLK_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) ASIC3_EXTCF_SD_MEM_ENABLE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /* Enable SD card slot 3.3V power supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) ASIC3_SDHWCTRL_SDPWR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) ASIC3_SD_CTRL_BASE >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static int asic3_mmc_disable(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /* Put in suspend mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) ASIC3_SDHWCTRL_SUSPEND, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /* Disable clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static const struct mfd_cell asic3_cell_mmc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .name = "tmio-mmc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .enable = asic3_mmc_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .disable = asic3_mmc_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) .suspend = asic3_mmc_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .resume = asic3_mmc_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .platform_data = &asic3_mmc_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .pdata_size = sizeof(asic3_mmc_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .num_resources = ARRAY_SIZE(asic3_mmc_resources),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .resources = asic3_mmc_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static const int clock_ledn[ASIC3_NUM_LEDS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) [0] = ASIC3_CLOCK_LED0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) [1] = ASIC3_CLOCK_LED1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) [2] = ASIC3_CLOCK_LED2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static int asic3_leds_enable(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) const struct mfd_cell *cell = mfd_get_cell(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) asic3_clk_enable(asic, &asic->clocks[clock_ledn[cell->id]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static int asic3_leds_disable(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) const struct mfd_cell *cell = mfd_get_cell(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static int asic3_leds_suspend(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) const struct mfd_cell *cell = mfd_get_cell(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) while (asic3_gpio_get(&asic->gpio, ASIC3_GPIO(C, cell->id)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .name = "leds-asic3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .enable = asic3_leds_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .disable = asic3_leds_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .suspend = asic3_leds_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .resume = asic3_leds_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .name = "leds-asic3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .id = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .enable = asic3_leds_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .disable = asic3_leds_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .suspend = asic3_leds_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .resume = asic3_leds_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) [2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .name = "leds-asic3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) .id = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) .enable = asic3_leds_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) .disable = asic3_leds_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .suspend = asic3_leds_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .resume = asic3_leds_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static int __init asic3_mfd_probe(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct asic3_platform_data *pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) struct resource *mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct asic3 *asic = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct resource *mem_sdio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) int irq, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) mem_sdio = platform_get_resource(pdev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (!mem_sdio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) dev_dbg(asic->dev, "no SDIO MEM resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) irq = platform_get_irq(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) dev_dbg(asic->dev, "no SDIO IRQ resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* DS1WM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) ASIC3_EXTCF_OWM_SMB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ds1wm_resources[0].start >>= asic->bus_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ds1wm_resources[0].end >>= asic->bus_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* MMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (mem_sdio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) asic->bus_shift) + mem_sdio->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (!asic->tmio_cnf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) asic3_mmc_resources[0].start >>= asic->bus_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) asic3_mmc_resources[0].end >>= asic->bus_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (pdata->clock_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) ds1wm_pdata.clock_rate = pdata->clock_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) ret = mfd_add_devices(&pdev->dev, pdev->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) goto out_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (mem_sdio && (irq >= 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ret = mfd_add_devices(&pdev->dev, pdev->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) &asic3_cell_mmc, 1, mem_sdio, irq, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) goto out_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (pdata->leds) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) for (i = 0; i < ASIC3_NUM_LEDS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) asic3_cell_leds[i].platform_data = &pdata->leds[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ret = mfd_add_devices(&pdev->dev, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) out_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (asic->tmio_cnf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) iounmap(asic->tmio_cnf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static void asic3_mfd_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) struct asic3 *asic = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) mfd_remove_devices(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) iounmap(asic->tmio_cnf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /* Core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static int __init asic3_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct asic3_platform_data *pdata = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct asic3 *asic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct resource *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) unsigned long clksel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) asic = devm_kzalloc(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) sizeof(struct asic3), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (!asic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) raw_spin_lock_init(&asic->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) platform_set_drvdata(pdev, asic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) asic->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (!mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) dev_err(asic->dev, "no MEM resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) asic->mapping = ioremap(mem->start, resource_size(mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (!asic->mapping) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) dev_err(asic->dev, "Couldn't ioremap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) asic->irq_base = pdata->irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /* calculate bus shift from mem resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) asic->bus_shift = 2 - (resource_size(mem) >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) clksel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ret = asic3_irq_probe(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) dev_err(asic->dev, "Couldn't probe IRQs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) goto out_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) asic->gpio.label = "asic3";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) asic->gpio.base = pdata->gpio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) asic->gpio.ngpio = ASIC3_NUM_GPIOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) asic->gpio.get = asic3_gpio_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) asic->gpio.set = asic3_gpio_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) asic->gpio.direction_input = asic3_gpio_direction_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) asic->gpio.direction_output = asic3_gpio_direction_output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) asic->gpio.to_irq = asic3_gpio_to_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) ret = asic3_gpio_probe(pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) pdata->gpio_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) pdata->gpio_config_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) dev_err(asic->dev, "GPIO probe failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) goto out_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) /* Making a per-device copy is only needed for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * theoretical case of multiple ASIC3s on one board:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) asic3_mfd_probe(pdev, pdata, mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) (ASIC3_EXTCF_CF0_BUF_EN|ASIC3_EXTCF_CF0_PWAIT_EN), 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) dev_info(asic->dev, "ASIC3 Core driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) out_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) asic3_irq_remove(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) out_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) iounmap(asic->mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static int asic3_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct asic3 *asic = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) (ASIC3_EXTCF_CF0_BUF_EN|ASIC3_EXTCF_CF0_PWAIT_EN), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) asic3_mfd_remove(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) ret = asic3_gpio_remove(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) asic3_irq_remove(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) iounmap(asic->mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static void asic3_shutdown(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static struct platform_driver asic3_device_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) .name = "asic3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) .remove = asic3_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) .shutdown = asic3_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static int __init asic3_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) retval = platform_driver_probe(&asic3_device_driver, asic3_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) subsys_initcall(asic3_init);