| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * MFD core driver for Rockchip RK808/RK818 |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 9 | 10 | * Copyright (C) 2016 PHYTEC Messtechnik GmbH |
|---|
| 10 | 11 | * |
|---|
| 11 | 12 | * Author: Wadim Egorov <w.egorov@phytec.de> |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 14 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 15 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 18 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 19 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 20 | | - * more details. |
|---|
| 21 | 13 | */ |
|---|
| 22 | 14 | |
|---|
| 23 | 15 | #include <linux/i2c.h> |
|---|
| .. | .. |
|---|
| 167 | 159 | .volatile_reg = rk817_is_volatile_reg, |
|---|
| 168 | 160 | }; |
|---|
| 169 | 161 | |
|---|
| 170 | | -static struct resource rtc_resources[] = { |
|---|
| 171 | | - { |
|---|
| 172 | | - .start = RK808_IRQ_RTC_ALARM, |
|---|
| 173 | | - .end = RK808_IRQ_RTC_ALARM, |
|---|
| 174 | | - .flags = IORESOURCE_IRQ, |
|---|
| 175 | | - } |
|---|
| 162 | +static const struct resource rtc_resources[] = { |
|---|
| 163 | + DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), |
|---|
| 176 | 164 | }; |
|---|
| 177 | 165 | |
|---|
| 178 | | -static struct resource rk816_rtc_resources[] = { |
|---|
| 179 | | - { |
|---|
| 180 | | - .start = RK816_IRQ_RTC_ALARM, |
|---|
| 181 | | - .end = RK816_IRQ_RTC_ALARM, |
|---|
| 182 | | - .flags = IORESOURCE_IRQ, |
|---|
| 183 | | - } |
|---|
| 166 | +static const struct resource rk816_rtc_resources[] = { |
|---|
| 167 | + DEFINE_RES_IRQ(RK816_IRQ_RTC_ALARM), |
|---|
| 184 | 168 | }; |
|---|
| 185 | 169 | |
|---|
| 186 | | -static struct resource rk817_rtc_resources[] = { |
|---|
| 170 | +static const struct resource rk817_rtc_resources[] = { |
|---|
| 187 | 171 | DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM), |
|---|
| 188 | 172 | }; |
|---|
| 189 | 173 | |
|---|
| 190 | | -static struct resource rk805_key_resources[] = { |
|---|
| 191 | | - { |
|---|
| 192 | | - .start = RK805_IRQ_PWRON_FALL, |
|---|
| 193 | | - .end = RK805_IRQ_PWRON_FALL, |
|---|
| 194 | | - .flags = IORESOURCE_IRQ, |
|---|
| 195 | | - }, |
|---|
| 196 | | - { |
|---|
| 197 | | - .start = RK805_IRQ_PWRON_RISE, |
|---|
| 198 | | - .end = RK805_IRQ_PWRON_RISE, |
|---|
| 199 | | - .flags = IORESOURCE_IRQ, |
|---|
| 200 | | - } |
|---|
| 174 | +static const struct resource rk805_key_resources[] = { |
|---|
| 175 | + DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL), |
|---|
| 176 | + DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE), |
|---|
| 201 | 177 | }; |
|---|
| 202 | 178 | |
|---|
| 203 | | -static struct resource rk816_pwrkey_resources[] = { |
|---|
| 204 | | - { |
|---|
| 205 | | - .start = RK816_IRQ_PWRON_FALL, |
|---|
| 206 | | - .end = RK816_IRQ_PWRON_FALL, |
|---|
| 207 | | - .flags = IORESOURCE_IRQ, |
|---|
| 208 | | - }, |
|---|
| 209 | | - { |
|---|
| 210 | | - .start = RK816_IRQ_PWRON_RISE, |
|---|
| 211 | | - .end = RK816_IRQ_PWRON_RISE, |
|---|
| 212 | | - .flags = IORESOURCE_IRQ, |
|---|
| 213 | | - }, |
|---|
| 179 | +static const struct resource rk816_pwrkey_resources[] = { |
|---|
| 180 | + DEFINE_RES_IRQ(RK816_IRQ_PWRON_FALL), |
|---|
| 181 | + DEFINE_RES_IRQ(RK816_IRQ_PWRON_RISE), |
|---|
| 214 | 182 | }; |
|---|
| 215 | 183 | |
|---|
| 216 | | -static struct resource rk817_pwrkey_resources[] = { |
|---|
| 184 | +static const struct resource rk817_pwrkey_resources[] = { |
|---|
| 217 | 185 | DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL), |
|---|
| 218 | 186 | DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE), |
|---|
| 219 | 187 | }; |
|---|
| .. | .. |
|---|
| 613 | 581 | REGMAP_IRQ_REG_LINE(23, 8) |
|---|
| 614 | 582 | }; |
|---|
| 615 | 583 | |
|---|
| 616 | | -static struct regmap_irq_chip rk805_irq_chip = { |
|---|
| 584 | +static const struct regmap_irq_chip rk805_irq_chip = { |
|---|
| 617 | 585 | .name = "rk805", |
|---|
| 618 | 586 | .irqs = rk805_irqs, |
|---|
| 619 | 587 | .num_irqs = ARRAY_SIZE(rk805_irqs), |
|---|
| .. | .. |
|---|
| 668 | 636 | }, |
|---|
| 669 | 637 | }; |
|---|
| 670 | 638 | |
|---|
| 671 | | -static struct regmap_irq_chip rk816_irq_chip = { |
|---|
| 639 | +static const struct regmap_irq_chip rk816_irq_chip = { |
|---|
| 672 | 640 | .name = "rk816", |
|---|
| 673 | 641 | .irqs = rk816_irqs, |
|---|
| 674 | 642 | .num_irqs = ARRAY_SIZE(rk816_irqs), |
|---|
| .. | .. |
|---|
| 680 | 648 | .init_ack_masked = true, |
|---|
| 681 | 649 | }; |
|---|
| 682 | 650 | |
|---|
| 683 | | -static struct regmap_irq_chip rk816_battery_irq_chip = { |
|---|
| 651 | +static const struct regmap_irq_chip rk816_battery_irq_chip = { |
|---|
| 684 | 652 | .name = "rk816_battery", |
|---|
| 685 | 653 | .irqs = rk816_battery_irqs, |
|---|
| 686 | 654 | .num_irqs = ARRAY_SIZE(rk816_battery_irqs), |
|---|
| .. | .. |
|---|
| 691 | 659 | .init_ack_masked = true, |
|---|
| 692 | 660 | }; |
|---|
| 693 | 661 | |
|---|
| 694 | | -static struct regmap_irq_chip rk817_irq_chip = { |
|---|
| 662 | +static const struct regmap_irq_chip rk817_irq_chip = { |
|---|
| 695 | 663 | .name = "rk817", |
|---|
| 696 | 664 | .irqs = rk817_irqs, |
|---|
| 697 | 665 | .num_irqs = ARRAY_SIZE(rk817_irqs), |
|---|
| .. | .. |
|---|
| 719 | 687 | static struct rk808_reg_data *suspend_reg, *resume_reg; |
|---|
| 720 | 688 | static int suspend_reg_num, resume_reg_num; |
|---|
| 721 | 689 | |
|---|
| 722 | | -static void rk805_device_shutdown(void) |
|---|
| 723 | | -{ |
|---|
| 724 | | - int ret; |
|---|
| 725 | | - struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); |
|---|
| 726 | | - |
|---|
| 727 | | - if (!rk808) |
|---|
| 728 | | - return; |
|---|
| 729 | | - |
|---|
| 730 | | - ret = regmap_update_bits(rk808->regmap, |
|---|
| 731 | | - RK805_DEV_CTRL_REG, |
|---|
| 732 | | - DEV_OFF, DEV_OFF); |
|---|
| 733 | | - if (ret) |
|---|
| 734 | | - dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); |
|---|
| 735 | | -} |
|---|
| 736 | | - |
|---|
| 737 | 690 | static void rk805_device_shutdown_prepare(void) |
|---|
| 738 | 691 | { |
|---|
| 739 | 692 | int ret; |
|---|
| .. | .. |
|---|
| 749 | 702 | dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); |
|---|
| 750 | 703 | } |
|---|
| 751 | 704 | |
|---|
| 752 | | -static void rk808_device_shutdown(void) |
|---|
| 753 | | -{ |
|---|
| 754 | | - int ret; |
|---|
| 755 | | - struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); |
|---|
| 756 | | - |
|---|
| 757 | | - if (!rk808) |
|---|
| 758 | | - return; |
|---|
| 759 | | - |
|---|
| 760 | | - ret = regmap_update_bits(rk808->regmap, |
|---|
| 761 | | - RK808_DEVCTRL_REG, |
|---|
| 762 | | - DEV_OFF_RST, DEV_OFF_RST); |
|---|
| 763 | | - if (ret) |
|---|
| 764 | | - dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); |
|---|
| 765 | | -} |
|---|
| 766 | | - |
|---|
| 767 | | -static void rk816_device_shutdown(void) |
|---|
| 768 | | -{ |
|---|
| 769 | | - int ret; |
|---|
| 770 | | - struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); |
|---|
| 771 | | - |
|---|
| 772 | | - if (!rk808) |
|---|
| 773 | | - return; |
|---|
| 774 | | - |
|---|
| 775 | | - ret = regmap_update_bits(rk808->regmap, |
|---|
| 776 | | - RK816_DEV_CTRL_REG, |
|---|
| 777 | | - DEV_OFF, DEV_OFF); |
|---|
| 778 | | - if (ret) |
|---|
| 779 | | - dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); |
|---|
| 780 | | -} |
|---|
| 781 | | - |
|---|
| 782 | 705 | static void rk817_shutdown_prepare(void) |
|---|
| 783 | 706 | { |
|---|
| 784 | 707 | int ret; |
|---|
| 785 | 708 | struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); |
|---|
| 786 | 709 | |
|---|
| 787 | | - /* close int when power off */ |
|---|
| 710 | + /* close rtc int when power off */ |
|---|
| 788 | 711 | regmap_update_bits(rk808->regmap, |
|---|
| 789 | 712 | RK817_INT_STS_MSK_REG0, |
|---|
| 790 | | - 0xff, 0xff); |
|---|
| 791 | | - regmap_update_bits(rk808->regmap, |
|---|
| 792 | | - RK817_INT_STS_MSK_REG1, |
|---|
| 793 | | - 0xff, 0xff); |
|---|
| 794 | | - regmap_update_bits(rk808->regmap, |
|---|
| 795 | | - RK817_INT_STS_MSK_REG2, |
|---|
| 796 | | - 0xff, 0xff); |
|---|
| 713 | + (0x3 << 5), (0x3 << 5)); |
|---|
| 797 | 714 | regmap_update_bits(rk808->regmap, |
|---|
| 798 | 715 | RK817_RTC_INT_REG, |
|---|
| 799 | 716 | (0x3 << 2), (0x0 << 2)); |
|---|
| 800 | | - |
|---|
| 801 | | - dev_info(&rk808_i2c_client->dev, "disabled int when device shutdown!\n"); |
|---|
| 802 | 717 | |
|---|
| 803 | 718 | if (rk808->pins && rk808->pins->p && rk808->pins->power_off) { |
|---|
| 804 | 719 | ret = regmap_update_bits(rk808->regmap, |
|---|
| .. | .. |
|---|
| 832 | 747 | mdelay(2); |
|---|
| 833 | 748 | } |
|---|
| 834 | 749 | |
|---|
| 835 | | -static void rk818_device_shutdown(void) |
|---|
| 750 | +static void rk8xx_device_shutdown(void) |
|---|
| 836 | 751 | { |
|---|
| 837 | 752 | int ret; |
|---|
| 753 | + unsigned int reg, bit; |
|---|
| 838 | 754 | struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); |
|---|
| 839 | 755 | |
|---|
| 840 | | - if (!rk808) |
|---|
| 756 | + switch (rk808->variant) { |
|---|
| 757 | + case RK805_ID: |
|---|
| 758 | + reg = RK805_DEV_CTRL_REG; |
|---|
| 759 | + bit = DEV_OFF; |
|---|
| 760 | + break; |
|---|
| 761 | + case RK808_ID: |
|---|
| 762 | + reg = RK808_DEVCTRL_REG, |
|---|
| 763 | + bit = DEV_OFF_RST; |
|---|
| 764 | + break; |
|---|
| 765 | + case RK816_ID: |
|---|
| 766 | + reg = RK816_DEV_CTRL_REG; |
|---|
| 767 | + bit = DEV_OFF; |
|---|
| 768 | + break; |
|---|
| 769 | + case RK818_ID: |
|---|
| 770 | + reg = RK818_DEVCTRL_REG; |
|---|
| 771 | + bit = DEV_OFF; |
|---|
| 772 | + break; |
|---|
| 773 | + default: |
|---|
| 841 | 774 | return; |
|---|
| 775 | + } |
|---|
| 842 | 776 | |
|---|
| 843 | | - ret = regmap_update_bits(rk808->regmap, |
|---|
| 844 | | - RK818_DEVCTRL_REG, |
|---|
| 845 | | - DEV_OFF, DEV_OFF); |
|---|
| 777 | + ret = regmap_update_bits(rk808->regmap, reg, bit, bit); |
|---|
| 846 | 778 | if (ret) |
|---|
| 847 | 779 | dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); |
|---|
| 848 | 780 | } |
|---|
| .. | .. |
|---|
| 1205 | 1137 | void (*of_property_prepare_fn)(struct rk808 *rk808, |
|---|
| 1206 | 1138 | struct device *dev) = NULL; |
|---|
| 1207 | 1139 | int (*pinctrl_init)(struct device *dev, struct rk808 *rk808) = NULL; |
|---|
| 1140 | + void (*device_shutdown_fn)(void) = NULL; |
|---|
| 1208 | 1141 | |
|---|
| 1209 | 1142 | rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); |
|---|
| 1210 | 1143 | if (!rk808) |
|---|
| .. | .. |
|---|
| 1251 | 1184 | suspend_reg_num = ARRAY_SIZE(rk805_suspend_reg); |
|---|
| 1252 | 1185 | resume_reg = rk805_resume_reg; |
|---|
| 1253 | 1186 | resume_reg_num = ARRAY_SIZE(rk805_resume_reg); |
|---|
| 1254 | | - rk808->pm_pwroff_fn = rk805_device_shutdown; |
|---|
| 1187 | + device_shutdown_fn = rk8xx_device_shutdown; |
|---|
| 1255 | 1188 | rk808->pm_pwroff_prep_fn = rk805_device_shutdown_prepare; |
|---|
| 1256 | 1189 | break; |
|---|
| 1257 | 1190 | case RK808_ID: |
|---|
| .. | .. |
|---|
| 1261 | 1194 | nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); |
|---|
| 1262 | 1195 | cells = rk808s; |
|---|
| 1263 | 1196 | nr_cells = ARRAY_SIZE(rk808s); |
|---|
| 1264 | | - rk808->pm_pwroff_fn = rk808_device_shutdown; |
|---|
| 1197 | + device_shutdown_fn = rk8xx_device_shutdown; |
|---|
| 1265 | 1198 | break; |
|---|
| 1266 | 1199 | case RK816_ID: |
|---|
| 1267 | 1200 | rk808->regmap_cfg = &rk816_regmap_config; |
|---|
| .. | .. |
|---|
| 1277 | 1210 | suspend_reg_num = ARRAY_SIZE(rk816_suspend_reg); |
|---|
| 1278 | 1211 | resume_reg = rk816_resume_reg; |
|---|
| 1279 | 1212 | resume_reg_num = ARRAY_SIZE(rk816_resume_reg); |
|---|
| 1280 | | - rk808->pm_pwroff_fn = rk816_device_shutdown; |
|---|
| 1213 | + device_shutdown_fn = rk8xx_device_shutdown; |
|---|
| 1281 | 1214 | break; |
|---|
| 1282 | 1215 | case RK818_ID: |
|---|
| 1283 | 1216 | rk808->regmap_cfg = &rk818_regmap_config; |
|---|
| .. | .. |
|---|
| 1292 | 1225 | suspend_reg_num = ARRAY_SIZE(rk818_suspend_reg); |
|---|
| 1293 | 1226 | resume_reg = rk818_resume_reg; |
|---|
| 1294 | 1227 | resume_reg_num = ARRAY_SIZE(rk818_resume_reg); |
|---|
| 1295 | | - rk808->pm_pwroff_fn = rk818_device_shutdown; |
|---|
| 1228 | + device_shutdown_fn = rk8xx_device_shutdown; |
|---|
| 1296 | 1229 | break; |
|---|
| 1297 | 1230 | case RK809_ID: |
|---|
| 1298 | 1231 | case RK817_ID: |
|---|
| .. | .. |
|---|
| 1402 | 1335 | if (!pm_power_off_prepare) |
|---|
| 1403 | 1336 | pm_power_off_prepare = rk808->pm_pwroff_prep_fn; |
|---|
| 1404 | 1337 | |
|---|
| 1405 | | - if (rk808->pm_pwroff_fn) { |
|---|
| 1338 | + if (device_shutdown_fn) { |
|---|
| 1406 | 1339 | register_syscore_ops(&rk808_syscore_ops); |
|---|
| 1407 | 1340 | /* power off system in the syscore shutdown ! */ |
|---|
| 1408 | | - pm_shutdown = rk808->pm_pwroff_fn; |
|---|
| 1341 | + pm_shutdown = device_shutdown_fn; |
|---|
| 1409 | 1342 | } |
|---|
| 1410 | 1343 | } |
|---|
| 1411 | 1344 | |
|---|
| .. | .. |
|---|
| 1433 | 1366 | struct rk808 *rk808 = i2c_get_clientdata(client); |
|---|
| 1434 | 1367 | |
|---|
| 1435 | 1368 | regmap_del_irq_chip(client->irq, rk808->irq_data); |
|---|
| 1436 | | - mfd_remove_devices(&client->dev); |
|---|
| 1437 | 1369 | |
|---|
| 1438 | 1370 | /** |
|---|
| 1439 | 1371 | * pm_power_off may points to a function from another module. |
|---|
| .. | .. |
|---|
| 1474 | 1406 | } |
|---|
| 1475 | 1407 | |
|---|
| 1476 | 1408 | switch (rk808->variant) { |
|---|
| 1409 | + case RK805_ID: |
|---|
| 1410 | + ret = regmap_update_bits(rk808->regmap, |
|---|
| 1411 | + RK805_GPIO_IO_POL_REG, |
|---|
| 1412 | + SLP_SD_MSK, |
|---|
| 1413 | + SLEEP_FUN); |
|---|
| 1414 | + break; |
|---|
| 1477 | 1415 | case RK809_ID: |
|---|
| 1478 | 1416 | case RK817_ID: |
|---|
| 1479 | 1417 | if (rk808->pins && rk808->pins->p && rk808->pins->sleep) { |
|---|