[PATCH] mm/mmap: fix the adjusted length error
In linux version 4.4, a 32-bit process may fail to allocate 64M hugepage memory by function shmat even though there is a 64M memory gap in the process. It is the adjusted length that causes the problem, introduced from commit db4fbfb9523c935 ("mm: vm_unmapped_area() lookup function"). Accounting for the worst case alignment overhead, function unmapped_area and unmapped_area_topdown adjust the search length before searching for available vma gap. This is an estimated length, sum of the desired length and the longest alignment offset, which can cause misjudgement if the system has very few virtual memory left. For example, if the longest memory gap available is 64M, we can’t get it from the system by allocating 64M hugepage memory via shmat function. The reason is that it requires a longger length, the sum of the desired length(64M) and the longest alignment offset. To fix this error ,we can calculate the alignment offset of gap_start or gap_end to get a desired gap_start or gap_end value, before searching for the available gap. In this way, we don't need to adjust the search length. Problem reproduces procedure: 1. allocate a lot of virtual memory segments via shmat and malloc 2. release one of the biggest memory segment via shmdt 3. attach the biggest memory segment via shmat e.g. process maps: 8000-9000 r-xp 00:12 3385/tmp/memory_mmap 00011000-00012000 rw-p 1000 00:12 3385/tmp/memory_mmap 27536000-f756a000 rw-p 00:00 0 f756a000-f7691000 r-xp 01:00 560 /lib/libc-2.11.1.so f7691000-f7699000 ---p 00127000 01:00 560 /lib/libc-2.11.1.so f7699000-f769b000 r--p 00127000 01:00 560 /lib/libc-2.11.1.so f769b000-f769c000 rw-p 00129000 01:00 560 /lib/libc-2.11.1.so f769c000-f769f000 rw-p 00:00 0 f769f000-f76c r-xp 01:00 583 /lib/libgcc_s.so.1 f76c-f76c7000 ---p 00021000 01:00 583 /lib/libgcc_s.so.1 f76c7000-f76c8000 rw-p 0002 01:00 583 /lib/libgcc_s.so.1 f76c8000-f76e5000 r-xp 01:00 543 /lib/ld-2.11.1.so f76e9000-f76ea000 rw-p 00:00 0 f76ea000-f76ec000 rw-p 00:00 0 f76ec000-f76ed000 r--p 0001c000 01:00 543 /lib/ld-2.11.1.so f76ed000-f76ee000 rw-p 0001d000 01:00 543 /lib/ld-2.11.1.so f780-f7a0 rw-s 00:0e 0 /SYSV00ea (deleted) fba0-fca0 rw-s 00:0e 65538 /SYSV00ec (deleted) fca0-fce0 rw-s 00:0e 98307 /SYSV00ed (deleted) fce0-fd80 rw-s 00:0e 131076 /SYSV00ee (deleted) ff913000-ff934000 rw-p 00:00 0 [stack] -1000 r-xp 00:00 0 [vectors] from 0xf7a0 to fba0, it has 64M memory gap, but we can't get it from kernel. Signed-off-by: jianhong chen Cc: sta...@vger.kernel.org --- mm/mmap.c | 43 +-- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index bd7b9f2..c5a5782 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1865,6 +1865,22 @@ unsigned long mmap_region(struct file *file, unsigned long addr, return error; } +static inline unsigned long gap_start_offset(struct vm_unmapped_area_info *info, + unsigned long addr) +{ + /* get gap_start offset to adjust gap address to the +* desired alignment +*/ + return (info->align_offset - addr) & info->align_mask; +} + +static inline unsigned long gap_end_offset(struct vm_unmapped_area_info *info, + unsigned long addr) +{ + /* get gap_end offset to adjust gap address to the desired alignment */ + return (addr - info->align_offset) & info->align_mask; +} + unsigned long unmapped_area(struct vm_unmapped_area_info *info) { /* @@ -1879,10 +1895,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) struct vm_area_struct *vma; unsigned long length, low_limit, high_limit, gap_start, gap_end; - /* Adjust search length to account for worst case alignment overhead */ - length = info->length + info->align_mask; - if (length < info->length) - return -ENOMEM; + length = info->length; /* Adjust search limits by the desired length */ if (info->high_limit < length) @@ -1914,6 +1927,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) } gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; + gap_start += gap_start_offset(info, gap_start); check_current: /* Check if current node has a suitable gap */ if (gap_start > high_limit) @@ -1942,6 +1956,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) struct vm_area_struct, vm_rb); if (prev == vma->vm_rb.rb_left) {
[PATCH] mm/mmap: fix the adjusted length error
In linux version 4.4, a 32-bit process may fail to allocate 64M hugepage memory by function shmat even though there is a 64M memory gap in the process. It is the adjusted length that causes the problem, introduced from commit db4fbfb9523c935 ("mm: vm_unmapped_area() lookup function"). Accounting for the worst case alignment overhead, function unmapped_area and unmapped_area_topdown adjust the search length before searching for available vma gap. This is an estimated length, sum of the desired length and the longest alignment offset, which can cause misjudgement if the system has very few virtual memory left. For example, if the longest memory gap available is 64M, we can’t get it from the system by allocating 64M hugepage memory via shmat function. The reason is that it requires a longger length, the sum of the desired length(64M) and the longest alignment offset. To fix this error ,we can calculate the alignment offset of gap_start or gap_end to get a desired gap_start or gap_end value, before searching for the available gap. In this way, we don't need to adjust the search length. Problem reproduces procedure: 1. allocate a lot of virtual memory segments via shmat and malloc 2. release one of the biggest memory segment via shmdt 3. attach the biggest memory segment via shmat e.g. process maps: 8000-9000 r-xp 00:12 3385/tmp/memory_mmap 00011000-00012000 rw-p 1000 00:12 3385/tmp/memory_mmap 27536000-f756a000 rw-p 00:00 0 f756a000-f7691000 r-xp 01:00 560 /lib/libc-2.11.1.so f7691000-f7699000 ---p 00127000 01:00 560 /lib/libc-2.11.1.so f7699000-f769b000 r--p 00127000 01:00 560 /lib/libc-2.11.1.so f769b000-f769c000 rw-p 00129000 01:00 560 /lib/libc-2.11.1.so f769c000-f769f000 rw-p 00:00 0 f769f000-f76c r-xp 01:00 583 /lib/libgcc_s.so.1 f76c-f76c7000 ---p 00021000 01:00 583 /lib/libgcc_s.so.1 f76c7000-f76c8000 rw-p 0002 01:00 583 /lib/libgcc_s.so.1 f76c8000-f76e5000 r-xp 01:00 543 /lib/ld-2.11.1.so f76e9000-f76ea000 rw-p 00:00 0 f76ea000-f76ec000 rw-p 00:00 0 f76ec000-f76ed000 r--p 0001c000 01:00 543 /lib/ld-2.11.1.so f76ed000-f76ee000 rw-p 0001d000 01:00 543 /lib/ld-2.11.1.so f780-f7a0 rw-s 00:0e 0 /SYSV00ea (deleted) fba0-fca0 rw-s 00:0e 65538 /SYSV00ec (deleted) fca0-fce0 rw-s 00:0e 98307 /SYSV00ed (deleted) fce0-fd80 rw-s 00:0e 131076 /SYSV00ee (deleted) ff913000-ff934000 rw-p 00:00 0 [stack] -1000 r-xp 00:00 0 [vectors] from 0xf7a0 to fba0, it has 64M memory gap, but we can't get it from kernel. Signed-off-by: jianhong chen Cc: sta...@vger.kernel.org --- mm/mmap.c | 43 +-- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index bd7b9f2..c5a5782 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1865,6 +1865,22 @@ unsigned long mmap_region(struct file *file, unsigned long addr, return error; } +static inline unsigned long gap_start_offset(struct vm_unmapped_area_info *info, + unsigned long addr) +{ + /* get gap_start offset to adjust gap address to the +* desired alignment +*/ + return (info->align_offset - addr) & info->align_mask; +} + +static inline unsigned long gap_end_offset(struct vm_unmapped_area_info *info, + unsigned long addr) +{ + /* get gap_end offset to adjust gap address to the desired alignment */ + return (addr - info->align_offset) & info->align_mask; +} + unsigned long unmapped_area(struct vm_unmapped_area_info *info) { /* @@ -1879,10 +1895,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) struct vm_area_struct *vma; unsigned long length, low_limit, high_limit, gap_start, gap_end; - /* Adjust search length to account for worst case alignment overhead */ - length = info->length + info->align_mask; - if (length < info->length) - return -ENOMEM; + length = info->length; /* Adjust search limits by the desired length */ if (info->high_limit < length) @@ -1914,6 +1927,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) } gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; + gap_start += gap_start_offset(info, gap_start); check_current: /* Check if current node has a suitable gap */ if (gap_start > high_limit) @@ -1942,6 +1956,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) struct vm_area_struct, vm_rb); if (prev == vma->vm_rb.rb_left) {
Re: [PATCH v6 08/12] gpio: Add GPIO driver for the RK805 PMIC
在 2017/6/29 18:29, Heiko Stübner 写道: Hi, Am Mittwoch, 14. Juni 2017, 20:11:06 CEST schrieb Jianhong Chen: 在 2017/6/9 20:17, Heiko Stuebner 写道: Am Freitag, 9. Juni 2017, 13:37:26 CEST schrieb Linus Walleij: Heiko, can you please look at this patch. On Thu, Jun 8, 2017 at 9:30 AM, Jianhong Chen <che...@rock-chips.com> wrote: From: chenjh <che...@rock-chips.com> Full name please. git config --global user.name "John Doe" might do the and make this permanent for all your commits :-) RK805 has two configurable GPIOs that can be used for several purposes. These are output only. This driver is generic for other Rockchip PMICs to be added. Signed-off-by: chenjh <che...@rock-chips.com> Dito. Your commit message says they are output-only, yet you implement .direction_input(). So what is is going to be? So far, I've only seen the rk808 and rk818. Both do not have any configurable pins. The rk805 which is a sort of variant of the above, does have the two pins defined below, but in the manual I could also only find them as output-only and having no other function than being output-pins. So I don't really know if all the input- or "gpio-mode"- handling is only an oversight (copy'n'paste) or if there are yet other rk808 variants around that can actually be configured as inputs or even non-gpio modes? I hope Jianhong will be able to answer that. Heiko This driver is not only for rk805, but also intend for rk816 and furtrue PMICs. The rk816 has one multi function pin(TS/GPIO), when setting as gpio, it can be configured as output or input. Here is simple description from manual: "Thermistor input. Connect a thermistor from this pin to ground. The thermistor is usually inside the battery pack. (multi-function for GPIO) ". As Linus suggested, this sounds like you want a pinctrl driver that also handles the gpios. Ideally you might also directly provide support for this rk816 in the same patch series, so reviewers can see the full extend of what is supported. Heiko Hi, Heiko: I have moved gpio-rk805.c to drivers/pinctrl/pinctrl-rk805.c, this driver is also designed for rk816 or furture PMICs to extend. RK816 is not in our team's plan at this porting, it will be added at next time, so I don't directly provide rk816 in this driver. I will add more descriptions in commit message to express my design purpose. Are you agreed ? If so, I will send [PATCH v7] today. -- Best Regards 陈健洪 (Joseph Chen) E-mail:che...@rock-chips.com 福州瑞芯微电子股份有限公司 Fuzhou Rockchip Electronics Co.Ltd 福建省福州市铜盘路软件大道89号软件园A区21号楼 (350003) No. 21 Building, A District, No.89,software Boulevard Fuzhou,Fujian,PRC TEL:0591-83991906/07-8573
Re: [PATCH v6 08/12] gpio: Add GPIO driver for the RK805 PMIC
在 2017/6/29 18:29, Heiko Stübner 写道: Hi, Am Mittwoch, 14. Juni 2017, 20:11:06 CEST schrieb Jianhong Chen: 在 2017/6/9 20:17, Heiko Stuebner 写道: Am Freitag, 9. Juni 2017, 13:37:26 CEST schrieb Linus Walleij: Heiko, can you please look at this patch. On Thu, Jun 8, 2017 at 9:30 AM, Jianhong Chen wrote: From: chenjh Full name please. git config --global user.name "John Doe" might do the and make this permanent for all your commits :-) RK805 has two configurable GPIOs that can be used for several purposes. These are output only. This driver is generic for other Rockchip PMICs to be added. Signed-off-by: chenjh Dito. Your commit message says they are output-only, yet you implement .direction_input(). So what is is going to be? So far, I've only seen the rk808 and rk818. Both do not have any configurable pins. The rk805 which is a sort of variant of the above, does have the two pins defined below, but in the manual I could also only find them as output-only and having no other function than being output-pins. So I don't really know if all the input- or "gpio-mode"- handling is only an oversight (copy'n'paste) or if there are yet other rk808 variants around that can actually be configured as inputs or even non-gpio modes? I hope Jianhong will be able to answer that. Heiko This driver is not only for rk805, but also intend for rk816 and furtrue PMICs. The rk816 has one multi function pin(TS/GPIO), when setting as gpio, it can be configured as output or input. Here is simple description from manual: "Thermistor input. Connect a thermistor from this pin to ground. The thermistor is usually inside the battery pack. (multi-function for GPIO) ". As Linus suggested, this sounds like you want a pinctrl driver that also handles the gpios. Ideally you might also directly provide support for this rk816 in the same patch series, so reviewers can see the full extend of what is supported. Heiko Hi, Heiko: I have moved gpio-rk805.c to drivers/pinctrl/pinctrl-rk805.c, this driver is also designed for rk816 or furture PMICs to extend. RK816 is not in our team's plan at this porting, it will be added at next time, so I don't directly provide rk816 in this driver. I will add more descriptions in commit message to express my design purpose. Are you agreed ? If so, I will send [PATCH v7] today. -- Best Regards 陈健洪 (Joseph Chen) E-mail:che...@rock-chips.com 福州瑞芯微电子股份有限公司 Fuzhou Rockchip Electronics Co.Ltd 福建省福州市铜盘路软件大道89号软件园A区21号楼 (350003) No. 21 Building, A District, No.89,software Boulevard Fuzhou,Fujian,PRC TEL:0591-83991906/07-8573
Re: [PATCH v6 08/12] gpio: Add GPIO driver for the RK805 PMIC
在 2017/6/9 20:17, Heiko Stuebner 写道: Hi, Am Freitag, 9. Juni 2017, 13:37:26 CEST schrieb Linus Walleij: Heiko, can you please look at this patch. On Thu, Jun 8, 2017 at 9:30 AM, Jianhong Chen <che...@rock-chips.com> wrote: From: chenjh <che...@rock-chips.com> Full name please. git config --global user.name "John Doe" might do the and make this permanent for all your commits :-) RK805 has two configurable GPIOs that can be used for several purposes. These are output only. This driver is generic for other Rockchip PMICs to be added. Signed-off-by: chenjh <che...@rock-chips.com> Dito. Your commit message says they are output-only, yet you implement .direction_input(). So what is is going to be? So far, I've only seen the rk808 and rk818. Both do not have any configurable pins. The rk805 which is a sort of variant of the above, does have the two pins defined below, but in the manual I could also only find them as output-only and having no other function than being output-pins. So I don't really know if all the input- or "gpio-mode"- handling is only an oversight (copy'n'paste) or if there are yet other rk808 variants around that can actually be configured as inputs or even non-gpio modes? I hope Jianhong will be able to answer that. Heiko This driver is not only for rk805, but also intend for rk816 and furtrue PMICs. The rk816 has one multi function pin(TS/GPIO), when setting as gpio, it can be configured as output or input. Here is simple description from manual: "Thermistor input. Connect a thermistor from this pin to ground. The thermistor is usually inside the battery pack. (multi-function for GPIO) ". At beginning, I want to name it "gpio-rk8xx.c", but I found rk808 and rk818 don't have gpio function. So I abandon this name and use "gpio-rk805.c", but still implement it as a generic driver for furture PMICs to be added. +#include +#include Only use: #include +/* + * @mode: supported modes for this gpio, i.e. OUTPUT_MODE, OUTPUT_MODE... Are you saying this should be an enum or a set of flags? Yes, as explain above, these "OUTPUT_MODE, INPUTOUT" flags are prepared for RK816 or furture PMICs. Maybe these should be enum are better. +static int rk805_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + int ret, val; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + ret = regmap_read(gpio->rk808->regmap, gpio->pins[offset].reg, ); + if (ret) { + dev_err(gpio->dev, "gpio%d not support output mode\n", offset); + return ret; + } + + return (val & gpio->pins[offset].val_msk) ? 1 : 0; Do this: return !!(val & gpio->pins[offset].val_msk) +static int rk805_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + int ret; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + /* switch to gpio mode */ + if (gpio->pins[offset].func_mask) { + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].func_mask, +gpio->pins[offset].func_mask); + if (ret) { + dev_err(gpio->dev, "set gpio%d func failed\n", offset); + return ret; + } + } + + return 0; +} This is pin control. Why don't you implement a proper pin control driver for this chip? If you don't, this will just come back and haunt you. Why not merge the driver into drivers/pinctrl/* and name it pinctrl-rk805.c to begin with? Becuase I refered to other PMICs, I see most of their gpio driver is merged into drivers/gpio/*, Only a few are added in drivers/pinctrl/*. So, it is better to merge the driver into drivers/pinctrl/* ? +static const struct gpio_chip rk805_chip = { + .label = "rk805-gpio", + .owner = THIS_MODULE, + .direction_input= rk805_gpio_direction_input, + .direction_output = rk805_gpio_direction_output, Please implement .get_direction() + .get= rk805_gpio_get, + .set= rk805_gpio_set, + .request= rk805_gpio_request, + .base = -1, + .ngpio = 2, + .can_sleep = true, Consider assigning the .names[] array some pin names. Yours, Linus Walleij ___ Linux-rockchip mailing list linux-rockc...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-rockchip -- 陈健洪 E-mail:che...@rock-chips.com 福州瑞芯微电子股份有限公司 Fuzhou Rockchip Electronics Co.Ltd 福建省福州市铜盘路软件大道89号软件园A区21号楼 (350003) No. 21 Building, A District, No.89,software Boulevard Fuzhou,Fujian,PRC TEL:0591-83991906/07-8573
Re: [PATCH v6 08/12] gpio: Add GPIO driver for the RK805 PMIC
在 2017/6/9 20:17, Heiko Stuebner 写道: Hi, Am Freitag, 9. Juni 2017, 13:37:26 CEST schrieb Linus Walleij: Heiko, can you please look at this patch. On Thu, Jun 8, 2017 at 9:30 AM, Jianhong Chen wrote: From: chenjh Full name please. git config --global user.name "John Doe" might do the and make this permanent for all your commits :-) RK805 has two configurable GPIOs that can be used for several purposes. These are output only. This driver is generic for other Rockchip PMICs to be added. Signed-off-by: chenjh Dito. Your commit message says they are output-only, yet you implement .direction_input(). So what is is going to be? So far, I've only seen the rk808 and rk818. Both do not have any configurable pins. The rk805 which is a sort of variant of the above, does have the two pins defined below, but in the manual I could also only find them as output-only and having no other function than being output-pins. So I don't really know if all the input- or "gpio-mode"- handling is only an oversight (copy'n'paste) or if there are yet other rk808 variants around that can actually be configured as inputs or even non-gpio modes? I hope Jianhong will be able to answer that. Heiko This driver is not only for rk805, but also intend for rk816 and furtrue PMICs. The rk816 has one multi function pin(TS/GPIO), when setting as gpio, it can be configured as output or input. Here is simple description from manual: "Thermistor input. Connect a thermistor from this pin to ground. The thermistor is usually inside the battery pack. (multi-function for GPIO) ". At beginning, I want to name it "gpio-rk8xx.c", but I found rk808 and rk818 don't have gpio function. So I abandon this name and use "gpio-rk805.c", but still implement it as a generic driver for furture PMICs to be added. +#include +#include Only use: #include +/* + * @mode: supported modes for this gpio, i.e. OUTPUT_MODE, OUTPUT_MODE... Are you saying this should be an enum or a set of flags? Yes, as explain above, these "OUTPUT_MODE, INPUTOUT" flags are prepared for RK816 or furture PMICs. Maybe these should be enum are better. +static int rk805_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + int ret, val; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + ret = regmap_read(gpio->rk808->regmap, gpio->pins[offset].reg, ); + if (ret) { + dev_err(gpio->dev, "gpio%d not support output mode\n", offset); + return ret; + } + + return (val & gpio->pins[offset].val_msk) ? 1 : 0; Do this: return !!(val & gpio->pins[offset].val_msk) +static int rk805_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + int ret; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + /* switch to gpio mode */ + if (gpio->pins[offset].func_mask) { + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].func_mask, +gpio->pins[offset].func_mask); + if (ret) { + dev_err(gpio->dev, "set gpio%d func failed\n", offset); + return ret; + } + } + + return 0; +} This is pin control. Why don't you implement a proper pin control driver for this chip? If you don't, this will just come back and haunt you. Why not merge the driver into drivers/pinctrl/* and name it pinctrl-rk805.c to begin with? Becuase I refered to other PMICs, I see most of their gpio driver is merged into drivers/gpio/*, Only a few are added in drivers/pinctrl/*. So, it is better to merge the driver into drivers/pinctrl/* ? +static const struct gpio_chip rk805_chip = { + .label = "rk805-gpio", + .owner = THIS_MODULE, + .direction_input= rk805_gpio_direction_input, + .direction_output = rk805_gpio_direction_output, Please implement .get_direction() + .get= rk805_gpio_get, + .set= rk805_gpio_set, + .request= rk805_gpio_request, + .base = -1, + .ngpio = 2, + .can_sleep = true, Consider assigning the .names[] array some pin names. Yours, Linus Walleij ___ Linux-rockchip mailing list linux-rockc...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-rockchip -- 陈健洪 E-mail:che...@rock-chips.com 福州瑞芯微电子股份有限公司 Fuzhou Rockchip Electronics Co.Ltd 福建省福州市铜盘路软件大道89号软件园A区21号楼 (350003) No. 21 Building, A District, No.89,software Boulevard Fuzhou,Fujian,PRC TEL:0591-83991906/07-8573
[PATCH v6 09/12] Input: Add power key driver for Rockchip RK805 PMIC
From: chenjhThis driver provides a input driver for the power key on the Rockchip RK805 PMIC. Signed-off-by: chenjh --- drivers/input/misc/Kconfig| 6 +++ drivers/input/misc/Makefile | 1 + drivers/input/misc/rk805-pwrkey.c | 111 ++ 3 files changed, 118 insertions(+) create mode 100644 drivers/input/misc/rk805-pwrkey.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 5b6c522..72dc4f5 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -571,6 +571,12 @@ config INPUT_PWM_BEEPER To compile this driver as a module, choose M here: the module will be called pwm-beeper. +config INPUT_RK805_PWRKEY + tristate "Rockchip RK805 PMIC power key support" + depends on MFD_RK808 + help + Select this option to enable power key driver for RK805. + config INPUT_GPIO_ROTARY_ENCODER tristate "Rotary encoders connected to GPIO pins" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index b10523f..c27052a 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)+= rotary_encoder.o +obj-$(CONFIG_INPUT_RK805_PWRKEY) += rk805-pwrkey.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o diff --git a/drivers/input/misc/rk805-pwrkey.c b/drivers/input/misc/rk805-pwrkey.c new file mode 100644 index 000..188eed5 --- /dev/null +++ b/drivers/input/misc/rk805-pwrkey.c @@ -0,0 +1,111 @@ +/* + * Rockchip RK805 PMIC Power Key driver + * + * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chen Jianhong + * + * 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 + +static irqreturn_t pwrkey_fall_irq(int irq, void *_pwr) +{ + struct input_dev *pwr = _pwr; + + input_report_key(pwr, KEY_POWER, 1); + input_sync(pwr); + + return IRQ_HANDLED; +} + +static irqreturn_t pwrkey_rise_irq(int irq, void *_pwr) +{ + struct input_dev *pwr = _pwr; + + input_report_key(pwr, KEY_POWER, 0); + input_sync(pwr); + + return IRQ_HANDLED; +} + +static int rk805_pwrkey_probe(struct platform_device *pdev) +{ + struct input_dev *pwr; + int fall_irq, rise_irq; + int err; + + pwr = devm_input_allocate_device(>dev); + if (!pwr) { + dev_err(>dev, "Can't allocate power button\n"); + return -ENOMEM; + } + + pwr->name = "rk805 pwrkey"; + pwr->phys = "rk805_pwrkey/input0"; + pwr->dev.parent = >dev; + input_set_capability(pwr, EV_KEY, KEY_POWER); + + fall_irq = platform_get_irq(pdev, 0); + if (fall_irq < 0) { + dev_err(>dev, "Can't get fall irq: %d\n", fall_irq); + return fall_irq; + } + + rise_irq = platform_get_irq(pdev, 1); + if (rise_irq < 0) { + dev_err(>dev, "Can't get rise irq: %d\n", rise_irq); + return rise_irq; + } + + err = devm_request_threaded_irq(>dev, fall_irq, NULL, + pwrkey_fall_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "rk805_pwrkey_fall", pwr); + if (err < 0) { + dev_err(>dev, "Can't register fall irq: %d\n", err); + return err; + } + + err = devm_request_threaded_irq(>dev, rise_irq, NULL, + pwrkey_rise_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "rk805_pwrkey_rise", pwr); + if (err < 0) { + dev_err(>dev, "Can't register rise irq: %d\n", err); + return err; + } + + err = input_register_device(pwr); + if (err) { + dev_err(>dev, "Can't register power button: %d\n", err); + return err; + } + + platform_set_drvdata(pdev, pwr); + device_init_wakeup(>dev, true); + + return 0; +} + +static struct platform_driver rk805_pwrkey_driver = { + .probe = rk805_pwrkey_probe, + .driver = { + .name = "rk805-pwrkey", + }, +};
[PATCH v6 09/12] Input: Add power key driver for Rockchip RK805 PMIC
From: chenjh This driver provides a input driver for the power key on the Rockchip RK805 PMIC. Signed-off-by: chenjh --- drivers/input/misc/Kconfig| 6 +++ drivers/input/misc/Makefile | 1 + drivers/input/misc/rk805-pwrkey.c | 111 ++ 3 files changed, 118 insertions(+) create mode 100644 drivers/input/misc/rk805-pwrkey.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 5b6c522..72dc4f5 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -571,6 +571,12 @@ config INPUT_PWM_BEEPER To compile this driver as a module, choose M here: the module will be called pwm-beeper. +config INPUT_RK805_PWRKEY + tristate "Rockchip RK805 PMIC power key support" + depends on MFD_RK808 + help + Select this option to enable power key driver for RK805. + config INPUT_GPIO_ROTARY_ENCODER tristate "Rotary encoders connected to GPIO pins" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index b10523f..c27052a 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)+= rotary_encoder.o +obj-$(CONFIG_INPUT_RK805_PWRKEY) += rk805-pwrkey.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o diff --git a/drivers/input/misc/rk805-pwrkey.c b/drivers/input/misc/rk805-pwrkey.c new file mode 100644 index 000..188eed5 --- /dev/null +++ b/drivers/input/misc/rk805-pwrkey.c @@ -0,0 +1,111 @@ +/* + * Rockchip RK805 PMIC Power Key driver + * + * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chen Jianhong + * + * 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 + +static irqreturn_t pwrkey_fall_irq(int irq, void *_pwr) +{ + struct input_dev *pwr = _pwr; + + input_report_key(pwr, KEY_POWER, 1); + input_sync(pwr); + + return IRQ_HANDLED; +} + +static irqreturn_t pwrkey_rise_irq(int irq, void *_pwr) +{ + struct input_dev *pwr = _pwr; + + input_report_key(pwr, KEY_POWER, 0); + input_sync(pwr); + + return IRQ_HANDLED; +} + +static int rk805_pwrkey_probe(struct platform_device *pdev) +{ + struct input_dev *pwr; + int fall_irq, rise_irq; + int err; + + pwr = devm_input_allocate_device(>dev); + if (!pwr) { + dev_err(>dev, "Can't allocate power button\n"); + return -ENOMEM; + } + + pwr->name = "rk805 pwrkey"; + pwr->phys = "rk805_pwrkey/input0"; + pwr->dev.parent = >dev; + input_set_capability(pwr, EV_KEY, KEY_POWER); + + fall_irq = platform_get_irq(pdev, 0); + if (fall_irq < 0) { + dev_err(>dev, "Can't get fall irq: %d\n", fall_irq); + return fall_irq; + } + + rise_irq = platform_get_irq(pdev, 1); + if (rise_irq < 0) { + dev_err(>dev, "Can't get rise irq: %d\n", rise_irq); + return rise_irq; + } + + err = devm_request_threaded_irq(>dev, fall_irq, NULL, + pwrkey_fall_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "rk805_pwrkey_fall", pwr); + if (err < 0) { + dev_err(>dev, "Can't register fall irq: %d\n", err); + return err; + } + + err = devm_request_threaded_irq(>dev, rise_irq, NULL, + pwrkey_rise_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "rk805_pwrkey_rise", pwr); + if (err < 0) { + dev_err(>dev, "Can't register rise irq: %d\n", err); + return err; + } + + err = input_register_device(pwr); + if (err) { + dev_err(>dev, "Can't register power button: %d\n", err); + return err; + } + + platform_set_drvdata(pdev, pwr); + device_init_wakeup(>dev, true); + + return 0; +} + +static struct platform_driver rk805_pwrkey_driver = { + .probe = rk805_pwrkey_probe, + .driver = { + .name = "rk805-pwrkey", + }, +}; +module_platform_driver(rk805_pwrkey_driver); + +MODULE_AUTHOR("Chen Jianghong ");
[PATCH v6 12/12] gpio: dt-bindings: add bindings for Rockchip RK805 PMIC
From: chenjhAdd device tree bindings documentation for Rockchip's RK805 PMIC Signed-off-by: chenjh --- .../devicetree/bindings/gpio/gpio-rk805.txt| 37 ++ 1 file changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-rk805.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio-rk805.txt b/Documentation/devicetree/bindings/gpio/gpio-rk805.txt new file mode 100644 index 000..98b75fa --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-rk805.txt @@ -0,0 +1,37 @@ +RK805 GPIO controller + +This driver follows the usual GPIO bindings found in +Documentation/devicetree/bindings/gpio/gpio.txt + +Required properties: +- #gpio-cells: Should be two. The first cell is the pin number and the + second is the GPIO flags. +- gpio-controller: Marks the device node as a GPIO controller. + +These properties must be added in the RK805 PMIC node, documented in +Documentation/devicetree/bindings/mfd/rk808.txt + +Example: + +rk805: pmic@18 { + compatible = "rockchip,rk808"; + clock-output-names = "xin32k", "rk808-clkout2"; + interrupt-parent = <>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + reg = <0x1a>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + ... + gpio-controller; + #gpio-cells = <2>; +}; + + +Example of a peripheral using the PMIC GPIOs: + +wireless-bluetooth { + compatible = "bluetooth-platdata"; + ... + gpios = < 0 GPIO_ACTIVE_HIGH>, < 1 GPIO_ACTIVE_HIGH>; +}; -- 1.9.1
[PATCH v6 12/12] gpio: dt-bindings: add bindings for Rockchip RK805 PMIC
From: chenjh Add device tree bindings documentation for Rockchip's RK805 PMIC Signed-off-by: chenjh --- .../devicetree/bindings/gpio/gpio-rk805.txt| 37 ++ 1 file changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-rk805.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio-rk805.txt b/Documentation/devicetree/bindings/gpio/gpio-rk805.txt new file mode 100644 index 000..98b75fa --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-rk805.txt @@ -0,0 +1,37 @@ +RK805 GPIO controller + +This driver follows the usual GPIO bindings found in +Documentation/devicetree/bindings/gpio/gpio.txt + +Required properties: +- #gpio-cells: Should be two. The first cell is the pin number and the + second is the GPIO flags. +- gpio-controller: Marks the device node as a GPIO controller. + +These properties must be added in the RK805 PMIC node, documented in +Documentation/devicetree/bindings/mfd/rk808.txt + +Example: + +rk805: pmic@18 { + compatible = "rockchip,rk808"; + clock-output-names = "xin32k", "rk808-clkout2"; + interrupt-parent = <>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + reg = <0x1a>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + ... + gpio-controller; + #gpio-cells = <2>; +}; + + +Example of a peripheral using the PMIC GPIOs: + +wireless-bluetooth { + compatible = "bluetooth-platdata"; + ... + gpios = < 0 GPIO_ACTIVE_HIGH>, < 1 GPIO_ACTIVE_HIGH>; +}; -- 1.9.1
[PATCH v6 11/12] mfd: rk808: Add RK805 power key support
From: chenjhSigned-off-by: chenjh --- drivers/mfd/rk808.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index f7cdcf5..d1e8d35 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -94,6 +94,19 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) } }; +static struct resource rk805_key_resources[] = { + { + .start = RK805_IRQ_PWRON_FALL, + .end= RK805_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK805_IRQ_PWRON_RISE, + .end= RK805_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, + } +}; + static const struct mfd_cell rk805s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -103,6 +116,10 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) .num_resources = ARRAY_SIZE(rtc_resources), .resources = _resources[0], }, + { .name = "rk805-pwrkey", + .num_resources = ARRAY_SIZE(rk805_key_resources), + .resources = _key_resources[0], + }, }; static const struct mfd_cell rk808s[] = { -- 1.9.1
[PATCH v6 11/12] mfd: rk808: Add RK805 power key support
From: chenjh Signed-off-by: chenjh --- drivers/mfd/rk808.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index f7cdcf5..d1e8d35 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -94,6 +94,19 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) } }; +static struct resource rk805_key_resources[] = { + { + .start = RK805_IRQ_PWRON_FALL, + .end= RK805_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK805_IRQ_PWRON_RISE, + .end= RK805_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, + } +}; + static const struct mfd_cell rk805s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -103,6 +116,10 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) .num_resources = ARRAY_SIZE(rtc_resources), .resources = _resources[0], }, + { .name = "rk805-pwrkey", + .num_resources = ARRAY_SIZE(rk805_key_resources), + .resources = _key_resources[0], + }, }; static const struct mfd_cell rk808s[] = { -- 1.9.1
[PATCH v6 10/12] mfd: rk808: Add RK805 gpio support
From: chenjhSigned-off-by: chenjh --- drivers/mfd/rk808.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 7276555..f7cdcf5 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -97,6 +97,7 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) static const struct mfd_cell rk805s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, + { .name = "rk805-gpio", }, { .name = "rk808-rtc", .num_resources = ARRAY_SIZE(rtc_resources), -- 1.9.1
[PATCH v6 10/12] mfd: rk808: Add RK805 gpio support
From: chenjh Signed-off-by: chenjh --- drivers/mfd/rk808.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 7276555..f7cdcf5 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -97,6 +97,7 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) static const struct mfd_cell rk805s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, + { .name = "rk805-gpio", }, { .name = "rk808-rtc", .num_resources = ARRAY_SIZE(rtc_resources), -- 1.9.1
[PATCH v6 08/12] gpio: Add GPIO driver for the RK805 PMIC
From: chenjhRK805 has two configurable GPIOs that can be used for several purposes. These are output only. This driver is generic for other Rockchip PMICs to be added. Signed-off-by: chenjh --- drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rk805.c | 234 ++ 3 files changed, 241 insertions(+) create mode 100644 drivers/gpio/gpio-rk805.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 0504307..c8cca89 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -974,6 +974,12 @@ config GPIO_RC5T583 This driver provides the support for driving/reading the gpio pins of RC5T583 device through standard gpio library. +config GPIO_RK805 + bool "Rockchip RK805 GPIO" + depends on MFD_RK808 + help + Select this option to enable GPIO driver for the RK805 PMIC. + config GPIO_STMPE bool "STMPE GPIOs" depends on MFD_STMPE diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index becb96c..55ba941 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_GPIO_PXA)+= gpio-pxa.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_RCAR)+= gpio-rcar.o +obj-$(CONFIG_GPIO_RK805) += gpio-rk805.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o diff --git a/drivers/gpio/gpio-rk805.c b/drivers/gpio/gpio-rk805.c new file mode 100644 index 000..bc17c92 --- /dev/null +++ b/drivers/gpio/gpio-rk805.c @@ -0,0 +1,234 @@ +/* + * GPIO driver for Rockchip RK805 PMIC + * + * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chen Jianhong + * + * 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. + * + * Based on the TPS65218 driver + */ + +#include +#include +#include +#include +#include +#include + +/* rk805 */ +#define RK805_OUT_REG 0x52 +#define RK805_OUT1_VAL_MSK BIT(0) +#define RK805_OUT2_VAL_MSK BIT(1) + +#define OUTPUT_MODEBIT(0) +#define INPUT_MODE BIT(1) + +/* + * @mode: supported modes for this gpio, i.e. OUTPUT_MODE, OUTPUT_MODE... + * @reg: gpio status setting register + * @func_mask: functions select mask value + * @dir_mask: input or output mask value + * @val_mask: gpio set value + */ +struct gpio_pin { + u8 mode; + u8 reg; + u8 func_mask; + u8 dir_msk; + u8 val_msk; +}; + +struct rk805_gpio { + struct device *dev; + struct gpio_chip chip; + struct gpio_pin *pins; + struct rk808 *rk808; +}; + +static int rk805_gpio_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + int ret; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + if (!(gpio->pins[offset].mode & INPUT_MODE)) { + dev_err(gpio->dev, "gpio%d not support input mode\n", offset); + return -EINVAL; + } + + if (gpio->pins[offset].dir_msk) { + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].dir_msk, 0); + if (ret) { + dev_err(gpio->dev, "set gpio%d input failed\n", offset); + return ret; + } + } + + return 0; +} + +static int rk805_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + int ret; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + if (!(gpio->pins[offset].mode & OUTPUT_MODE)) { + dev_err(gpio->dev, "gpio%d not support output mode\n", offset); + return -EINVAL; + } + + if (gpio->pins[offset].dir_msk) { + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].dir_msk, +gpio->pins[offset].dir_msk); + if (ret) { + dev_err(gpio->dev, "set gpio%d out failed\n", offset); + return ret; + } + } + + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].val_msk, +value ? gpio->pins[offset].val_msk : 0); + if (ret) { +
[PATCH v6 08/12] gpio: Add GPIO driver for the RK805 PMIC
From: chenjh RK805 has two configurable GPIOs that can be used for several purposes. These are output only. This driver is generic for other Rockchip PMICs to be added. Signed-off-by: chenjh --- drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rk805.c | 234 ++ 3 files changed, 241 insertions(+) create mode 100644 drivers/gpio/gpio-rk805.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 0504307..c8cca89 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -974,6 +974,12 @@ config GPIO_RC5T583 This driver provides the support for driving/reading the gpio pins of RC5T583 device through standard gpio library. +config GPIO_RK805 + bool "Rockchip RK805 GPIO" + depends on MFD_RK808 + help + Select this option to enable GPIO driver for the RK805 PMIC. + config GPIO_STMPE bool "STMPE GPIOs" depends on MFD_STMPE diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index becb96c..55ba941 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_GPIO_PXA)+= gpio-pxa.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_RCAR)+= gpio-rcar.o +obj-$(CONFIG_GPIO_RK805) += gpio-rk805.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o diff --git a/drivers/gpio/gpio-rk805.c b/drivers/gpio/gpio-rk805.c new file mode 100644 index 000..bc17c92 --- /dev/null +++ b/drivers/gpio/gpio-rk805.c @@ -0,0 +1,234 @@ +/* + * GPIO driver for Rockchip RK805 PMIC + * + * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chen Jianhong + * + * 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. + * + * Based on the TPS65218 driver + */ + +#include +#include +#include +#include +#include +#include + +/* rk805 */ +#define RK805_OUT_REG 0x52 +#define RK805_OUT1_VAL_MSK BIT(0) +#define RK805_OUT2_VAL_MSK BIT(1) + +#define OUTPUT_MODEBIT(0) +#define INPUT_MODE BIT(1) + +/* + * @mode: supported modes for this gpio, i.e. OUTPUT_MODE, OUTPUT_MODE... + * @reg: gpio status setting register + * @func_mask: functions select mask value + * @dir_mask: input or output mask value + * @val_mask: gpio set value + */ +struct gpio_pin { + u8 mode; + u8 reg; + u8 func_mask; + u8 dir_msk; + u8 val_msk; +}; + +struct rk805_gpio { + struct device *dev; + struct gpio_chip chip; + struct gpio_pin *pins; + struct rk808 *rk808; +}; + +static int rk805_gpio_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + int ret; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + if (!(gpio->pins[offset].mode & INPUT_MODE)) { + dev_err(gpio->dev, "gpio%d not support input mode\n", offset); + return -EINVAL; + } + + if (gpio->pins[offset].dir_msk) { + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].dir_msk, 0); + if (ret) { + dev_err(gpio->dev, "set gpio%d input failed\n", offset); + return ret; + } + } + + return 0; +} + +static int rk805_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + int ret; + struct rk805_gpio *gpio = gpiochip_get_data(chip); + + if (!(gpio->pins[offset].mode & OUTPUT_MODE)) { + dev_err(gpio->dev, "gpio%d not support output mode\n", offset); + return -EINVAL; + } + + if (gpio->pins[offset].dir_msk) { + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].dir_msk, +gpio->pins[offset].dir_msk); + if (ret) { + dev_err(gpio->dev, "set gpio%d out failed\n", offset); + return ret; + } + } + + ret = regmap_update_bits(gpio->rk808->regmap, +gpio->pins[offset].reg, +gpio->pins[offset].val_msk, +value ? gpio->pins[offset].val_msk : 0); + if (ret) { + dev_err(gpio->dev, "set gpio%d value failed\n", offset); +
[PATCH v6 07/12] mfd: dt-bindings: Add RK805 device tree bindings document
From: Elaine ZhangAdd device tree bindings documentation for Rockchip's RK805 PMIC. Signed-off-by: Elaine Zhang --- Documentation/devicetree/bindings/mfd/rk808.txt | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt index 9636ae8..91b6522 100644 --- a/Documentation/devicetree/bindings/mfd/rk808.txt +++ b/Documentation/devicetree/bindings/mfd/rk808.txt @@ -1,11 +1,14 @@ RK8XX Power Management Integrated Circuit The rk8xx family current members: +rk805 rk808 rk818 Required properties: -- compatible: "rockchip,rk808", "rockchip,rk818" +- compatible: "rockchip,rk805" +- compatible: "rockchip,rk808" +- compatible: "rockchip,rk818" - reg: I2C slave address - interrupt-parent: The parent interrupt controller. - interrupts: the interrupt outputs of the controller. @@ -18,6 +21,14 @@ Optional properties: - rockchip,system-power-controller: Telling whether or not this pmic is controlling the system power. +Optional RK805 properties: +- vcc1-supply: The input supply for DCDC_REG1 +- vcc2-supply: The input supply for DCDC_REG2 +- vcc3-supply: The input supply for DCDC_REG3 +- vcc4-supply: The input supply for DCDC_REG4 +- vcc5-supply: The input supply for LDO_REG1 and LDO_REG2 +- vcc6-supply: The input supply for LDO_REG3 + Optional RK808 properties: - vcc1-supply: The input supply for DCDC_REG1 - vcc2-supply: The input supply for DCDC_REG2 @@ -56,6 +67,15 @@ by a child node of the 'regulators' node. /* standard regulator bindings here */ }; +Following regulators of the RK805 PMIC regulators are supported. Note that +the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO +number as described in RK805 datasheet. + + - DCDC_REGn + - valid values for n are 1 to 4. + - LDO_REGn + - valid values for n are 1 to 3 + Following regulators of the RK808 PMIC block are supported. Note that the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO number as described in RK808 datasheet. -- 1.9.1
[PATCH v6 07/12] mfd: dt-bindings: Add RK805 device tree bindings document
From: Elaine Zhang Add device tree bindings documentation for Rockchip's RK805 PMIC. Signed-off-by: Elaine Zhang --- Documentation/devicetree/bindings/mfd/rk808.txt | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt index 9636ae8..91b6522 100644 --- a/Documentation/devicetree/bindings/mfd/rk808.txt +++ b/Documentation/devicetree/bindings/mfd/rk808.txt @@ -1,11 +1,14 @@ RK8XX Power Management Integrated Circuit The rk8xx family current members: +rk805 rk808 rk818 Required properties: -- compatible: "rockchip,rk808", "rockchip,rk818" +- compatible: "rockchip,rk805" +- compatible: "rockchip,rk808" +- compatible: "rockchip,rk818" - reg: I2C slave address - interrupt-parent: The parent interrupt controller. - interrupts: the interrupt outputs of the controller. @@ -18,6 +21,14 @@ Optional properties: - rockchip,system-power-controller: Telling whether or not this pmic is controlling the system power. +Optional RK805 properties: +- vcc1-supply: The input supply for DCDC_REG1 +- vcc2-supply: The input supply for DCDC_REG2 +- vcc3-supply: The input supply for DCDC_REG3 +- vcc4-supply: The input supply for DCDC_REG4 +- vcc5-supply: The input supply for LDO_REG1 and LDO_REG2 +- vcc6-supply: The input supply for LDO_REG3 + Optional RK808 properties: - vcc1-supply: The input supply for DCDC_REG1 - vcc2-supply: The input supply for DCDC_REG2 @@ -56,6 +67,15 @@ by a child node of the 'regulators' node. /* standard regulator bindings here */ }; +Following regulators of the RK805 PMIC regulators are supported. Note that +the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO +number as described in RK805 datasheet. + + - DCDC_REGn + - valid values for n are 1 to 4. + - LDO_REGn + - valid values for n are 1 to 3 + Following regulators of the RK808 PMIC block are supported. Note that the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO number as described in RK808 datasheet. -- 1.9.1
[PATCH v6 06/12] rtc: Kconfig: Name RK805 in Kconfig for RTC_DRV_RK808
From: Elaine ZhangThe RK808 and RK805 PMICs are using a similar register map. We can reuse the rtc driver for the RK805 PMIC. So let's add the RK805 in the Kconfig description. Signed-off-by: Elaine Zhang --- drivers/rtc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5dc673d..47d6a8d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -352,11 +352,11 @@ config RTC_DRV_MAX77686 will be called rtc-max77686. config RTC_DRV_RK808 - tristate "Rockchip RK808/RK818 RTC" + tristate "Rockchip RK805/RK808/RK818 RTC" depends on MFD_RK808 help If you say yes here you will get support for the - RTC of RK808 and RK818 PMIC. + RTC of RK805, RK808 and RK818 PMIC. This driver can also be built as a module. If so, the module will be called rk808-rtc. -- 1.9.1
[PATCH v6 06/12] rtc: Kconfig: Name RK805 in Kconfig for RTC_DRV_RK808
From: Elaine Zhang The RK808 and RK805 PMICs are using a similar register map. We can reuse the rtc driver for the RK805 PMIC. So let's add the RK805 in the Kconfig description. Signed-off-by: Elaine Zhang --- drivers/rtc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5dc673d..47d6a8d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -352,11 +352,11 @@ config RTC_DRV_MAX77686 will be called rtc-max77686. config RTC_DRV_RK808 - tristate "Rockchip RK808/RK818 RTC" + tristate "Rockchip RK805/RK808/RK818 RTC" depends on MFD_RK808 help If you say yes here you will get support for the - RTC of RK808 and RK818 PMIC. + RTC of RK805, RK808 and RK818 PMIC. This driver can also be built as a module. If so, the module will be called rk808-rtc. -- 1.9.1
[PATCH v6 05/12] clk: Kconfig: Name RK805 in Kconfig for COMMON_CLK_RK808
From: Elaine ZhangThe RK808 and RK805 PMICs are using a similar register map. We can reuse the clk driver for the RK805 PMIC. So let's add the RK805 in the Kconfig description. Signed-off-by: Elaine Zhang --- drivers/clk/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 9356ab4..7ca8f02 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -39,10 +39,10 @@ config COMMON_CLK_MAX77686 clock. config COMMON_CLK_RK808 - tristate "Clock driver for RK808/RK818" + tristate "Clock driver for RK805/RK808/RK818" depends on MFD_RK808 ---help--- - This driver supports RK808 and RK818 crystal oscillator clock. These + This driver supports RK805, RK808 and RK818 crystal oscillator clock. These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. Clkout1 is always on, Clkout2 can off by control register. -- 1.9.1
[PATCH v6 05/12] clk: Kconfig: Name RK805 in Kconfig for COMMON_CLK_RK808
From: Elaine Zhang The RK808 and RK805 PMICs are using a similar register map. We can reuse the clk driver for the RK805 PMIC. So let's add the RK805 in the Kconfig description. Signed-off-by: Elaine Zhang --- drivers/clk/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 9356ab4..7ca8f02 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -39,10 +39,10 @@ config COMMON_CLK_MAX77686 clock. config COMMON_CLK_RK808 - tristate "Clock driver for RK808/RK818" + tristate "Clock driver for RK805/RK808/RK818" depends on MFD_RK808 ---help--- - This driver supports RK808 and RK818 crystal oscillator clock. These + This driver supports RK805, RK808 and RK818 crystal oscillator clock. These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. Clkout1 is always on, Clkout2 can off by control register. -- 1.9.1
[PATCH v6 03/12] regulator: rk808: Add regulator driver for RK805
From: Elaine ZhangAdd support for the rk805 regulator. The regulator module consists of 4 DCDCs, 3 LDOs. The output voltages are configurable and are meant to supply power to the main processor and other components. Signed-off-by: Elaine Zhang --- drivers/regulator/Kconfig | 4 +- drivers/regulator/rk808-regulator.c | 130 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index be06eb2..285e280 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -650,11 +650,11 @@ config REGULATOR_RC5T583 outputs which can be controlled by i2c communication. config REGULATOR_RK808 - tristate "Rockchip RK808/RK818 Power regulators" + tristate "Rockchip RK805/RK808/RK818 Power regulators" depends on MFD_RK808 help Select this option to enable the power regulator of ROCKCHIP - PMIC RK808 and RK818. + PMIC RK805,RK808 and RK818. This driver supports the control of different power rails of device through regulator interface. The device supports multiple DCDC/LDO outputs which can be controlled by i2c communication. diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index fb44d52..128c81e 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -65,6 +65,27 @@ /* max steps for increase voltage of Buck1/2, equal 100mv*/ #define MAX_STEPS_ONE_TIME 8 +#define RK805_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _etime) \ + [_id] = { \ + .name = (_match), \ + .supply_name= (_supply),\ + .of_match = of_match_ptr(_match), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE,\ + .id = (_id),\ + .n_voltages = (((_max) - (_min)) / (_step) + 1),\ + .owner = THIS_MODULE, \ + .min_uV = (_min) * 1000,\ + .uV_step= (_step) * 1000, \ + .vsel_reg = (_vreg), \ + .vsel_mask = (_vmask), \ + .enable_reg = (_ereg), \ + .enable_mask= (_emask), \ + .enable_time= (_etime), \ + .ops= _reg_ops, \ + } + #define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _etime) \ [_id] = { \ @@ -298,6 +319,28 @@ static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) sel); } +static int rk805_set_suspend_enable(struct regulator_dev *rdev) +{ + unsigned int reg; + + reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->enable_mask, + rdev->desc->enable_mask); +} + +static int rk805_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int reg; + + reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->enable_mask, + 0); +} + static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; @@ -320,6 +363,27 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) rdev->desc->enable_mask); } +static struct regulator_ops rk805_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage= regulator_map_voltage_linear, + .get_voltage_sel= regulator_get_voltage_sel_regmap, + .set_voltage_sel= regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable= regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_voltage= rk808_set_suspend_voltage, + .set_suspend_enable =
[PATCH v6 03/12] regulator: rk808: Add regulator driver for RK805
From: Elaine Zhang Add support for the rk805 regulator. The regulator module consists of 4 DCDCs, 3 LDOs. The output voltages are configurable and are meant to supply power to the main processor and other components. Signed-off-by: Elaine Zhang --- drivers/regulator/Kconfig | 4 +- drivers/regulator/rk808-regulator.c | 130 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index be06eb2..285e280 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -650,11 +650,11 @@ config REGULATOR_RC5T583 outputs which can be controlled by i2c communication. config REGULATOR_RK808 - tristate "Rockchip RK808/RK818 Power regulators" + tristate "Rockchip RK805/RK808/RK818 Power regulators" depends on MFD_RK808 help Select this option to enable the power regulator of ROCKCHIP - PMIC RK808 and RK818. + PMIC RK805,RK808 and RK818. This driver supports the control of different power rails of device through regulator interface. The device supports multiple DCDC/LDO outputs which can be controlled by i2c communication. diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index fb44d52..128c81e 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -65,6 +65,27 @@ /* max steps for increase voltage of Buck1/2, equal 100mv*/ #define MAX_STEPS_ONE_TIME 8 +#define RK805_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _etime) \ + [_id] = { \ + .name = (_match), \ + .supply_name= (_supply),\ + .of_match = of_match_ptr(_match), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE,\ + .id = (_id),\ + .n_voltages = (((_max) - (_min)) / (_step) + 1),\ + .owner = THIS_MODULE, \ + .min_uV = (_min) * 1000,\ + .uV_step= (_step) * 1000, \ + .vsel_reg = (_vreg), \ + .vsel_mask = (_vmask), \ + .enable_reg = (_ereg), \ + .enable_mask= (_emask), \ + .enable_time= (_etime), \ + .ops= _reg_ops, \ + } + #define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _etime) \ [_id] = { \ @@ -298,6 +319,28 @@ static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) sel); } +static int rk805_set_suspend_enable(struct regulator_dev *rdev) +{ + unsigned int reg; + + reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->enable_mask, + rdev->desc->enable_mask); +} + +static int rk805_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int reg; + + reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->enable_mask, + 0); +} + static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; @@ -320,6 +363,27 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) rdev->desc->enable_mask); } +static struct regulator_ops rk805_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage= regulator_map_voltage_linear, + .get_voltage_sel= regulator_get_voltage_sel_regmap, + .set_voltage_sel= regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable= regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_voltage= rk808_set_suspend_voltage, + .set_suspend_enable = rk805_set_suspend_enable, + .set_suspend_disable=
[PATCH v6 02/12] mfd: rk808: add rk805 regs addr and ID
From: Elaine ZhangSigned-off-by: Elaine Zhang --- include/linux/mfd/rk808.h | 120 ++ 1 file changed, 120 insertions(+) diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 54feb14..d315659 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -206,6 +206,97 @@ enum rk818_reg { #define RK818_USB_ILMIN_2000MA 0x7 #define RK818_USB_CHG_SD_VSEL_MASK 0x70 +/* RK805 */ +enum rk805_reg { + RK805_ID_DCDC1, + RK805_ID_DCDC2, + RK805_ID_DCDC3, + RK805_ID_DCDC4, + RK805_ID_LDO1, + RK805_ID_LDO2, + RK805_ID_LDO3, +}; + +/* CONFIG REGISTER */ +#define RK805_VB_MON_REG 0x21 +#define RK805_THERMAL_REG 0x22 + +/* POWER CHANNELS ENABLE REGISTER */ +#define RK805_DCDC_EN_REG 0x23 +#define RK805_SLP_DCDC_EN_REG 0x25 +#define RK805_SLP_LDO_EN_REG 0x26 +#define RK805_LDO_EN_REG 0x27 + +/* BUCK AND LDO CONFIG REGISTER */ +#define RK805_BUCK_LDO_SLP_LP_EN_REG 0x2A +#define RK805_BUCK1_CONFIG_REG 0x2E +#define RK805_BUCK1_ON_VSEL_REG0x2F +#define RK805_BUCK1_SLP_VSEL_REG 0x30 +#define RK805_BUCK2_CONFIG_REG 0x32 +#define RK805_BUCK2_ON_VSEL_REG0x33 +#define RK805_BUCK2_SLP_VSEL_REG 0x34 +#define RK805_BUCK3_CONFIG_REG 0x36 +#define RK805_BUCK4_CONFIG_REG 0x37 +#define RK805_BUCK4_ON_VSEL_REG0x38 +#define RK805_BUCK4_SLP_VSEL_REG 0x39 +#define RK805_LDO1_ON_VSEL_REG 0x3B +#define RK805_LDO1_SLP_VSEL_REG0x3C +#define RK805_LDO2_ON_VSEL_REG 0x3D +#define RK805_LDO2_SLP_VSEL_REG0x3E +#define RK805_LDO3_ON_VSEL_REG 0x3F +#define RK805_LDO3_SLP_VSEL_REG0x40 + +/* INTERRUPT REGISTER */ +#define RK805_PWRON_LP_INT_TIME_REG0x47 +#define RK805_PWRON_DB_REG 0x48 +#define RK805_DEV_CTRL_REG 0x4B +#define RK805_INT_STS_REG 0x4C +#define RK805_INT_STS_MSK_REG 0x4D +#define RK805_GPIO_IO_POL_REG 0x50 +#define RK805_OUT_REG 0x52 +#define RK805_ON_SOURCE_REG0xAE +#define RK805_OFF_SOURCE_REG 0xAF + +#define RK805_NUM_REGULATORS 7 + +#define RK805_PWRON_FALL_RISE_INT_EN 0x0 +#define RK805_PWRON_FALL_RISE_INT_MSK 0x81 + +/* RK805 IRQ Definitions */ +#define RK805_IRQ_PWRON_RISE 0 +#define RK805_IRQ_VB_LOW 1 +#define RK805_IRQ_PWRON2 +#define RK805_IRQ_PWRON_LP 3 +#define RK805_IRQ_HOTDIE 4 +#define RK805_IRQ_RTC_ALARM5 +#define RK805_IRQ_RTC_PERIOD 6 +#define RK805_IRQ_PWRON_FALL 7 + +#define RK805_IRQ_PWRON_RISE_MSK BIT(0) +#define RK805_IRQ_VB_LOW_MSK BIT(1) +#define RK805_IRQ_PWRON_MSKBIT(2) +#define RK805_IRQ_PWRON_LP_MSK BIT(3) +#define RK805_IRQ_HOTDIE_MSK BIT(4) +#define RK805_IRQ_RTC_ALARM_MSKBIT(5) +#define RK805_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK805_IRQ_PWRON_FALL_MSK BIT(7) + +#define RK805_PWR_RISE_INT_STATUS BIT(0) +#define RK805_VB_LOW_INT_STATUSBIT(1) +#define RK805_PWRON_INT_STATUS BIT(2) +#define RK805_PWRON_LP_INT_STATUS BIT(3) +#define RK805_HOTDIE_INT_STATUSBIT(4) +#define RK805_ALARM_INT_STATUS BIT(5) +#define RK805_PERIOD_INT_STATUSBIT(6) +#define RK805_PWR_FALL_INT_STATUS BIT(7) + +#define RK805_BUCK1_2_ILMAX_MASK (3 << 6) +#define RK805_BUCK3_4_ILMAX_MASK(3 << 3) +#define RK805_RTC_PERIOD_INT_MASK (1 << 6) +#define RK805_RTC_ALARM_INT_MASK (1 << 5) +#define RK805_INT_ALARM_EN (1 << 3) +#define RK805_INT_TIMER_EN (1 << 2) + /* RK808 IRQ Definitions */ #define RK808_IRQ_VOUT_LO 0 #define RK808_IRQ_VB_LO1 @@ -298,7 +389,14 @@ enum rk818_reg { #define VOUT_LO_INTBIT(0) #define CLK32KOUT2_EN BIT(0) +#define TEMP115C 0x0c +#define TEMP_HOTDIE_MSK0x0c +#define SLP_SD_MSK (0x3 << 2) +#define SHUTDOWN_FUN (0x2 << 2) +#define SLEEP_FUN (0x1 << 2) #define RK8XX_ID_MSK 0xfff0 +#define FPWM_MODE BIT(7) + enum { BUCK_ILMIN_50MA, BUCK_ILMIN_100MA, @@ -322,6 +420,28 @@ enum { }; enum { + RK805_BUCK1_2_ILMAX_2500MA, + RK805_BUCK1_2_ILMAX_3000MA, + RK805_BUCK1_2_ILMAX_3500MA, + RK805_BUCK1_2_ILMAX_4000MA, +}; + +enum { + RK805_BUCK3_ILMAX_1500MA, + RK805_BUCK3_ILMAX_2000MA, + RK805_BUCK3_ILMAX_2500MA, + RK805_BUCK3_ILMAX_3000MA, +}; + +enum { + RK805_BUCK4_ILMAX_2000MA, + RK805_BUCK4_ILMAX_2500MA, + RK805_BUCK4_ILMAX_3000MA, +
[PATCH v6 04/12] mfd: rk808: Add RK805 support
From: Elaine ZhangThe RK805 chip is a Power Management IC (PMIC) for multimedia and handheld devices. It contains the following components: - Regulators - RTC - Clocking Both RK808 and RK805 chips are using a similar register map, so we can reuse the RTC and Clocking functionality. Signed-off-by: Elaine Zhang --- drivers/mfd/Kconfig | 4 +- drivers/mfd/rk808.c | 108 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 55ecdfb..b410a34 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -892,13 +892,13 @@ config MFD_RC5T583 different functionality of the device. config MFD_RK808 - tristate "Rockchip RK808/RK818 Power Management Chip" + tristate "Rockchip RK805/RK808/RK818 Power Management Chip" depends on I2C && OF select MFD_CORE select REGMAP_I2C select REGMAP_IRQ help - If you say yes here you get support for the RK808 and RK818 + If you say yes here you get support for the RK805, RK808 and RK818 Power Management chips. This driver provides common support for accessing the device through I2C interface. The device supports multiple sub-devices diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 3334a2a..7276555 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -70,6 +70,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) .volatile_reg = rk808_is_volatile_reg, }; +static const struct regmap_config rk805_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK805_OFF_SOURCE_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + static const struct regmap_config rk808_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -86,6 +94,16 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) } }; +static const struct mfd_cell rk805s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = _resources[0], + }, +}; + static const struct mfd_cell rk808s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -106,6 +124,20 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) }, }; +static const struct rk808_reg_data rk805_pre_init_reg[] = { + {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, +RK805_BUCK1_2_ILMAX_4000MA}, + {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, +RK805_BUCK1_2_ILMAX_4000MA}, + {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, +RK805_BUCK3_ILMAX_3000MA}, + {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, +RK805_BUCK4_ILMAX_3500MA}, + {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, + {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN}, + {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, +}; + static const struct rk808_reg_data rk808_pre_init_reg[] = { { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, @@ -135,6 +167,41 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) VB_LO_SEL_3500MV }, }; +static const struct regmap_irq rk805_irqs[] = { + [RK805_IRQ_PWRON_RISE] = { + .mask = RK805_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_VB_LOW] = { + .mask = RK805_IRQ_VB_LOW_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON] = { + .mask = RK805_IRQ_PWRON_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_LP] = { + .mask = RK805_IRQ_PWRON_LP_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_HOTDIE] = { + .mask = RK805_IRQ_HOTDIE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_ALARM] = { + .mask = RK805_IRQ_RTC_ALARM_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_PERIOD] = { + .mask = RK805_IRQ_RTC_PERIOD_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_FALL] = { + .mask = RK805_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, +}; + static const struct regmap_irq rk808_irqs[] = { /* INT_STS */ [RK808_IRQ_VOUT_LO] = { @@ -247,6 +314,17 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) }, };
[PATCH v6 02/12] mfd: rk808: add rk805 regs addr and ID
From: Elaine Zhang Signed-off-by: Elaine Zhang --- include/linux/mfd/rk808.h | 120 ++ 1 file changed, 120 insertions(+) diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 54feb14..d315659 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -206,6 +206,97 @@ enum rk818_reg { #define RK818_USB_ILMIN_2000MA 0x7 #define RK818_USB_CHG_SD_VSEL_MASK 0x70 +/* RK805 */ +enum rk805_reg { + RK805_ID_DCDC1, + RK805_ID_DCDC2, + RK805_ID_DCDC3, + RK805_ID_DCDC4, + RK805_ID_LDO1, + RK805_ID_LDO2, + RK805_ID_LDO3, +}; + +/* CONFIG REGISTER */ +#define RK805_VB_MON_REG 0x21 +#define RK805_THERMAL_REG 0x22 + +/* POWER CHANNELS ENABLE REGISTER */ +#define RK805_DCDC_EN_REG 0x23 +#define RK805_SLP_DCDC_EN_REG 0x25 +#define RK805_SLP_LDO_EN_REG 0x26 +#define RK805_LDO_EN_REG 0x27 + +/* BUCK AND LDO CONFIG REGISTER */ +#define RK805_BUCK_LDO_SLP_LP_EN_REG 0x2A +#define RK805_BUCK1_CONFIG_REG 0x2E +#define RK805_BUCK1_ON_VSEL_REG0x2F +#define RK805_BUCK1_SLP_VSEL_REG 0x30 +#define RK805_BUCK2_CONFIG_REG 0x32 +#define RK805_BUCK2_ON_VSEL_REG0x33 +#define RK805_BUCK2_SLP_VSEL_REG 0x34 +#define RK805_BUCK3_CONFIG_REG 0x36 +#define RK805_BUCK4_CONFIG_REG 0x37 +#define RK805_BUCK4_ON_VSEL_REG0x38 +#define RK805_BUCK4_SLP_VSEL_REG 0x39 +#define RK805_LDO1_ON_VSEL_REG 0x3B +#define RK805_LDO1_SLP_VSEL_REG0x3C +#define RK805_LDO2_ON_VSEL_REG 0x3D +#define RK805_LDO2_SLP_VSEL_REG0x3E +#define RK805_LDO3_ON_VSEL_REG 0x3F +#define RK805_LDO3_SLP_VSEL_REG0x40 + +/* INTERRUPT REGISTER */ +#define RK805_PWRON_LP_INT_TIME_REG0x47 +#define RK805_PWRON_DB_REG 0x48 +#define RK805_DEV_CTRL_REG 0x4B +#define RK805_INT_STS_REG 0x4C +#define RK805_INT_STS_MSK_REG 0x4D +#define RK805_GPIO_IO_POL_REG 0x50 +#define RK805_OUT_REG 0x52 +#define RK805_ON_SOURCE_REG0xAE +#define RK805_OFF_SOURCE_REG 0xAF + +#define RK805_NUM_REGULATORS 7 + +#define RK805_PWRON_FALL_RISE_INT_EN 0x0 +#define RK805_PWRON_FALL_RISE_INT_MSK 0x81 + +/* RK805 IRQ Definitions */ +#define RK805_IRQ_PWRON_RISE 0 +#define RK805_IRQ_VB_LOW 1 +#define RK805_IRQ_PWRON2 +#define RK805_IRQ_PWRON_LP 3 +#define RK805_IRQ_HOTDIE 4 +#define RK805_IRQ_RTC_ALARM5 +#define RK805_IRQ_RTC_PERIOD 6 +#define RK805_IRQ_PWRON_FALL 7 + +#define RK805_IRQ_PWRON_RISE_MSK BIT(0) +#define RK805_IRQ_VB_LOW_MSK BIT(1) +#define RK805_IRQ_PWRON_MSKBIT(2) +#define RK805_IRQ_PWRON_LP_MSK BIT(3) +#define RK805_IRQ_HOTDIE_MSK BIT(4) +#define RK805_IRQ_RTC_ALARM_MSKBIT(5) +#define RK805_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK805_IRQ_PWRON_FALL_MSK BIT(7) + +#define RK805_PWR_RISE_INT_STATUS BIT(0) +#define RK805_VB_LOW_INT_STATUSBIT(1) +#define RK805_PWRON_INT_STATUS BIT(2) +#define RK805_PWRON_LP_INT_STATUS BIT(3) +#define RK805_HOTDIE_INT_STATUSBIT(4) +#define RK805_ALARM_INT_STATUS BIT(5) +#define RK805_PERIOD_INT_STATUSBIT(6) +#define RK805_PWR_FALL_INT_STATUS BIT(7) + +#define RK805_BUCK1_2_ILMAX_MASK (3 << 6) +#define RK805_BUCK3_4_ILMAX_MASK(3 << 3) +#define RK805_RTC_PERIOD_INT_MASK (1 << 6) +#define RK805_RTC_ALARM_INT_MASK (1 << 5) +#define RK805_INT_ALARM_EN (1 << 3) +#define RK805_INT_TIMER_EN (1 << 2) + /* RK808 IRQ Definitions */ #define RK808_IRQ_VOUT_LO 0 #define RK808_IRQ_VB_LO1 @@ -298,7 +389,14 @@ enum rk818_reg { #define VOUT_LO_INTBIT(0) #define CLK32KOUT2_EN BIT(0) +#define TEMP115C 0x0c +#define TEMP_HOTDIE_MSK0x0c +#define SLP_SD_MSK (0x3 << 2) +#define SHUTDOWN_FUN (0x2 << 2) +#define SLEEP_FUN (0x1 << 2) #define RK8XX_ID_MSK 0xfff0 +#define FPWM_MODE BIT(7) + enum { BUCK_ILMIN_50MA, BUCK_ILMIN_100MA, @@ -322,6 +420,28 @@ enum { }; enum { + RK805_BUCK1_2_ILMAX_2500MA, + RK805_BUCK1_2_ILMAX_3000MA, + RK805_BUCK1_2_ILMAX_3500MA, + RK805_BUCK1_2_ILMAX_4000MA, +}; + +enum { + RK805_BUCK3_ILMAX_1500MA, + RK805_BUCK3_ILMAX_2000MA, + RK805_BUCK3_ILMAX_2500MA, + RK805_BUCK3_ILMAX_3000MA, +}; + +enum { + RK805_BUCK4_ILMAX_2000MA, + RK805_BUCK4_ILMAX_2500MA, + RK805_BUCK4_ILMAX_3000MA, + RK805_BUCK4_ILMAX_3500MA, +}; + +enum { +
[PATCH v6 04/12] mfd: rk808: Add RK805 support
From: Elaine Zhang The RK805 chip is a Power Management IC (PMIC) for multimedia and handheld devices. It contains the following components: - Regulators - RTC - Clocking Both RK808 and RK805 chips are using a similar register map, so we can reuse the RTC and Clocking functionality. Signed-off-by: Elaine Zhang --- drivers/mfd/Kconfig | 4 +- drivers/mfd/rk808.c | 108 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 55ecdfb..b410a34 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -892,13 +892,13 @@ config MFD_RC5T583 different functionality of the device. config MFD_RK808 - tristate "Rockchip RK808/RK818 Power Management Chip" + tristate "Rockchip RK805/RK808/RK818 Power Management Chip" depends on I2C && OF select MFD_CORE select REGMAP_I2C select REGMAP_IRQ help - If you say yes here you get support for the RK808 and RK818 + If you say yes here you get support for the RK805, RK808 and RK818 Power Management chips. This driver provides common support for accessing the device through I2C interface. The device supports multiple sub-devices diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 3334a2a..7276555 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -70,6 +70,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) .volatile_reg = rk808_is_volatile_reg, }; +static const struct regmap_config rk805_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK805_OFF_SOURCE_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + static const struct regmap_config rk808_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -86,6 +94,16 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) } }; +static const struct mfd_cell rk805s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = _resources[0], + }, +}; + static const struct mfd_cell rk808s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -106,6 +124,20 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) }, }; +static const struct rk808_reg_data rk805_pre_init_reg[] = { + {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, +RK805_BUCK1_2_ILMAX_4000MA}, + {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, +RK805_BUCK1_2_ILMAX_4000MA}, + {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, +RK805_BUCK3_ILMAX_3000MA}, + {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, +RK805_BUCK4_ILMAX_3500MA}, + {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, + {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN}, + {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, +}; + static const struct rk808_reg_data rk808_pre_init_reg[] = { { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, @@ -135,6 +167,41 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) VB_LO_SEL_3500MV }, }; +static const struct regmap_irq rk805_irqs[] = { + [RK805_IRQ_PWRON_RISE] = { + .mask = RK805_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_VB_LOW] = { + .mask = RK805_IRQ_VB_LOW_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON] = { + .mask = RK805_IRQ_PWRON_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_LP] = { + .mask = RK805_IRQ_PWRON_LP_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_HOTDIE] = { + .mask = RK805_IRQ_HOTDIE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_ALARM] = { + .mask = RK805_IRQ_RTC_ALARM_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_PERIOD] = { + .mask = RK805_IRQ_RTC_PERIOD_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_FALL] = { + .mask = RK805_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, +}; + static const struct regmap_irq rk808_irqs[] = { /* INT_STS */ [RK808_IRQ_VOUT_LO] = { @@ -247,6 +314,17 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) }, }; +static struct regmap_irq_chip rk805_irq_chip = {
[PATCH v6 01/12] mfd: rk808: fix up the chip id get failed
From: Elaine Zhangthe rk8xx chip id is: ((MSB << 8) | LSB) & 0xfff0 Signed-off-by: Elaine Zhang --- drivers/mfd/rk808.c | 21 +++-- include/linux/mfd/rk808.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index fd087cb..3334a2a 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -325,7 +325,7 @@ static int rk808_probe(struct i2c_client *client, void (*pm_pwroff_fn)(void); int nr_pre_init_regs; int nr_cells; - int pm_off = 0; + int pm_off = 0, msb, lsb; int ret; int i; @@ -333,14 +333,23 @@ static int rk808_probe(struct i2c_client *client, if (!rk808) return -ENOMEM; - rk808->variant = i2c_smbus_read_word_data(client, RK808_ID_MSB); - if (rk808->variant < 0) { - dev_err(>dev, "Failed to read the chip id at 0x%02x\n", + /* read Chip variant */ + msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB); + if (msb < 0) { + dev_err(>dev, "failed to read the chip id at 0x%x\n", RK808_ID_MSB); - return rk808->variant; + return msb; } - dev_dbg(>dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant); + lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB); + if (lsb < 0) { + dev_err(>dev, "failed to read the chip id at 0x%x\n", + RK808_ID_LSB); + return lsb; + } + + rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; + dev_info(>dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant); switch (rk808->variant) { case RK808_ID: diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 83701ef..54feb14 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -298,6 +298,7 @@ enum rk818_reg { #define VOUT_LO_INTBIT(0) #define CLK32KOUT2_EN BIT(0) +#define RK8XX_ID_MSK 0xfff0 enum { BUCK_ILMIN_50MA, BUCK_ILMIN_100MA, -- 1.9.1
[PATCH v6 01/12] mfd: rk808: fix up the chip id get failed
From: Elaine Zhang the rk8xx chip id is: ((MSB << 8) | LSB) & 0xfff0 Signed-off-by: Elaine Zhang --- drivers/mfd/rk808.c | 21 +++-- include/linux/mfd/rk808.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index fd087cb..3334a2a 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -325,7 +325,7 @@ static int rk808_probe(struct i2c_client *client, void (*pm_pwroff_fn)(void); int nr_pre_init_regs; int nr_cells; - int pm_off = 0; + int pm_off = 0, msb, lsb; int ret; int i; @@ -333,14 +333,23 @@ static int rk808_probe(struct i2c_client *client, if (!rk808) return -ENOMEM; - rk808->variant = i2c_smbus_read_word_data(client, RK808_ID_MSB); - if (rk808->variant < 0) { - dev_err(>dev, "Failed to read the chip id at 0x%02x\n", + /* read Chip variant */ + msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB); + if (msb < 0) { + dev_err(>dev, "failed to read the chip id at 0x%x\n", RK808_ID_MSB); - return rk808->variant; + return msb; } - dev_dbg(>dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant); + lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB); + if (lsb < 0) { + dev_err(>dev, "failed to read the chip id at 0x%x\n", + RK808_ID_LSB); + return lsb; + } + + rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; + dev_info(>dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant); switch (rk808->variant) { case RK808_ID: diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 83701ef..54feb14 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -298,6 +298,7 @@ enum rk818_reg { #define VOUT_LO_INTBIT(0) #define CLK32KOUT2_EN BIT(0) +#define RK8XX_ID_MSK 0xfff0 enum { BUCK_ILMIN_50MA, BUCK_ILMIN_100MA, -- 1.9.1
[PATCH v6 00/12] rk808: Add RK805 support
From: chenjhchange in v6: patch1~7 no changed in V6. add patch 8~12 for gpio and powerkey func for rk805. change in v5: PATCH V5 1/7: NO change in V5 PATCH V5 2/7: fix the rk805 reg addr in numerical order PATCH V5 3/7: NO change in V5 PATCH V5 4/7: fix up the rk805_device_shutdown func PATCH V5 5/7: NO change in V5 PATCH V5 6/7: NO change in V5 PATCH V5 7/7: fix up the description of the rk805 change in v4: PATCH V4 1/7: NO change in V4 PATCH V4 2/7: rename the commit message PATCH V4 3/7: NO change in V4 PATCH V4 4/7: Split this patch up into subsystems patch 5/7 6/7 PATCH V4 5/7: new added PATCH V4 6/7: new added PATCH V4 7/7: NO change in V4 change in V3: PATCH V3 1/5: NO change in V3 PATCH V3 2/5: add rk805 RTC INT MASK define PATCH V3 3/5: RK805 set suspend enable and disable is different from rk808 use rk805_regs_ops and rk805_switch_ops PATCH V3 4/5: fix up the shutdown func use pm_shutdown_prepare_fn to prepare shutdown and pm_pwroff_fn pull down gpio to shut down rk805 it will update in the future(after rk808 support gpio func) PATCH V3 5/5: NO change in V3 change in V2: PATCH V2 1/5: NO change in V2 PATCH V2 2/5: add rk805 BUCK ILMAX define PATCH V2 3/5: NO change in V2 PATCH V2 4/5: setting RK805 BUCK ILMAX in pre init PATCH V2 5/5: Add RK805 device tree bindings document Elaine Zhang (7): mfd: rk808: fix up the chip id get failed mfd: rk808: add rk805 regs addr and ID regulator: rk808: Add regulator driver for RK805 mfd: rk808: Add RK805 support clk: Kconfig: Name RK805 in Kconfig for COMMON_CLK_RK808 rtc: Kconfig: Name RK805 in Kconfig for RTC_DRV_RK808 mfd: dt-bindings: Add RK805 device tree bindings document chenjh (5): gpio: Add GPIO driver for the RK805 PMIC Input: Add power key driver for Rockchip RK805 PMIC mfd: rk808: Add RK805 gpio support mfd: rk808: Add RK805 power key support gpio: dt-bindings: add bindings for Rockchip RK805 PMIC .../devicetree/bindings/gpio/gpio-rk805.txt| 37 Documentation/devicetree/bindings/mfd/rk808.txt| 22 +- drivers/clk/Kconfig| 4 +- drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rk805.c | 234 + drivers/input/misc/Kconfig | 6 + drivers/input/misc/Makefile| 1 + drivers/input/misc/rk805-pwrkey.c | 111 ++ drivers/mfd/Kconfig| 4 +- drivers/mfd/rk808.c| 147 - drivers/regulator/Kconfig | 4 +- drivers/regulator/rk808-regulator.c| 130 drivers/rtc/Kconfig| 4 +- include/linux/mfd/rk808.h | 121 +++ 15 files changed, 817 insertions(+), 15 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-rk805.txt create mode 100644 drivers/gpio/gpio-rk805.c create mode 100644 drivers/input/misc/rk805-pwrkey.c -- 1.9.1
[PATCH v6 00/12] rk808: Add RK805 support
From: chenjh change in v6: patch1~7 no changed in V6. add patch 8~12 for gpio and powerkey func for rk805. change in v5: PATCH V5 1/7: NO change in V5 PATCH V5 2/7: fix the rk805 reg addr in numerical order PATCH V5 3/7: NO change in V5 PATCH V5 4/7: fix up the rk805_device_shutdown func PATCH V5 5/7: NO change in V5 PATCH V5 6/7: NO change in V5 PATCH V5 7/7: fix up the description of the rk805 change in v4: PATCH V4 1/7: NO change in V4 PATCH V4 2/7: rename the commit message PATCH V4 3/7: NO change in V4 PATCH V4 4/7: Split this patch up into subsystems patch 5/7 6/7 PATCH V4 5/7: new added PATCH V4 6/7: new added PATCH V4 7/7: NO change in V4 change in V3: PATCH V3 1/5: NO change in V3 PATCH V3 2/5: add rk805 RTC INT MASK define PATCH V3 3/5: RK805 set suspend enable and disable is different from rk808 use rk805_regs_ops and rk805_switch_ops PATCH V3 4/5: fix up the shutdown func use pm_shutdown_prepare_fn to prepare shutdown and pm_pwroff_fn pull down gpio to shut down rk805 it will update in the future(after rk808 support gpio func) PATCH V3 5/5: NO change in V3 change in V2: PATCH V2 1/5: NO change in V2 PATCH V2 2/5: add rk805 BUCK ILMAX define PATCH V2 3/5: NO change in V2 PATCH V2 4/5: setting RK805 BUCK ILMAX in pre init PATCH V2 5/5: Add RK805 device tree bindings document Elaine Zhang (7): mfd: rk808: fix up the chip id get failed mfd: rk808: add rk805 regs addr and ID regulator: rk808: Add regulator driver for RK805 mfd: rk808: Add RK805 support clk: Kconfig: Name RK805 in Kconfig for COMMON_CLK_RK808 rtc: Kconfig: Name RK805 in Kconfig for RTC_DRV_RK808 mfd: dt-bindings: Add RK805 device tree bindings document chenjh (5): gpio: Add GPIO driver for the RK805 PMIC Input: Add power key driver for Rockchip RK805 PMIC mfd: rk808: Add RK805 gpio support mfd: rk808: Add RK805 power key support gpio: dt-bindings: add bindings for Rockchip RK805 PMIC .../devicetree/bindings/gpio/gpio-rk805.txt| 37 Documentation/devicetree/bindings/mfd/rk808.txt| 22 +- drivers/clk/Kconfig| 4 +- drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rk805.c | 234 + drivers/input/misc/Kconfig | 6 + drivers/input/misc/Makefile| 1 + drivers/input/misc/rk805-pwrkey.c | 111 ++ drivers/mfd/Kconfig| 4 +- drivers/mfd/rk808.c| 147 - drivers/regulator/Kconfig | 4 +- drivers/regulator/rk808-regulator.c| 130 drivers/rtc/Kconfig| 4 +- include/linux/mfd/rk808.h | 121 +++ 15 files changed, 817 insertions(+), 15 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-rk805.txt create mode 100644 drivers/gpio/gpio-rk805.c create mode 100644 drivers/input/misc/rk805-pwrkey.c -- 1.9.1
[PATCH] mfd: rk808: RK818 uses DEV_OFF to power off supplies
DEV_OFF and DEV_OFF_RST functions for RK808 are designed error that only DEV_OFF_RST can power off supplies. RK818 has been fixed this issue, so that DEV_OFF is used to power off supplies. Signed-off-by: Jianhong Chen <che...@rock-chips.com> --- drivers/mfd/rk808.c | 23 ++- include/linux/mfd/rk808.h | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 0f8acc5..2c9acdb 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -290,6 +290,24 @@ static void rk808_device_shutdown(void) dev_err(_i2c_client->dev, "power off error!\n"); } +static void rk818_device_shutdown(void) +{ + int ret; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + + if (!rk808) { + dev_warn(_i2c_client->dev, +"have no rk818, so do nothing here\n"); + return; + } + + ret = regmap_update_bits(rk808->regmap, +RK818_DEVCTRL_REG, +DEV_OFF, DEV_OFF); + if (ret) + dev_err(_i2c_client->dev, "power off error!\n"); +} + static const struct of_device_id rk808_of_match[] = { { .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk818" }, @@ -304,6 +322,7 @@ static int rk808_probe(struct i2c_client *client, struct rk808 *rk808; const struct rk808_reg_data *pre_init_reg; const struct mfd_cell *cells; + void (*pm_pwroff_fn)(void); int nr_pre_init_regs; int nr_cells; int pm_off = 0; @@ -331,6 +350,7 @@ static int rk808_probe(struct i2c_client *client, nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); cells = rk808s; nr_cells = ARRAY_SIZE(rk808s); + pm_pwroff_fn = rk808_device_shutdown; break; case RK818_ID: rk808->regmap_cfg = _regmap_config; @@ -339,6 +359,7 @@ static int rk808_probe(struct i2c_client *client, nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); cells = rk818s; nr_cells = ARRAY_SIZE(rk818s); + pm_pwroff_fn = rk818_device_shutdown; break; default: dev_err(>dev, "Unsupported RK8XX ID %lu\n", @@ -393,7 +414,7 @@ static int rk808_probe(struct i2c_client *client, "rockchip,system-power-controller"); if (pm_off && !pm_power_off) { rk808_i2c_client = client; - pm_power_off = rk808_device_shutdown; + pm_power_off = pm_pwroff_fn; } return 0; diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 6d435a3..83701ef 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -290,6 +290,7 @@ enum rk818_reg { #define SWITCH2_EN BIT(6) #define SWITCH1_EN BIT(5) #define DEV_OFF_RSTBIT(3) +#define DEV_OFFBIT(0) #define VB_LO_ACT BIT(4) #define VB_LO_SEL_3500MV (7 << 0) -- 1.9.1
[PATCH] mfd: rk808: RK818 uses DEV_OFF to power off supplies
DEV_OFF and DEV_OFF_RST functions for RK808 are designed error that only DEV_OFF_RST can power off supplies. RK818 has been fixed this issue, so that DEV_OFF is used to power off supplies. Signed-off-by: Jianhong Chen --- drivers/mfd/rk808.c | 23 ++- include/linux/mfd/rk808.h | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 0f8acc5..2c9acdb 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -290,6 +290,24 @@ static void rk808_device_shutdown(void) dev_err(_i2c_client->dev, "power off error!\n"); } +static void rk818_device_shutdown(void) +{ + int ret; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + + if (!rk808) { + dev_warn(_i2c_client->dev, +"have no rk818, so do nothing here\n"); + return; + } + + ret = regmap_update_bits(rk808->regmap, +RK818_DEVCTRL_REG, +DEV_OFF, DEV_OFF); + if (ret) + dev_err(_i2c_client->dev, "power off error!\n"); +} + static const struct of_device_id rk808_of_match[] = { { .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk818" }, @@ -304,6 +322,7 @@ static int rk808_probe(struct i2c_client *client, struct rk808 *rk808; const struct rk808_reg_data *pre_init_reg; const struct mfd_cell *cells; + void (*pm_pwroff_fn)(void); int nr_pre_init_regs; int nr_cells; int pm_off = 0; @@ -331,6 +350,7 @@ static int rk808_probe(struct i2c_client *client, nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); cells = rk808s; nr_cells = ARRAY_SIZE(rk808s); + pm_pwroff_fn = rk808_device_shutdown; break; case RK818_ID: rk808->regmap_cfg = _regmap_config; @@ -339,6 +359,7 @@ static int rk808_probe(struct i2c_client *client, nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); cells = rk818s; nr_cells = ARRAY_SIZE(rk818s); + pm_pwroff_fn = rk818_device_shutdown; break; default: dev_err(>dev, "Unsupported RK8XX ID %lu\n", @@ -393,7 +414,7 @@ static int rk808_probe(struct i2c_client *client, "rockchip,system-power-controller"); if (pm_off && !pm_power_off) { rk808_i2c_client = client; - pm_power_off = rk808_device_shutdown; + pm_power_off = pm_pwroff_fn; } return 0; diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 6d435a3..83701ef 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -290,6 +290,7 @@ enum rk818_reg { #define SWITCH2_EN BIT(6) #define SWITCH1_EN BIT(5) #define DEV_OFF_RSTBIT(3) +#define DEV_OFFBIT(0) #define VB_LO_ACT BIT(4) #define VB_LO_SEL_3500MV (7 << 0) -- 1.9.1