X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fmfd%2Frk808.c;h=2eadd2c10e6994f8366af01221675f355b1361de;hb=2ae05321496aa27767bc33a5cc19451b3db67919;hp=9d9327828ca571be0864ccc14caea23d77a268b8;hpb=01afa13ceb6b3e695c1a886b25f97a28c5c8d4d7;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 9d9327828ca5..2eadd2c10e69 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include struct rk808_reg_data { int addr; @@ -65,7 +68,32 @@ static int rk808_shutdown(struct regmap *regmap) ret = regmap_update_bits(regmap, RK808_DEVCTRL_REG, - DEV_OFF_RST, DEV_OFF_RST); + DEV_OFF, DEV_OFF); + if (ret) + printk("DEV_OFF error!\n"); + + mdelay(2); + ret = regmap_update_bits(regmap, + RK808_DCDC_EN_REG, + BUCK1_EN_MASK | BUCK2_EN_MASK | BUCK3_EN_MASK | BUCK4_EN_MASK, 0xf); + if (ret) + printk("RK808_DCDC_EN_REG error!\n"); + ret = regmap_update_bits(regmap, + RK808_LDO_EN_REG, + 0xff, 0xff); + if (ret) + printk("RK808_LDO_EN_REG error!\n"); + + return ret; +} + +static int rk816_shutdown(struct regmap *regmap) +{ + int ret; + + ret = regmap_update_bits(regmap, + RK816_DEV_CTRL_REG, + DEV_OFF, DEV_OFF); return ret; } @@ -146,6 +174,22 @@ static const struct regmap_config rk805_regmap_config = { .volatile_reg = rk808_is_volatile_reg, }; +static const struct regmap_config rk816_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK816_DATA18_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk818_is_volatile_reg, +}; + +static const struct regmap_config rk818_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK818_SAVE_DATA19, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk818_is_volatile_reg, +}; + static struct resource rtc_resources[] = { { .start = RK808_IRQ_RTC_ALARM, @@ -167,6 +211,19 @@ static struct resource pwrkey_resources[] = { }, }; +static struct resource rk816_pwrkey_resources[] = { + { + .start = RK816_IRQ_PWRON_RISE, + .end = RK816_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK816_IRQ_PWRON_FALL, + .end = RK816_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, + }, +}; + static const struct mfd_cell rk808s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -184,6 +241,7 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = { { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA }, { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA }, { RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE}, + { RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | VB_LO_SEL_3500MV }, }; @@ -242,17 +300,101 @@ static struct regmap_irq_chip rk808_irq_chip = { .init_ack_masked = true, }; -static const struct regmap_config rk818_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK818_SAVE_DATA19, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk818_is_volatile_reg, +static const struct mfd_cell rk816s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { .name = "rk8xx-gpio", }, + { + .name = "rk8xx-pwrkey", + .num_resources = ARRAY_SIZE(rk816_pwrkey_resources), + .resources = &rk816_pwrkey_resources[0], + }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + }, +}; + +static const struct rk808_reg_data rk816_pre_init_reg[] = { + /* buck4 Max ILMIT*/ + {RK816_BUCK4_CONFIG_REG, BUCK4_MAX_ILIMIT, REG_WRITE_MSK}, + /* hotdie temperature: 105c*/ + {RK816_THERMAL_REG, TEMP105C, REG_WRITE_MSK}, + /* set buck 12.5mv/us */ + {RK816_BUCK1_CONFIG_REG, BUCK_RATE_12_5MV_US, BUCK_RATE_MSK}, + {RK816_BUCK2_CONFIG_REG, BUCK_RATE_12_5MV_US, BUCK_RATE_MSK}, + /* enable RTC_PERIOD & RTC_ALARM int */ + {RK816_INT_STS_MSK_REG2, RTC_PERIOD_ALARM_INT_EN, REG_WRITE_MSK}, + /* set bat 3.0 low and act shutdown */ + {RK816_VB_MON_REG, RK816_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN, + VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK}, + /* enable PWRON rising/faling int */ + {RK816_INT_STS_MSK_REG1, RK816_PWRON_FALL_RISE_INT_EN, REG_WRITE_MSK}, + /* enable PLUG IN/OUT int */ + {RK816_INT_STS_MSK_REG3, PLUGIN_OUT_INT_EN, REG_WRITE_MSK}, + /* clear int flags */ + {RK816_INT_STS_REG1, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_INT_STS_REG2, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_INT_STS_REG3, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_DCDC_EN_REG2, BOOST_DISABLE, BOOST_EN_MASK}, +}; + +static const struct regmap_irq rk816_irqs[] = { + /* INT_STS */ + [RK816_IRQ_PWRON_FALL] = { + .mask = RK816_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_PWRON_RISE] = { + .mask = RK816_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_VB_LOW] = { + .mask = RK816_IRQ_VB_LOW_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON] = { + .mask = RK816_IRQ_PWRON_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON_LP] = { + .mask = RK816_IRQ_PWRON_LP_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_HOTDIE] = { + .mask = RK816_IRQ_HOTDIE_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_ALARM] = { + .mask = RK816_IRQ_RTC_ALARM_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_PERIOD] = { + .mask = RK816_IRQ_RTC_PERIOD_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_USB_OV] = { + .mask = RK816_IRQ_USB_OV_MSK, + .reg_offset = 1, + }, +}; + +static struct regmap_irq_chip rk816_irq_chip = { + .name = "rk816", + .irqs = rk816_irqs, + .num_irqs = ARRAY_SIZE(rk816_irqs), + .num_regs = 2, + .irq_reg_stride = 3, + .status_base = RK816_INT_STS_REG1, + .mask_base = RK816_INT_STS_MSK_REG1, + .ack_base = RK816_INT_STS_REG1, + .init_ack_masked = true, }; static const struct mfd_cell rk818s[] = { { .name = "rk808-clkout", }, - { .name = "rk818-regulator", }, + { .name = "rk808-regulator", }, { .name = "rk818-battery", .of_compatible = "rk818-battery", }, { .name = "rk818-charger", }, { @@ -269,6 +411,7 @@ static const struct rk808_reg_data rk818_pre_init_reg[] = { BOOST_EN_ENABLE | SWITCH_EN_ENABLE }, { RK818_SLEEP_SET_OFF_REG1, OTG_SLP_SET_MASK, OTG_SLP_SET_OFF }, { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA }, + { RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, }; static const struct regmap_irq rk818_irqs[] = { @@ -399,6 +542,7 @@ static struct regmap_irq_chip rk805_irq_chip = { }; static const struct mfd_cell rk805s[] = { + { .name = "rk808-clkout", }, { .name = "rk818-regulator", }, { .name = "rk8xx-gpio", }, { @@ -416,6 +560,7 @@ static const struct mfd_cell rk805s[] = { static const struct rk808_reg_data rk805_pre_init_reg[] = { {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN}, + {RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, }; @@ -428,6 +573,15 @@ static void rk808_device_shutdown_prepare(void) int ret; struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + if (gpio_is_valid(rk808->stby_gpio)) { + printk("rk808->stby_gpio(%d)=low\n", rk808->stby_gpio); + gpio_direction_output(rk808->stby_gpio, 0); + } + if (gpio_is_valid(rk808->hold_gpio)) { + printk("rk808->hold_gpio(%d)=low\n", rk808->hold_gpio); + gpio_direction_output(rk808->hold_gpio, 0); + mdelay(200); + } if (!rk808) { dev_warn(&rk808_i2c_client->dev, "have no rk808, so do nothing here\n"); @@ -454,22 +608,84 @@ static void rk808_device_shutdown(void) } /* close rtc int when power off */ +#if 0 regmap_update_bits(rk808->regmap, RK808_INT_STS_MSK_REG1, (0x3 << 5), (0x3 << 5)); regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, (0x3 << 2), (0x0 << 2)); +#endif + + if (gpio_is_valid(rk808->stby_gpio)) { + printk("rk808->stby_gpio(%d)=low\n", rk808->stby_gpio); + gpio_direction_output(rk808->stby_gpio, 0); + } + if (gpio_is_valid(rk808->hold_gpio)) { + printk("rk808->hold_gpio(%d)=low\n", rk808->hold_gpio); + gpio_direction_output(rk808->hold_gpio, 0); + mdelay(200); + } if (pm_shutdown) { ret = pm_shutdown(rk808->regmap); if (ret) dev_err(&rk808_i2c_client->dev, "power off error!\n"); } + printk("%s-%d: pm_shutdown\n", __FUNCTION__, __LINE__); +} + +static ssize_t rk8xx_dbg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + char cmd; + u32 input[2], addr, data; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + + ret = sscanf(buf, "%c ", &cmd); + switch (cmd) { + case 'w': + ret = sscanf(buf, "%c %x %x ", &cmd, &input[0], &input[1]); + if (ret != 3) { + pr_err("erro! cmd format: echo w [addr] [value]\n"); + goto out; + }; + addr = input[0] & 0xff; + data = input[1] & 0xff; + pr_info("cmd : %c %x %x\n\n", cmd, input[0], input[1]); + regmap_write(rk808->regmap, addr, data); + regmap_read(rk808->regmap, addr, &data); + pr_info("new: %x %x\n", addr, data); + break; + case 'r': + ret = sscanf(buf, "%c %x ", &cmd, &input[0]); + if (ret != 2) { + pr_err("erro! cmd format: echo r [addr]\n"); + goto out; + }; + pr_info("cmd : %c %x\n\n", cmd, input[0]); + addr = input[0] & 0xff; + regmap_read(rk808->regmap, addr, &data); + pr_info("%x %x\n", input[0], data); + break; + default: + pr_err("Unknown command\n"); + break; + } + +out: + return count; } +static struct kobject *rk8xx_kobj; +static struct device_attribute rk8xx_attrs = + __ATTR(rk8xx_dbg, 0200, NULL, rk8xx_dbg_store); + static const struct of_device_id rk808_of_match[] = { { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk816" }, { .compatible = "rockchip,rk818" }, { }, }; @@ -532,6 +748,17 @@ static int rk808_probe(struct i2c_client *client, on_source = RK818_ON_SOURCE_REG; off_source = RK818_OFF_SOURCE_REG; break; + case RK816_ID: + cell = rk816s; + cell_num = ARRAY_SIZE(rk816s); + pre_init_reg = rk816_pre_init_reg; + reg_num = ARRAY_SIZE(rk816_pre_init_reg); + regmap_config = &rk816_regmap_config; + irq_chip = &rk816_irq_chip; + pm_shutdown_fn = rk816_shutdown; + on_source = RK816_ON_SOURCE_REG; + off_source = RK816_OFF_SOURCE_REG; + break; case RK808_ID: cell = rk808s; cell_num = ARRAY_SIZE(rk808s); @@ -628,6 +855,43 @@ static int rk808_probe(struct i2c_client *client, } } + rk8xx_kobj = kobject_create_and_add("rk8xx", NULL); + if (rk8xx_kobj) { + ret = sysfs_create_file(rk8xx_kobj, &rk8xx_attrs.attr); + if (ret) + dev_err(&client->dev, "create rk8xx sysfs error\n"); + } + //pmic,hold-gpio + rk808->hold_gpio = of_get_named_gpio(np, "pmic,hold-gpio", 0); + if (gpio_is_valid(rk808->hold_gpio)) { + ret = devm_gpio_request(&client->dev, rk808->hold_gpio, "pmic-hold-gpio"); + if(ret < 0){ + dev_err(&client->dev, "pmic-hold-gpio request ERROR\n"); + goto err_irq; + } + dev_dbg(&client->dev, "hold_gpio(%d)=high\n", rk808->hold_gpio); + gpio_direction_output(rk808->hold_gpio, 1); + } + else { + dev_err(&client->dev, "Can not read property pmic,hold-gpio\n"); + //goto err_irq; + } + + //pmic,stby-gpio + rk808->stby_gpio = of_get_named_gpio(np, "pmic,stby-gpio", 0); + if (gpio_is_valid(rk808->stby_gpio)) { + ret = devm_gpio_request(&client->dev, rk808->stby_gpio, "pmic-stby-gpio"); + if(ret < 0){ + dev_err(&client->dev, "devm_gpio_request pmic-stby-gpio request ERROR\n"); + goto err_irq; + } + dev_dbg(&client->dev, "stby_gpio(%d)=low\n", rk808->stby_gpio); + gpio_direction_output(rk808->stby_gpio, 1); + } else { + dev_err(&client->dev, "Can not read property pmic,stby-gpio\n"); + //goto err_irq; + } + return 0; err_irq: @@ -652,6 +916,7 @@ static int rk808_remove(struct i2c_client *client) static const struct i2c_device_id rk808_ids[] = { { "rk805" }, { "rk808" }, + { "rk816" }, { "rk818" }, { }, };