/* * drivers/mfd/max77663-core.c * Max77663 mfd driver (I2C bus access) * * Copyright 2011 Maxim Integrated Products, Inc. * Copyright (C) 2011-2012 NVIDIA Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* RTC i2c slave address */ #define MAX77663_RTC_I2C_ADDR 0x48 /* Registers */ #define MAX77663_REG_IRQ_TOP 0x05 #define MAX77663_REG_LBT_IRQ 0x06 #define MAX77663_REG_SD_IRQ 0x07 #define MAX77663_REG_LDOX_IRQ 0x08 #define MAX77663_REG_LDO8_IRQ 0x09 #define MAX77663_REG_GPIO_IRQ 0x0A #define MAX77663_REG_ONOFF_IRQ 0x0B #define MAX77663_REG_NVER 0x0C #define MAX77663_REG_IRQ_TOP_MASK 0x0D #define MAX77663_REG_LBT_IRQ_MASK 0x0E #define MAX77663_REG_SD_IRQ_MASK 0x0F #define MAX77663_REG_LDOX_IRQ_MASK 0x10 #define MAX77663_REG_LDO8_IRQ_MASK 0x11 #define MAX77663_REG_ONOFF_IRQ_MASK 0x12 #define MAX77663_REG_GPIO_CTRL0 0x36 #define MAX77663_REG_GPIO_CTRL1 0x37 #define MAX77663_REG_GPIO_CTRL2 0x38 #define MAX77663_REG_GPIO_CTRL3 0x39 #define MAX77663_REG_GPIO_CTRL4 0x3A #define MAX77663_REG_GPIO_CTRL5 0x3B #define MAX77663_REG_GPIO_CTRL6 0x3C #define MAX77663_REG_GPIO_CTRL7 0x3D #define MAX77663_REG_GPIO_PU 0x3E #define MAX77663_REG_GPIO_PD 0x3F #define MAX77663_REG_GPIO_ALT 0x40 #define MAX77663_REG_ONOFF_CFG1 0x41 #define MAX77663_REG_ONOFF_CFG2 0x42 #define MAX77663_REG_CID4 0x5C #define MAX77663_REG_CID5 0x5D #define IRQ_TOP_GLBL_MASK (1 << 7) #define IRQ_TOP_GLBL_SHIFT 7 #define IRQ_TOP_SD_MASK (1 << 6) #define IRQ_TOP_SD_SHIFT 6 #define IRQ_TOP_LDO_MASK (1 << 5) #define IRQ_TOP_LDO_SHIFT 5 #define IRQ_TOP_GPIO_MASK (1 << 4) #define IRQ_TOP_GPIO_SHIFT 4 #define IRQ_TOP_RTC_MASK (1 << 3) #define IRQ_TOP_RTC_SHIFT 3 #define IRQ_TOP_32K_MASK (1 << 2) #define IRQ_TOP_32K_SHIFT 2 #define IRQ_TOP_ONOFF_MASK (1 << 1) #define IRQ_TOP_ONOFF_SHIFT 1 #define IRQ_TOP_NVER_MASK (1 << 0) #define IRQ_TOP_NVER_SHIFT 0 #define IRQ_GLBL_MASK (1 << 0) #define IRQ_LBT_BASE MAX77663_IRQ_LBT_LB #define IRQ_LBT_END MAX77663_IRQ_LBT_THERM_ALRM2 #define IRQ_GPIO_BASE MAX77663_IRQ_GPIO0 #define IRQ_GPIO_END MAX77663_IRQ_GPIO7 #define IRQ_ONOFF_BASE MAX77663_IRQ_ONOFF_HRDPOWRN #define IRQ_ONOFF_END MAX77663_IRQ_ONOFF_ACOK_RISING #define GPIO_REG_ADDR(offset) (MAX77663_REG_GPIO_CTRL0 + offset) #define GPIO_CTRL_DBNC_MASK (3 << 6) #define GPIO_CTRL_DBNC_SHIFT 6 #define GPIO_CTRL_REFE_IRQ_MASK (3 << 4) #define GPIO_CTRL_REFE_IRQ_SHIFT 4 #define GPIO_CTRL_DOUT_MASK (1 << 3) #define GPIO_CTRL_DOUT_SHIFT 3 #define GPIO_CTRL_DIN_MASK (1 << 2) #define GPIO_CTRL_DIN_SHIFT 2 #define GPIO_CTRL_DIR_MASK (1 << 1) #define GPIO_CTRL_DIR_SHIFT 1 #define GPIO_CTRL_OUT_DRV_MASK (1 << 0) #define GPIO_CTRL_OUT_DRV_SHIFT 0 #define GPIO_REFE_IRQ_NONE 0 #define GPIO_REFE_IRQ_EDGE_FALLING 1 #define GPIO_REFE_IRQ_EDGE_RISING 2 #define GPIO_REFE_IRQ_EDGE_BOTH 3 #define GPIO_DBNC_NONE 0 #define GPIO_DBNC_8MS 1 #define GPIO_DBNC_16MS 2 #define GPIO_DBNC_32MS 3 #define ONOFF_SFT_RST_MASK (1 << 7) #define ONOFF_SLPEN_MASK (1 << 2) #define ONOFF_PWR_OFF_MASK (1 << 1) #define ONOFF_SLP_LPM_MASK (1 << 5) #define ONOFF_IRQ_EN0_RISING (1 << 3) enum { CACHE_IRQ_LBT, CACHE_IRQ_SD, CACHE_IRQ_LDO, CACHE_IRQ_ONOFF, CACHE_IRQ_NR, }; struct max77663_irq_data { int mask_reg; u16 mask; u8 top_mask; u8 top_shift; int cache_idx; bool is_rtc; bool is_unmask; u8 trigger_type; }; struct max77663_chip { struct device *dev; struct i2c_client *i2c_power; struct i2c_client *i2c_rtc; struct regmap *regmap_power; struct regmap *regmap_rtc; struct max77663_platform_data *pdata; struct mutex io_lock; struct irq_chip irq; struct mutex irq_lock; int irq_base; int irq_top_count[8]; u8 cache_irq_top_mask; u16 cache_irq_mask[CACHE_IRQ_NR]; u8 rtc_i2c_addr; }; struct max77663_chip *max77663_chip; static struct resource gpio_resources[] = { { .start = MAX77663_IRQ_INT_TOP_GPIO, .end = MAX77663_IRQ_INT_TOP_GPIO, .flags = IORESOURCE_IRQ, } }; static struct resource rtc_resources[] = { { .start = MAX77663_IRQ_RTC, .end = MAX77663_IRQ_RTC, .flags = IORESOURCE_IRQ, } }; static struct mfd_cell max77663_cells[] = { { .name = "max77663-gpio", .num_resources = ARRAY_SIZE(gpio_resources), .resources = &gpio_resources[0], }, { .name = "max77663-pmic", }, { .name = "max77663-rtc", .num_resources = ARRAY_SIZE(rtc_resources), .resources = &rtc_resources[0], }, }; #define IRQ_DATA_LBT(_name, _shift) \ [MAX77663_IRQ_LBT_##_name] = { \ .mask_reg = MAX77663_REG_LBT_IRQ_MASK, \ .mask = (1 << _shift), \ .top_mask = IRQ_TOP_GLBL_MASK, \ .top_shift = IRQ_TOP_GLBL_SHIFT, \ .cache_idx = CACHE_IRQ_LBT, \ } #define IRQ_DATA_GPIO_TOP() \ [MAX77663_IRQ_INT_TOP_GPIO] = { \ .top_mask = IRQ_TOP_GPIO_MASK, \ .top_shift = IRQ_TOP_GPIO_SHIFT, \ .cache_idx = -1, \ } #define IRQ_DATA_ONOFF(_name, _shift) \ [MAX77663_IRQ_ONOFF_##_name] = { \ .mask_reg = MAX77663_REG_ONOFF_IRQ_MASK,\ .mask = (1 << _shift), \ .top_mask = IRQ_TOP_ONOFF_MASK, \ .top_shift = IRQ_TOP_ONOFF_SHIFT, \ .cache_idx = CACHE_IRQ_ONOFF, \ } static struct max77663_irq_data max77663_irqs[MAX77663_IRQ_NR] = { IRQ_DATA_GPIO_TOP(), IRQ_DATA_LBT(LB, 3), IRQ_DATA_LBT(THERM_ALRM1, 2), IRQ_DATA_LBT(THERM_ALRM2, 1), IRQ_DATA_ONOFF(HRDPOWRN, 0), IRQ_DATA_ONOFF(EN0_1SEC, 1), IRQ_DATA_ONOFF(EN0_FALLING, 2), IRQ_DATA_ONOFF(EN0_RISING, 3), IRQ_DATA_ONOFF(LID_FALLING, 4), IRQ_DATA_ONOFF(LID_RISING, 5), IRQ_DATA_ONOFF(ACOK_FALLING, 6), IRQ_DATA_ONOFF(ACOK_RISING, 7), [MAX77663_IRQ_RTC] = { .top_mask = IRQ_TOP_RTC_MASK, .top_shift = IRQ_TOP_RTC_SHIFT, .cache_idx = -1, .is_rtc = 1, }, [MAX77663_IRQ_SD_PF] = { .mask_reg = MAX77663_REG_SD_IRQ_MASK, .mask = 0xF8, .top_mask = IRQ_TOP_SD_MASK, .top_shift = IRQ_TOP_SD_SHIFT, .cache_idx = CACHE_IRQ_SD, }, [MAX77663_IRQ_LDO_PF] = { .mask_reg = MAX77663_REG_LDOX_IRQ_MASK, .mask = 0x1FF, .top_mask = IRQ_TOP_LDO_MASK, .top_shift = IRQ_TOP_LDO_SHIFT, .cache_idx = CACHE_IRQ_LDO, }, [MAX77663_IRQ_32K] = { .top_mask = IRQ_TOP_32K_MASK, .top_shift = IRQ_TOP_32K_SHIFT, .cache_idx = -1, }, [MAX77663_IRQ_NVER] = { .top_mask = IRQ_TOP_NVER_MASK, .top_shift = IRQ_TOP_NVER_SHIFT, .cache_idx = -1, }, }; /* MAX77663 PMU doesn't allow PWR_OFF and SFT_RST setting in ONOFF_CFG1 * at the same time. So if it try to set PWR_OFF and SFT_RST to ONOFF_CFG1 * simultaneously, handle only SFT_RST and ignore PWR_OFF. */ #define CHECK_ONOFF_CFG1_MASK (ONOFF_SFT_RST_MASK | ONOFF_PWR_OFF_MASK) #define CHECK_ONOFF_CFG1(_addr, _val) \ unlikely((_addr == MAX77663_REG_ONOFF_CFG1) && \ ((_val & CHECK_ONOFF_CFG1_MASK) == CHECK_ONOFF_CFG1_MASK)) static inline int max77663_i2c_write(struct max77663_chip *chip, u8 addr, void *src, u32 bytes, bool is_rtc) { int ret = 0; dev_dbg(chip->dev, "i2c_write: addr=0x%02x, src=0x%02x, bytes=%u\n", addr, *((u8 *)src), bytes); if (is_rtc) { /* RTC registers support sequential writing */ ret = regmap_bulk_write(chip->regmap_rtc, addr, src, bytes); } else { /* Power registers support register-data pair writing */ u8 *src8 = (u8 *)src; unsigned int val; int i; for (i = 0; i < bytes; i++) { if (CHECK_ONOFF_CFG1(addr, *src8)) val = *src8++ & ~ONOFF_PWR_OFF_MASK; else val = *src8++; ret = regmap_write(chip->regmap_power, addr, val); if (ret < 0) break; addr++; } } if (ret < 0) dev_err(chip->dev, "%s() failed, e %d\n", __func__, ret); return ret; } static inline int max77663_i2c_read(struct max77663_chip *chip, u8 addr, void *dest, u32 bytes, bool is_rtc) { int ret = 0; struct regmap *regmap = chip->regmap_power; if (is_rtc) regmap = chip->regmap_rtc; ret = regmap_bulk_read(regmap, addr, dest, bytes); if (ret < 0) { dev_err(chip->dev, "%s() failed, e %d\n", __func__, ret); return ret; } dev_dbg(chip->dev, "i2c_read: addr=0x%02x, dest=0x%02x, bytes=%u\n", addr, *((u8 *)dest), bytes); return ret; } int max77663_read(struct device *dev, u8 addr, void *values, u32 len, bool is_rtc) { struct max77663_chip *chip = dev_get_drvdata(dev); int ret; mutex_lock(&chip->io_lock); ret = max77663_i2c_read(chip, addr, values, len, is_rtc); mutex_unlock(&chip->io_lock); return ret; } EXPORT_SYMBOL(max77663_read); int max77663_write(struct device *dev, u8 addr, void *values, u32 len, bool is_rtc) { struct max77663_chip *chip = dev_get_drvdata(dev); int ret; mutex_lock(&chip->io_lock); ret = max77663_i2c_write(chip, addr, values, len, is_rtc); mutex_unlock(&chip->io_lock); return ret; } EXPORT_SYMBOL(max77663_write); int max77663_set_bits(struct device *dev, u8 addr, u8 mask, u8 value, bool is_rtc) { struct max77663_chip *chip = dev_get_drvdata(dev); int ret; struct regmap *regmap = chip->regmap_power; if (is_rtc) regmap = chip->regmap_rtc; mutex_lock(&chip->io_lock); ret = regmap_update_bits(regmap, addr, mask, value); mutex_unlock(&chip->io_lock); return ret; } EXPORT_SYMBOL(max77663_set_bits); static void max77663_power_off(void) { struct max77663_chip *chip = max77663_chip; if (!chip) return; dev_info(chip->dev, "%s: Global shutdown\n", __func__); max77663_set_bits(chip->dev, MAX77663_REG_ONOFF_CFG1, ONOFF_SFT_RST_MASK, ONOFF_SFT_RST_MASK, 0); } static int max77663_sleep(struct max77663_chip *chip, bool on) { int ret = 0; if (chip->pdata->flags & SLP_LPM_ENABLE) { /* Put the power rails into Low-Power mode during sleep mode, * if the power rail's power mode is GLPM. */ ret = max77663_set_bits(chip->dev, MAX77663_REG_ONOFF_CFG2, ONOFF_SLP_LPM_MASK, on ? ONOFF_SLP_LPM_MASK : 0, 0); if (ret < 0) return ret; } /* Enable sleep that AP can be placed into sleep mode * by pulling EN1 low */ return max77663_set_bits(chip->dev, MAX77663_REG_ONOFF_CFG1, ONOFF_SLPEN_MASK, on ? ONOFF_SLPEN_MASK : 0, 0); } static inline int max77663_cache_write(struct device *dev, u8 addr, u8 mask, u8 val, u8 *cache) { u8 new_val; int ret; new_val = (*cache & ~mask) | (val & mask); if (*cache != new_val) { ret = max77663_write(dev, addr, &new_val, 1, 0); if (ret < 0) return ret; *cache = new_val; } return 0; } static void max77663_irq_mask(struct irq_data *data) { struct max77663_chip *chip = irq_data_get_irq_chip_data(data); max77663_irqs[data->irq - chip->irq_base].is_unmask = 0; } static void max77663_irq_unmask(struct irq_data *data) { struct max77663_chip *chip = irq_data_get_irq_chip_data(data); max77663_irqs[data->irq - chip->irq_base].is_unmask = 1; } static void max77663_irq_lock(struct irq_data *data) { struct max77663_chip *chip = irq_data_get_irq_chip_data(data); mutex_lock(&chip->irq_lock); } static void max77663_irq_sync_unlock(struct irq_data *data) { struct max77663_chip *chip = irq_data_get_irq_chip_data(data); struct max77663_irq_data *irq_data = &max77663_irqs[data->irq - chip->irq_base]; int idx = irq_data->cache_idx; u8 irq_top_mask = chip->cache_irq_top_mask; u16 irq_mask = chip->cache_irq_mask[idx]; int update_irq_top = 0; u32 len = 1; int ret; if (irq_data->is_unmask) { if (chip->irq_top_count[irq_data->top_shift] == 0) update_irq_top = 1; chip->irq_top_count[irq_data->top_shift]++; if (irq_data->top_mask != IRQ_TOP_GLBL_MASK) irq_top_mask &= ~irq_data->top_mask; if (idx != -1) irq_mask &= ~irq_data->mask; } else { if (chip->irq_top_count[irq_data->top_shift] == 1) update_irq_top = 1; if (--chip->irq_top_count[irq_data->top_shift] < 0) chip->irq_top_count[irq_data->top_shift] = 0; if (irq_data->top_mask != IRQ_TOP_GLBL_MASK) irq_top_mask |= irq_data->top_mask; if (idx != -1) irq_mask |= irq_data->mask; } if ((idx != -1) && (irq_mask != chip->cache_irq_mask[idx])) { if (irq_data->top_mask == IRQ_TOP_LDO_MASK) len = 2; ret = max77663_write(chip->dev, irq_data->mask_reg, &irq_mask, len, irq_data->is_rtc); if (ret < 0) goto out; chip->cache_irq_mask[idx] = irq_mask; } if (update_irq_top && (irq_top_mask != chip->cache_irq_top_mask)) { ret = max77663_cache_write(chip->dev, MAX77663_REG_IRQ_TOP_MASK, irq_data->top_mask, irq_top_mask, &chip->cache_irq_top_mask); if (ret < 0) goto out; } out: mutex_unlock(&chip->irq_lock); } static inline int max77663_do_irq(struct max77663_chip *chip, u8 addr, int irq_base, int irq_end) { struct max77663_irq_data *irq_data = NULL; int irqs_to_handle[irq_end - irq_base + 1]; int handled = 0; u16 val; u32 len = 1; int i; int ret; ret = max77663_read(chip->dev, addr, &val, len, 0); if (ret < 0) return ret; for (i = irq_base; i <= irq_end; i++) { irq_data = &max77663_irqs[i]; if (val & irq_data->mask) { irqs_to_handle[handled] = i + chip->irq_base; handled++; } } for (i = 0; i < handled; i++) handle_nested_irq(irqs_to_handle[i]); return 0; } static irqreturn_t max77663_irq(int irq, void *data) { struct max77663_chip *chip = data; u8 irq_top; int ret; ret = max77663_read(chip->dev, MAX77663_REG_IRQ_TOP, &irq_top, 1, 0); if (ret < 0) { dev_err(chip->dev, "irq: Failed to get irq top status\n"); return IRQ_NONE; } if (irq_top & IRQ_TOP_GLBL_MASK) { ret = max77663_do_irq(chip, MAX77663_REG_LBT_IRQ, IRQ_LBT_BASE, IRQ_LBT_END); if (ret < 0) return IRQ_NONE; } if (irq_top & IRQ_TOP_GPIO_MASK) handle_nested_irq(MAX77663_IRQ_INT_TOP_GPIO + chip->irq_base); if (irq_top & IRQ_TOP_ONOFF_MASK) { ret = max77663_do_irq(chip, MAX77663_REG_ONOFF_IRQ, IRQ_ONOFF_BASE, IRQ_ONOFF_END); if (ret < 0) return IRQ_NONE; } if (irq_top & IRQ_TOP_RTC_MASK) handle_nested_irq(MAX77663_IRQ_RTC + chip->irq_base); if (irq_top & IRQ_TOP_SD_MASK) handle_nested_irq(MAX77663_IRQ_SD_PF + chip->irq_base); if (irq_top & IRQ_TOP_LDO_MASK) handle_nested_irq(MAX77663_IRQ_LDO_PF + chip->irq_base); if (irq_top & IRQ_TOP_32K_MASK) handle_nested_irq(MAX77663_IRQ_32K + chip->irq_base); if (irq_top & IRQ_TOP_NVER_MASK) handle_nested_irq(MAX77663_IRQ_NVER + chip->irq_base); return IRQ_HANDLED; } static struct irq_chip max77663_irq_chip = { .name = "max77663-irq", .irq_mask = max77663_irq_mask, .irq_unmask = max77663_irq_unmask, .irq_bus_lock = max77663_irq_lock, .irq_bus_sync_unlock = max77663_irq_sync_unlock, }; static int max77663_irq_init(struct max77663_chip *chip) { u32 temp; int i, ret = 0; mutex_init(&chip->irq_lock); /* Mask all interrupts */ chip->cache_irq_top_mask = 0xFF; chip->cache_irq_mask[CACHE_IRQ_LBT] = 0x0F; chip->cache_irq_mask[CACHE_IRQ_SD] = 0xFF; chip->cache_irq_mask[CACHE_IRQ_LDO] = 0xFFFF; chip->cache_irq_mask[CACHE_IRQ_ONOFF] = 0xFF; max77663_write(chip->dev, MAX77663_REG_IRQ_TOP_MASK, &chip->cache_irq_top_mask, 1, 0); max77663_write(chip->dev, MAX77663_REG_LBT_IRQ_MASK, &chip->cache_irq_mask[CACHE_IRQ_LBT], 1, 0); max77663_write(chip->dev, MAX77663_REG_SD_IRQ_MASK, &chip->cache_irq_mask[CACHE_IRQ_SD], 1, 0); max77663_write(chip->dev, MAX77663_REG_LDOX_IRQ_MASK, &chip->cache_irq_mask[CACHE_IRQ_LDO], 2, 0); max77663_write(chip->dev, MAX77663_REG_ONOFF_IRQ_MASK, &chip->cache_irq_mask[CACHE_IRQ_ONOFF], 1, 0); /* Clear all interrups */ max77663_read(chip->dev, MAX77663_REG_LBT_IRQ, &temp, 1, 0); max77663_read(chip->dev, MAX77663_REG_SD_IRQ, &temp, 1, 0); max77663_read(chip->dev, MAX77663_REG_LDOX_IRQ, &temp, 2, 0); //max77663_read(chip->dev, MAX77663_REG_GPIO_IRQ, &temp, 1, 0); max77663_read(chip->dev, MAX77663_REG_ONOFF_IRQ, &temp, 1, 0); for (i = chip->irq_base; i < (MAX77663_IRQ_NR + chip->irq_base); i++) { int irq = i - chip->irq_base; if (i >= NR_IRQS) { dev_err(chip->dev, "irq_init: Can't set irq chip for irq %d\n", i); continue; } if ((irq >= MAX77663_IRQ_GPIO0) && (irq <= MAX77663_IRQ_GPIO7)) continue; irq_set_chip_data(i, chip); irq_set_chip_and_handler(i, &max77663_irq_chip, handle_edge_irq); #ifdef CONFIG_ARM set_irq_flags(i, IRQF_VALID); #else irq_set_noprobe(i); #endif irq_set_nested_thread(i, 1); } ret = request_threaded_irq(chip->i2c_power->irq, NULL, max77663_irq, IRQF_ONESHOT, "max77663", chip); if (ret) { dev_err(chip->dev, "irq_init: Failed to request irq %d\n", chip->i2c_power->irq); return ret; } device_init_wakeup(chip->dev, 1); enable_irq_wake(chip->i2c_power->irq); chip->cache_irq_top_mask &= ~IRQ_TOP_GLBL_MASK; max77663_write(chip->dev, MAX77663_REG_IRQ_TOP_MASK, &chip->cache_irq_top_mask, 1, 0); chip->cache_irq_mask[CACHE_IRQ_LBT] &= ~IRQ_GLBL_MASK; max77663_write(chip->dev, MAX77663_REG_LBT_IRQ_MASK, &chip->cache_irq_mask[CACHE_IRQ_LBT], 1, 0); chip->cache_irq_mask[CACHE_IRQ_ONOFF] &= ~ONOFF_IRQ_EN0_RISING; max77663_write(chip->dev, MAX77663_REG_ONOFF_IRQ_MASK, &chip->cache_irq_mask[CACHE_IRQ_ONOFF], 1, 0); return 0; } static void max77663_irq_exit(struct max77663_chip *chip) { if (chip->i2c_power->irq) free_irq(chip->i2c_power->irq, chip); } #ifdef CONFIG_DEBUG_FS static struct dentry *max77663_dentry_regs; static int max77663_debugfs_dump_regs(struct max77663_chip *chip, char *label, u8 *addrs, int num_addrs, char *buf, ssize_t *len, int is_rtc) { ssize_t count = *len; u8 val; int ret = 0; int i; count += sprintf(buf + count, "%s\n", label); if (count >= PAGE_SIZE - 1) return -ERANGE; for (i = 0; i < num_addrs; i++) { count += sprintf(buf + count, "0x%02x: ", addrs[i]); if (count >= PAGE_SIZE - 1) return -ERANGE; ret = max77663_read(chip->dev, addrs[i], &val, 1, is_rtc); if (ret == 0) count += sprintf(buf + count, "0x%02x\n", val); else count += sprintf(buf + count, "\n", ret); if (count >= PAGE_SIZE - 1) return -ERANGE; } *len = count; return 0; } static int max77663_debugfs_regs_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; return 0; } static ssize_t max77663_debugfs_regs_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct max77663_chip *chip = file->private_data; char *buf; size_t len = 0; ssize_t ret; /* Excluded interrupt status register to prevent register clear */ u8 global_regs[] = { 0x00, 0x01, 0x02, 0x05, 0x0D, 0x0E, 0x13 }; u8 sd_regs[] = { 0x07, 0x0F, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22 }; u8 ldo_regs[] = { 0x10, 0x11, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35 }; u8 gpio_regs[] = { 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40 }; u8 rtc_regs[] = { 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B }; u8 osc_32k_regs[] = { 0x03 }; u8 bbc_regs[] = { 0x04 }; u8 onoff_regs[] = { 0x12, 0x15, 0x41, 0x42 }; u8 fps_regs[] = { 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57 }; u8 cid_regs[] = { 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D }; buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; len += sprintf(buf + len, "MAX77663 Registers\n"); max77663_debugfs_dump_regs(chip, "[Global]", global_regs, ARRAY_SIZE(global_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[Step-Down]", sd_regs, ARRAY_SIZE(sd_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[LDO]", ldo_regs, ARRAY_SIZE(ldo_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[GPIO]", gpio_regs, ARRAY_SIZE(gpio_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[RTC]", rtc_regs, ARRAY_SIZE(rtc_regs), buf, &len, 1); max77663_debugfs_dump_regs(chip, "[32kHz Oscillator]", osc_32k_regs, ARRAY_SIZE(osc_32k_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[Backup Battery Charger]", bbc_regs, ARRAY_SIZE(bbc_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[On/OFF Controller]", onoff_regs, ARRAY_SIZE(onoff_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[Flexible Power Sequencer]", fps_regs, ARRAY_SIZE(fps_regs), buf, &len, 0); max77663_debugfs_dump_regs(chip, "[Chip Identification]", cid_regs, ARRAY_SIZE(cid_regs), buf, &len, 0); ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret; } static const struct file_operations max77663_debugfs_regs_fops = { .open = max77663_debugfs_regs_open, .read = max77663_debugfs_regs_read, }; static void max77663_debugfs_init(struct max77663_chip *chip) { max77663_dentry_regs = debugfs_create_file(chip->i2c_power->name, 0444, 0, chip, &max77663_debugfs_regs_fops); if (!max77663_dentry_regs) dev_warn(chip->dev, "debugfs_init: Failed to create debugfs file\n"); } static void max77663_debugfs_exit(struct max77663_chip *chip) { debugfs_remove(max77663_dentry_regs); } #else static inline void max77663_debugfs_init(struct max77663_chip *chip) { } static inline void max77663_debugfs_exit(struct max77663_chip *chip) { } #endif /* CONFIG_DEBUG_FS */ static bool rd_wr_reg_power(struct device *dev, unsigned int reg) { if (reg < 0x60) return true; dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg); BUG(); return false; } static bool rd_wr_reg_rtc(struct device *dev, unsigned int reg) { if (reg < 0x1C) return true; dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg); BUG(); return false; } int max77663_read_chip_version(struct device *dev, u8 *val) { int ret, version; version = MAX77663_DRV_NOT_DEFINED; ret = max77663_read(dev, MAX77663_REG_CID4, val, 1, 0); if (!ret) { if (*val == 0x24) version = MAX77663_DRV_24; return version; } return ret; } static const struct regmap_config max77663_regmap_config_power = { .reg_bits = 8, .val_bits = 8, .max_register = 0x60, .writeable_reg = rd_wr_reg_power, .readable_reg = rd_wr_reg_power, .cache_type = REGCACHE_RBTREE, }; static const struct regmap_config max77663_regmap_config_rtc = { .reg_bits = 8, .val_bits = 8, .max_register = 0x1C, .writeable_reg = rd_wr_reg_rtc, .readable_reg = rd_wr_reg_rtc, .cache_type = REGCACHE_RBTREE, }; static int max77663_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max77663_platform_data *pdata = client->dev.platform_data; struct max77663_chip *chip; int ret = 0; u8 val; if (pdata == NULL) { dev_err(&client->dev, "probe: Invalid platform_data\n"); return -ENODEV; } chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (chip == NULL) { dev_err(&client->dev, "probe: kzalloc() failed\n"); return -ENOMEM; } max77663_chip = chip; chip->i2c_power = client; i2c_set_clientdata(client, chip); chip->regmap_power = devm_regmap_init_i2c(client, &max77663_regmap_config_power); if (IS_ERR(chip->regmap_power)) { ret = PTR_ERR(chip->regmap_power); dev_err(&client->dev, "power regmap init failed: %d\n", ret); return ret; } if (pdata->rtc_i2c_addr) chip->rtc_i2c_addr = pdata->rtc_i2c_addr; else chip->rtc_i2c_addr = MAX77663_RTC_I2C_ADDR; chip->i2c_rtc = i2c_new_dummy(client->adapter, chip->rtc_i2c_addr); if (!chip->i2c_rtc) { dev_err(&client->dev, "can't attach client at addr 0x%x\n", chip->rtc_i2c_addr); return -ENOMEM; } i2c_set_clientdata(chip->i2c_rtc, chip); chip->regmap_rtc = devm_regmap_init_i2c(chip->i2c_rtc, &max77663_regmap_config_rtc); if (IS_ERR(chip->regmap_rtc)) { ret = PTR_ERR(chip->regmap_rtc); dev_err(&client->dev, "rtc tegmap init failed: %d\n", ret); goto out_rtc_regmap_fail; } chip->dev = &client->dev; chip->pdata = pdata; chip->irq_base = pdata->irq_base; mutex_init(&chip->io_lock); /* Dummy read to see if chip is present or not*/ ret = max77663_read(chip->dev, MAX77663_REG_CID5, &val, 1, 0); if (ret < 0) { dev_err(chip->dev, "preinit: Failed to get register 0x%x\n", MAX77663_REG_CID5); return ret; } /* Reading chip version */ ret = max77663_read_chip_version(chip->dev, &val); if (ret < 0) dev_err(chip->dev, "Failed to read chip version\n"); else dev_dbg(chip->dev, "Chip version - 0x%x\n", val); max77663_irq_init(chip); max77663_debugfs_init(chip); ret = max77663_sleep(chip, false); if (ret < 0) { dev_err(&client->dev, "probe: Failed to disable sleep\n"); goto out_exit; } if (pdata->use_power_off && !pm_power_off) pm_power_off = max77663_power_off; ret = mfd_add_devices(&client->dev, -1, max77663_cells, ARRAY_SIZE(max77663_cells), NULL, chip->irq_base, NULL); if (ret < 0) { dev_err(&client->dev, "mfd add dev failed, e = %d\n", ret); goto out_exit; } ret = mfd_add_devices(&client->dev, 0, pdata->sub_devices, pdata->num_subdevs, NULL, 0, NULL); if (ret != 0) { dev_err(&client->dev, "probe: Failed to add subdev: %d\n", ret); goto out_mfd_clean; } return 0; out_mfd_clean: mfd_remove_devices(chip->dev); out_exit: max77663_debugfs_exit(chip); max77663_irq_exit(chip); mutex_destroy(&chip->io_lock); out_rtc_regmap_fail: i2c_unregister_device(chip->i2c_rtc); max77663_chip = NULL; return ret; } static int max77663_remove(struct i2c_client *client) { struct max77663_chip *chip = i2c_get_clientdata(client); mfd_remove_devices(chip->dev); max77663_debugfs_exit(chip); max77663_irq_exit(chip); mutex_destroy(&chip->io_lock); i2c_unregister_device(chip->i2c_rtc); max77663_chip = NULL; return 0; } #ifdef CONFIG_PM_SLEEP static int max77663_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct max77663_chip *chip = i2c_get_clientdata(client); int ret; if (client->irq) disable_irq(client->irq); ret = max77663_sleep(chip, true); if (ret < 0) dev_err(dev, "suspend: Failed to enable sleep\n"); return ret; } static int max77663_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct max77663_chip *chip = i2c_get_clientdata(client); int ret; ret = max77663_sleep(chip, false); if (ret < 0) { dev_err(dev, "resume: Failed to disable sleep\n"); return ret; } if (client->irq) enable_irq(client->irq); return 0; } #else #define max77663_suspend NULL #define max77663_resume NULL #endif /* CONFIG_PM_SLEEP */ static const struct i2c_device_id max77663_id[] = { {"max77663", 0}, {}, }; MODULE_DEVICE_TABLE(i2c, max77663_id); static const struct dev_pm_ops max77663_pm = { .suspend = max77663_suspend, .resume = max77663_resume, }; static struct i2c_driver max77663_driver = { .driver = { .name = "max77663", .owner = THIS_MODULE, .pm = &max77663_pm, }, .probe = max77663_probe, .remove = max77663_remove, .id_table = max77663_id, }; static int __init max77663_init(void) { return i2c_add_driver(&max77663_driver); } subsys_initcall(max77663_init); static void __exit max77663_exit(void) { i2c_del_driver(&max77663_driver); } module_exit(max77663_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("MAX77663 Multi Function Device Core Driver"); MODULE_VERSION("1.0");