1f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong/* 2f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * MFD core driver for Rockchip RK808 3f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * 4f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd 5f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * 6f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * Author: Chris Zhong <zyw@rock-chips.com> 7f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * Author: Zhang Qing <zhangqing@rock-chips.com> 8f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * 9f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * This program is free software; you can redistribute it and/or modify it 10f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * under the terms and conditions of the GNU General Public License, 11f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * version 2, as published by the Free Software Foundation. 12f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * 13f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * This program is distributed in the hope it will be useful, but WITHOUT 14f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 16f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong * more details. 17f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong */ 18f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 19f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong#include <linux/i2c.h> 20f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong#include <linux/interrupt.h> 21f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong#include <linux/mfd/rk808.h> 22f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong#include <linux/mfd/core.h> 23f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong#include <linux/module.h> 24f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong#include <linux/regmap.h> 25f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 26f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstruct rk808_reg_data { 27f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong int addr; 28f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong int mask; 29f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong int value; 30f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 31f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 322adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Andersonstatic bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) 332adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson{ 342adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson /* 352adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson * Notes: 362adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but 372adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson * we don't use that feature. It's better to cache. 382adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since 392adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson * bits are cleared in case when we shutoff anyway, but better safe. 402adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson */ 412adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson 422adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson switch (reg) { 432adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_SECONDS_REG ... RK808_WEEKS_REG: 442adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_RTC_STATUS_REG: 452adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_VB_MON_REG: 462adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_THERMAL_REG: 472adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_DCDC_UV_STS_REG: 482adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_LDO_UV_STS_REG: 492adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_DCDC_PG_REG: 502adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_LDO_PG_REG: 512adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_DEVCTRL_REG: 522adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_INT_STS_REG1: 532adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson case RK808_INT_STS_REG2: 542adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson return true; 552adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson } 562adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson 572adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson return false; 582adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson} 592adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson 60f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic const struct regmap_config rk808_regmap_config = { 61f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_bits = 8, 62f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .val_bits = 8, 63f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .max_register = RK808_IO_POL_REG, 642adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson .cache_type = REGCACHE_RBTREE, 652adb3b8e6fa310d64ea6209f8ac5d5575839f6daDoug Anderson .volatile_reg = rk808_is_volatile_reg, 66f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 67f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 68f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic struct resource rtc_resources[] = { 69f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { 70f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .start = RK808_IRQ_RTC_ALARM, 71f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .end = RK808_IRQ_RTC_ALARM, 72f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .flags = IORESOURCE_IRQ, 73f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 74f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 75f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 76f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic const struct mfd_cell rk808s[] = { 77f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { .name = "rk808-clkout", }, 78f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { .name = "rk808-regulator", }, 79f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { 80f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .name = "rk808-rtc", 81f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .num_resources = ARRAY_SIZE(rtc_resources), 82f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .resources = &rtc_resources[0], 83f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 84f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 85f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 86f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic const struct rk808_reg_data pre_init_reg[] = { 87f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, 88f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, 89f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, 90f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA }, 91f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA }, 92f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | 93f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong VB_LO_SEL_3500MV }, 94f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 95f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 96f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic const struct regmap_irq rk808_irqs[] = { 97f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong /* INT_STS */ 98f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_VOUT_LO] = { 99f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_VOUT_LO_MSK, 100f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 0, 101f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 102f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_VB_LO] = { 103f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_VB_LO_MSK, 104f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 0, 105f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 106f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_PWRON] = { 107f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_PWRON_MSK, 108f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 0, 109f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 110f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_PWRON_LP] = { 111f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_PWRON_LP_MSK, 112f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 0, 113f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 114f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_HOTDIE] = { 115f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_HOTDIE_MSK, 116f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 0, 117f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 118f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_RTC_ALARM] = { 119f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_RTC_ALARM_MSK, 120f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 0, 121f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 122f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_RTC_PERIOD] = { 123f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_RTC_PERIOD_MSK, 124f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 0, 125f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 126f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 127f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong /* INT_STS2 */ 128f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_PLUG_IN_INT] = { 129f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_PLUG_IN_INT_MSK, 130f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 1, 131f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 132f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong [RK808_IRQ_PLUG_OUT_INT] = { 133f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask = RK808_IRQ_PLUG_OUT_INT_MSK, 134f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .reg_offset = 1, 135f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 136f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 137f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 138f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic struct regmap_irq_chip rk808_irq_chip = { 139f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .name = "rk808", 140f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .irqs = rk808_irqs, 141f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .num_irqs = ARRAY_SIZE(rk808_irqs), 142f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .num_regs = 2, 143f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .irq_reg_stride = 2, 144f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .status_base = RK808_INT_STS_REG1, 145f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .mask_base = RK808_INT_STS_MSK_REG1, 146f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .ack_base = RK808_INT_STS_REG1, 147f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .init_ack_masked = true, 148f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 149f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 150f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic struct i2c_client *rk808_i2c_client; 151f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic void rk808_device_shutdown(void) 152f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong{ 153f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong int ret; 154f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 155f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 156f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (!rk808) { 157f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong dev_warn(&rk808_i2c_client->dev, 158f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong "have no rk808, so do nothing here\n"); 159f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return; 160f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 161f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 162f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong ret = regmap_update_bits(rk808->regmap, 163f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong RK808_DEVCTRL_REG, 164f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong DEV_OFF_RST, DEV_OFF_RST); 165f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (ret) 166f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong dev_err(&rk808_i2c_client->dev, "power off error!\n"); 167f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong} 168f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 169f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic int rk808_probe(struct i2c_client *client, 170f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong const struct i2c_device_id *id) 171f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong{ 172f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong struct device_node *np = client->dev.of_node; 173f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong struct rk808 *rk808; 174f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong int pm_off = 0; 175f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong int ret; 176f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong int i; 177f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 178f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (!client->irq) { 179f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong dev_err(&client->dev, "No interrupt support, no core IRQ\n"); 180f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return -EINVAL; 181f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 182f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 183f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); 184f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (!rk808) 185f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return -ENOMEM; 186f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 187f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong rk808->regmap = devm_regmap_init_i2c(client, &rk808_regmap_config); 188f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (IS_ERR(rk808->regmap)) { 189f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong dev_err(&client->dev, "regmap initialization failed\n"); 190f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return PTR_ERR(rk808->regmap); 191f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 192f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 193f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong for (i = 0; i < ARRAY_SIZE(pre_init_reg); i++) { 194f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr, 195f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong pre_init_reg[i].mask, 196f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong pre_init_reg[i].value); 197f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (ret) { 198f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong dev_err(&client->dev, 199f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong "0x%x write err\n", pre_init_reg[i].addr); 200f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return ret; 201f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 202f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 203f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 204f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong ret = regmap_add_irq_chip(rk808->regmap, client->irq, 205f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong IRQF_ONESHOT, -1, 206f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong &rk808_irq_chip, &rk808->irq_data); 207f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (ret) { 208f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); 209f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return ret; 210f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 211f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 212f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong rk808->i2c = client; 213f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong i2c_set_clientdata(client, rk808); 214f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 215f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong ret = mfd_add_devices(&client->dev, -1, 216f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong rk808s, ARRAY_SIZE(rk808s), 217f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong NULL, 0, regmap_irq_get_domain(rk808->irq_data)); 218f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (ret) { 219f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong dev_err(&client->dev, "failed to add MFD devices %d\n", ret); 220f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong goto err_irq; 221f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 222f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 223f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong pm_off = of_property_read_bool(np, 224f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong "rockchip,system-power-controller"); 225f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong if (pm_off && !pm_power_off) { 226f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong rk808_i2c_client = client; 227f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong pm_power_off = rk808_device_shutdown; 228f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong } 229f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 230f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return 0; 231f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 232f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongerr_irq: 233f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong regmap_del_irq_chip(client->irq, rk808->irq_data); 234f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return ret; 235f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong} 236f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 237f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic int rk808_remove(struct i2c_client *client) 238f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong{ 239f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong struct rk808 *rk808 = i2c_get_clientdata(client); 240f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 241f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong regmap_del_irq_chip(client->irq, rk808->irq_data); 242f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong mfd_remove_devices(&client->dev); 243f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong pm_power_off = NULL; 244f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 245f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong return 0; 246f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong} 247f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 248f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic struct of_device_id rk808_of_match[] = { 249f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { .compatible = "rockchip,rk808" }, 250f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { }, 251f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 252f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris ZhongMODULE_DEVICE_TABLE(of, rk808_of_match); 253f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 254f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic const struct i2c_device_id rk808_ids[] = { 255f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { "rk808" }, 256f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong { }, 257f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 258f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris ZhongMODULE_DEVICE_TABLE(i2c, rk808_ids); 259f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 260f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongstatic struct i2c_driver rk808_i2c_driver = { 261f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .driver = { 262f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .name = "rk808", 263f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .of_match_table = rk808_of_match, 264f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong }, 265f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .probe = rk808_probe, 266f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .remove = rk808_remove, 267f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong .id_table = rk808_ids, 268f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong}; 269f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 270f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhongmodule_i2c_driver(rk808_i2c_driver); 271f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris Zhong 272f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris ZhongMODULE_LICENSE("GPL"); 273f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris ZhongMODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); 274f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris ZhongMODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); 275f69a7cf74d5536faa180437581be2a9c0aad1bb1Chris ZhongMODULE_DESCRIPTION("RK808 PMIC driver"); 276