1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <arch/io.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pnp.h>
7 #include <option.h>
8 #include <delay.h>
9 #include <types.h>
10
11 #include "pmh7.h"
12 #include "chip.h"
13
pmh7_backlight_enable(int onoff)14 void pmh7_backlight_enable(int onoff)
15 {
16 if (onoff)
17 pmh7_register_set_bit(0x50, 5);
18 else
19 pmh7_register_clear_bit(0x50, 5);
20 }
21
pmh7_dock_event_enable(int onoff)22 void pmh7_dock_event_enable(int onoff)
23 {
24 if (onoff)
25 pmh7_register_set_bit(0x60, 3);
26 else
27 pmh7_register_clear_bit(0x60, 3);
28 }
29
pmh7_touchpad_enable(int onoff)30 void pmh7_touchpad_enable(int onoff)
31 {
32 if (onoff)
33 pmh7_register_clear_bit(0x51, 2);
34 else
35 pmh7_register_set_bit(0x51, 2);
36 }
37
pmh7_trackpoint_enable(int onoff)38 void pmh7_trackpoint_enable(int onoff)
39 {
40 if (onoff)
41 pmh7_register_clear_bit(0x51, 0);
42 else
43 pmh7_register_set_bit(0x51, 0);
44 }
45
pmh7_ultrabay_power_enable(int onoff)46 void pmh7_ultrabay_power_enable(int onoff)
47 {
48 if (onoff)
49 pmh7_register_clear_bit(0x62, 0);
50 else
51 pmh7_register_set_bit(0x62, 0);
52 }
53
pmh7_dgpu_power_enable(int onoff)54 void pmh7_dgpu_power_enable(int onoff)
55 {
56 if (onoff) {
57 pmh7_register_clear_bit(0x50, 7); // DGPU_RST
58 pmh7_register_set_bit(0x50, 3); // DGPU_PWR
59 mdelay(10);
60 pmh7_register_set_bit(0x50, 7); // DGPU_RST
61 mdelay(50);
62 } else {
63 pmh7_register_clear_bit(0x50, 7); // DGPU_RST
64 udelay(100);
65 pmh7_register_clear_bit(0x50, 3); // DGPU_PWR
66 }
67 }
68
pmh7_dgpu_power_state(void)69 bool pmh7_dgpu_power_state(void)
70 {
71 return (pmh7_register_read(0x50) & 0x08) == 8;
72 }
73
pmh7_register_set_bit(int reg,int bit)74 void pmh7_register_set_bit(int reg, int bit)
75 {
76 char val;
77
78 val = pmh7_register_read(reg);
79 pmh7_register_write(reg, val | (1 << bit));
80 }
81
pmh7_register_clear_bit(int reg,int bit)82 void pmh7_register_clear_bit(int reg, int bit)
83 {
84 char val;
85
86 val = pmh7_register_read(reg);
87 pmh7_register_write(reg, val & ~(1 << bit));
88 }
89
pmh7_register_read(int reg)90 char pmh7_register_read(int reg)
91 {
92 outb(reg & 0xff, EC_LENOVO_PMH7_ADDR_L);
93 outb((reg & 0xff00) >> 8, EC_LENOVO_PMH7_ADDR_H);
94 return inb(EC_LENOVO_PMH7_DATA);
95 }
96
pmh7_register_write(int reg,int val)97 void pmh7_register_write(int reg, int val)
98 {
99 outb(reg & 0xff, EC_LENOVO_PMH7_ADDR_L);
100 outb((reg & 0xff00) >> 8, EC_LENOVO_PMH7_ADDR_H);
101 outb(val, EC_LENOVO_PMH7_DATA);
102 }
103
enable_dev(struct device * dev)104 static void enable_dev(struct device *dev)
105 {
106 const struct ec_lenovo_pmh7_config *conf = dev->chip_info;
107 struct resource *resource;
108
109 resource = new_resource(dev, EC_LENOVO_PMH7_INDEX);
110 resource->base = EC_LENOVO_PMH7_BASE;
111 resource->size = 16;
112 resource->align = 5;
113 resource->gran = 5;
114 resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
115
116 pmh7_backlight_enable(conf->backlight_enable);
117 pmh7_dock_event_enable(conf->dock_event_enable);
118
119 pmh7_touchpad_enable(get_uint_option("touchpad", 1));
120
121 pmh7_trackpoint_enable(get_uint_option("trackpoint", 1));
122
123 printk(BIOS_INFO, "PMH7: ID %02x Revision %02x\n",
124 pmh7_register_read(EC_LENOVO_PMH7_REG_ID),
125 pmh7_register_read(EC_LENOVO_PMH7_REG_REV));
126 }
127
128 struct chip_operations ec_lenovo_pmh7_ops = {
129 .name = "Lenovo Power Management Hardware Hub 7",
130 .enable_dev = enable_dev,
131 };
132