Sat Apr 29 19:57:00 2017 UTC ()
Add AS3722 SD4 regulator frobbing bits.

Reduces aprint_error counter with TEGRA kernel on Jetson TK1 to 1 from 3.


(jakllsch)
diff -r1.9 -r1.10 src/sys/dev/i2c/as3722.c

cvs diff -r1.9 -r1.10 src/sys/dev/i2c/as3722.c (expand / switch to unified diff)

--- src/sys/dev/i2c/as3722.c 2017/04/22 23:50:13 1.9
+++ src/sys/dev/i2c/as3722.c 2017/04/29 19:56:59 1.10
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: as3722.c,v 1.9 2017/04/22 23:50:13 jmcneill Exp $ */ 1/* $NetBSD: as3722.c,v 1.10 2017/04/29 19:56:59 jakllsch Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -19,77 +19,82 @@ @@ -19,77 +19,82 @@
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include "opt_fdt.h" 29#include "opt_fdt.h"
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.9 2017/04/22 23:50:13 jmcneill Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.10 2017/04/29 19:56:59 jakllsch Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/systm.h> 35#include <sys/systm.h>
36#include <sys/kernel.h> 36#include <sys/kernel.h>
37#include <sys/device.h> 37#include <sys/device.h>
38#include <sys/conf.h> 38#include <sys/conf.h>
39#include <sys/bus.h> 39#include <sys/bus.h>
40#include <sys/kmem.h> 40#include <sys/kmem.h>
41#include <sys/wdog.h> 41#include <sys/wdog.h>
42 42
43#include <dev/clock_subr.h> 43#include <dev/clock_subr.h>
44 44
45#include <dev/sysmon/sysmonvar.h> 45#include <dev/sysmon/sysmonvar.h>
46 46
47#include <dev/i2c/i2cvar.h> 47#include <dev/i2c/i2cvar.h>
48#include <dev/i2c/as3722.h> 48#include <dev/i2c/as3722.h>
49 49
50#ifdef FDT 50#ifdef FDT
51#include <dev/fdt/fdtvar.h> 51#include <dev/fdt/fdtvar.h>
52#endif 52#endif
53 53
54#define AS3722_START_YEAR 2000 54#define AS3722_START_YEAR 2000
55 55
56#define AS3722_SD0_VOLTAGE_REG 0x00 56#define AS3722_SD0_VOLTAGE_REG 0x00
57 57
 58#define AS3722_SD4_VOLTAGE_REG 0x04
 59
58#define AS3722_GPIO0_CTRL_REG 0x08 60#define AS3722_GPIO0_CTRL_REG 0x08
59#define AS3722_GPIO0_CTRL_INVERT __BIT(7) 61#define AS3722_GPIO0_CTRL_INVERT __BIT(7)
60#define AS3722_GPIO0_CTRL_IOSF __BITS(6,3) 62#define AS3722_GPIO0_CTRL_IOSF __BITS(6,3)
61#define AS3722_GPIO0_CTRL_IOSF_GPIO 0 63#define AS3722_GPIO0_CTRL_IOSF_GPIO 0
62#define AS3722_GPIO0_CTRL_IOSF_WATCHDOG 9 64#define AS3722_GPIO0_CTRL_IOSF_WATCHDOG 9
63#define AS3722_GPIO0_CTRL_MODE __BITS(2,0) 65#define AS3722_GPIO0_CTRL_MODE __BITS(2,0)
64#define AS3722_GPIO0_CTRL_MODE_PULLDOWN 5 66#define AS3722_GPIO0_CTRL_MODE_PULLDOWN 5
65 67
66#define AS3722_LDO6_VOLTAGE_REG 0x16 68#define AS3722_LDO6_VOLTAGE_REG 0x16
67 69
68#define AS3722_RESET_CTRL_REG 0x36 70#define AS3722_RESET_CTRL_REG 0x36
69#define AS3722_RESET_CTRL_POWER_OFF __BIT(1) 71#define AS3722_RESET_CTRL_POWER_OFF __BIT(1)
70#define AS3722_RESET_CTRL_FORCE_RESET __BIT(0) 72#define AS3722_RESET_CTRL_FORCE_RESET __BIT(0)
71 73
72#define AS3722_WATCHDOG_CTRL_REG 0x38 74#define AS3722_WATCHDOG_CTRL_REG 0x38
73#define AS3722_WATCHDOG_CTRL_MODE __BITS(2,1) 75#define AS3722_WATCHDOG_CTRL_MODE __BITS(2,1)
74#define AS3722_WATCHDOG_CTRL_ON __BIT(0) 76#define AS3722_WATCHDOG_CTRL_ON __BIT(0)
75 77
76#define AS3722_WATCHDOG_TIMER_REG 0x46 78#define AS3722_WATCHDOG_TIMER_REG 0x46
77#define AS3722_WATCHDOG_TIMER_TIMER __BITS(6,0) 79#define AS3722_WATCHDOG_TIMER_TIMER __BITS(6,0)
78 80
79#define AS3722_WATCHDOG_SIGNAL_REG 0x48 81#define AS3722_WATCHDOG_SIGNAL_REG 0x48
80#define AS3722_WATCHDOG_SIGNAL_PWM_DIV __BITS(7,6) 82#define AS3722_WATCHDOG_SIGNAL_PWM_DIV __BITS(7,6)
81#define AS3722_WATCHDOG_SIGNAL_SW_SIG __BIT(0) 83#define AS3722_WATCHDOG_SIGNAL_SW_SIG __BIT(0)
82 84
 85#define AS3722_SDCONTROL_REG 0x4d
 86#define AS3722_SDCONTROL_SD4_ENABLE __BIT(4)
 87
83#define AS3722_LDOCONTROL0_REG 0x4e 88#define AS3722_LDOCONTROL0_REG 0x4e
84 89
85#define AS3722_RTC_CONTROL_REG 0x60 90#define AS3722_RTC_CONTROL_REG 0x60
86#define AS3722_RTC_CONTROL_RTC_ON __BIT(2) 91#define AS3722_RTC_CONTROL_RTC_ON __BIT(2)
87 92
88#define AS3722_RTC_SECOND_REG 0x61 93#define AS3722_RTC_SECOND_REG 0x61
89#define AS3722_RTC_MINUTE_REG 0x62 94#define AS3722_RTC_MINUTE_REG 0x62
90#define AS3722_RTC_HOUR_REG 0x63 95#define AS3722_RTC_HOUR_REG 0x63
91#define AS3722_RTC_DAY_REG 0x64 96#define AS3722_RTC_DAY_REG 0x64
92#define AS3722_RTC_MONTH_REG 0x65 97#define AS3722_RTC_MONTH_REG 0x65
93#define AS3722_RTC_YEAR_REG 0x66 98#define AS3722_RTC_YEAR_REG 0x66
94#define AS3722_RTC_ACCESS_REG 0x6f 99#define AS3722_RTC_ACCESS_REG 0x6f
95 100
@@ -99,43 +104,52 @@ __KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1 @@ -99,43 +104,52 @@ __KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1
99struct as3722_softc { 104struct as3722_softc {
100 device_t sc_dev; 105 device_t sc_dev;
101 i2c_tag_t sc_i2c; 106 i2c_tag_t sc_i2c;
102 i2c_addr_t sc_addr; 107 i2c_addr_t sc_addr;
103 int sc_phandle; 108 int sc_phandle;
104 109
105 struct sysmon_wdog sc_smw; 110 struct sysmon_wdog sc_smw;
106 struct todr_chip_handle sc_todr; 111 struct todr_chip_handle sc_todr;
107}; 112};
108 113
109#ifdef FDT 114#ifdef FDT
110static int as3722reg_set_voltage_sd0(device_t, u_int, u_int); 115static int as3722reg_set_voltage_sd0(device_t, u_int, u_int);
111static int as3722reg_get_voltage_sd0(device_t, u_int *); 116static int as3722reg_get_voltage_sd0(device_t, u_int *);
 117static int as3722reg_set_voltage_sd4(device_t, u_int, u_int);
 118static int as3722reg_get_voltage_sd4(device_t, u_int *);
112static int as3722reg_set_voltage_ldo(device_t, u_int, u_int); 119static int as3722reg_set_voltage_ldo(device_t, u_int, u_int);
113static int as3722reg_get_voltage_ldo(device_t, u_int *); 120static int as3722reg_get_voltage_ldo(device_t, u_int *);
114 121
115static const struct as3722regdef { 122static const struct as3722regdef {
116 const char *name; 123 const char *name;
117 u_int vsel_reg; 124 u_int vsel_reg;
118 u_int vsel_mask; 125 u_int vsel_mask;
119 u_int enable_reg; 126 u_int enable_reg;
120 u_int enable_mask; 127 u_int enable_mask;
121 int (*set)(device_t, u_int, u_int); 128 int (*set)(device_t, u_int, u_int);
122 int (*get)(device_t, u_int *); 129 int (*get)(device_t, u_int *);
123} as3722regdefs[] = { 130} as3722regdefs[] = {
124 { .name = "sd0", 131 { .name = "sd0",
125 .vsel_reg = AS3722_SD0_VOLTAGE_REG, 132 .vsel_reg = AS3722_SD0_VOLTAGE_REG,
126 .vsel_mask = 0x7f, 133 .vsel_mask = 0x7f,
127 .set = as3722reg_set_voltage_sd0, 134 .set = as3722reg_set_voltage_sd0,
128 .get = as3722reg_get_voltage_sd0 }, 135 .get = as3722reg_get_voltage_sd0 },
 136 { .name = "sd4",
 137 .vsel_reg = AS3722_SD4_VOLTAGE_REG,
 138 .vsel_mask = 0x7f,
 139 .enable_reg = AS3722_SDCONTROL_REG,
 140 .enable_mask = AS3722_SDCONTROL_SD4_ENABLE,
 141 .set = as3722reg_set_voltage_sd4,
 142 .get = as3722reg_get_voltage_sd4 },
129 { .name = "ldo6", 143 { .name = "ldo6",
130 .vsel_reg = AS3722_LDO6_VOLTAGE_REG, 144 .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
131 .vsel_mask = 0x7f, 145 .vsel_mask = 0x7f,
132 .enable_reg = AS3722_LDOCONTROL0_REG, 146 .enable_reg = AS3722_LDOCONTROL0_REG,
133 .enable_mask = 0x40, 147 .enable_mask = 0x40,
134 .set = as3722reg_set_voltage_ldo, 148 .set = as3722reg_set_voltage_ldo,
135 .get = as3722reg_get_voltage_ldo }, 149 .get = as3722reg_get_voltage_ldo },
136}; 150};
137 151
138struct as3722reg_softc { 152struct as3722reg_softc {
139 device_t sc_dev; 153 device_t sc_dev;
140 int sc_phandle; 154 int sc_phandle;
141 const struct as3722regdef *sc_regdef; 155 const struct as3722regdef *sc_regdef;
@@ -658,26 +672,103 @@ as3722reg_get_voltage_sd0(device_t dev,  @@ -658,26 +672,103 @@ as3722reg_get_voltage_sd0(device_t dev,
658 v &= regdef->vsel_mask; 672 v &= regdef->vsel_mask;
659 673
660 if (v == 0) 674 if (v == 0)
661 *puvol = 0; /* DC/DC powered down */ 675 *puvol = 0; /* DC/DC powered down */
662 else if (v >= 0x01 && v <= 0x5a) 676 else if (v >= 0x01 && v <= 0x5a)
663 *puvol = 600000 + (v * 10000); 677 *puvol = 600000 + (v * 10000);
664 else 678 else
665 return EINVAL; 679 return EINVAL;
666 680
667 return 0; 681 return 0;
668} 682}
669 683
670static int 684static int
 685as3722reg_set_voltage_sd4(device_t dev, u_int min_uvol, u_int max_uvol)
 686{
 687 struct as3722reg_softc *sc = device_private(dev);
 688 struct as3722_softc *asc = device_private(device_parent(dev));
 689 const struct as3722regdef *regdef = sc->sc_regdef;
 690 const int flags = (cold ? I2C_F_POLL : 0);
 691 uint8_t set_v = 0x00;
 692 u_int uvol;
 693 int error;
 694
 695
 696 for (uint8_t v = 0x01; v <= 0x40; v++) {
 697 uvol = 600000 + (v * 12500);
 698 if (uvol >= min_uvol && uvol <= max_uvol) {
 699 set_v = v;
 700 goto done;
 701 }
 702 }
 703 for (uint8_t v = 0x41; v <= 0x70; v++) {
 704 uvol = 1400000 + ((v - 0x40) * 25000);
 705 if (uvol >= min_uvol && uvol <= max_uvol) {
 706 set_v = v;
 707 goto done;
 708 }
 709 }
 710 for (uint8_t v = 0x71; v <= 0x7f; v++) {
 711 uvol = 2600000 + ((v - 0x70) * 50000);
 712 if (uvol >= min_uvol && uvol <= max_uvol) {
 713 set_v = v;
 714 goto done;
 715 }
 716 }
 717 if (set_v == 0)
 718 return ERANGE;
 719
 720done:
 721 iic_acquire_bus(asc->sc_i2c, flags);
 722 error = as3722_set_clear(asc, regdef->vsel_reg, set_v,
 723 regdef->vsel_mask, flags);
 724 iic_release_bus(asc->sc_i2c, flags);
 725
 726 return error;
 727}
 728
 729static int
 730as3722reg_get_voltage_sd4(device_t dev, u_int *puvol)
 731{
 732 struct as3722reg_softc *sc = device_private(dev);
 733 struct as3722_softc *asc = device_private(device_parent(dev));
 734 const struct as3722regdef *regdef = sc->sc_regdef;
 735 const int flags = (cold ? I2C_F_POLL : 0);
 736 uint8_t v;
 737 int error;
 738
 739 iic_acquire_bus(asc->sc_i2c, flags);
 740 error = as3722_read(asc, regdef->vsel_reg, &v, flags);
 741 iic_release_bus(asc->sc_i2c, flags);
 742 if (error != 0)
 743 return error;
 744
 745 v &= regdef->vsel_mask;
 746
 747 if (v == 0)
 748 *puvol = 0; /* DC/DC powered down */
 749 else if (v >= 0x01 && v <= 0x40)
 750 *puvol = 600000 + (v * 12500);
 751 else if (v >= 0x41 && v <= 0x70)
 752 *puvol = 1400000 + (v - 0x40) * 25000;
 753 else if (v >= 0x71 && v <= 0x7f)
 754 *puvol = 2600000 + (v - 0x70) * 50000;
 755 else
 756 return EINVAL;
 757
 758 return 0;
 759}
 760
 761static int
671as3722reg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol) 762as3722reg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
672{ 763{
673 struct as3722reg_softc *sc = device_private(dev); 764 struct as3722reg_softc *sc = device_private(dev);
674 const struct as3722regdef *regdef = sc->sc_regdef; 765 const struct as3722regdef *regdef = sc->sc_regdef;
675 766
676 return regdef->set(dev, min_uvol, max_uvol); 767 return regdef->set(dev, min_uvol, max_uvol);
677} 768}
678 769
679static int 770static int
680as3722reg_get_voltage(device_t dev, u_int *puvol) 771as3722reg_get_voltage(device_t dev, u_int *puvol)
681{ 772{
682 struct as3722reg_softc *sc = device_private(dev); 773 struct as3722reg_softc *sc = device_private(dev);
683 const struct as3722regdef *regdef = sc->sc_regdef; 774 const struct as3722regdef *regdef = sc->sc_regdef;