View | Details | Raw Unified | Return to bug 238037 | Differences between
and this patch

Collapse All | Expand All

(-)sys/dev/ichiic/ig4_acpi.c (+2 lines)
Lines 153-158 Link Here
153
	DEVMETHOD(device_probe, ig4iic_acpi_probe),
153
	DEVMETHOD(device_probe, ig4iic_acpi_probe),
154
	DEVMETHOD(device_attach, ig4iic_acpi_attach),
154
	DEVMETHOD(device_attach, ig4iic_acpi_attach),
155
	DEVMETHOD(device_detach, ig4iic_acpi_detach),
155
	DEVMETHOD(device_detach, ig4iic_acpi_detach),
156
	DEVMETHOD(device_suspend, bus_generic_suspend),
157
	DEVMETHOD(device_resume, bus_generic_resume),
156
158
157
	/* iicbus interface */
159
	/* iicbus interface */
158
	DEVMETHOD(iicbus_transfer, ig4iic_transfer),
160
	DEVMETHOD(iicbus_transfer, ig4iic_transfer),
(-)sys/dev/ichiic/ig4_iic.c (-21 / +1 lines)
Lines 79-108 Link Here
79
	   &ig4_dump, 0, "Dump controller registers");
79
	   &ig4_dump, 0, "Dump controller registers");
80
80
81
/*
81
/*
82
 * Low-level inline support functions
83
 */
84
static __inline void
85
reg_write(ig4iic_softc_t *sc, uint32_t reg, uint32_t value)
86
{
87
	bus_write_4(sc->regs_res, reg, value);
88
	bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_WRITE);
89
}
90
91
static __inline uint32_t
92
reg_read(ig4iic_softc_t *sc, uint32_t reg)
93
{
94
	uint32_t value;
95
96
	bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_READ);
97
	value = bus_read_4(sc->regs_res, reg);
98
	return (value);
99
}
100
101
/*
102
 * Enable or disable the controller and wait for the controller to acknowledge
82
 * Enable or disable the controller and wait for the controller to acknowledge
103
 * the state change.
83
 * the state change.
104
 */
84
 */
105
static int
85
int
106
set_controller(ig4iic_softc_t *sc, uint32_t ctl)
86
set_controller(ig4iic_softc_t *sc, uint32_t ctl)
107
{
87
{
108
	int retry;
88
	int retry;
(-)sys/dev/ichiic/ig4_pci.c (+111 lines)
Lines 206-216 Link Here
206
	return (0);
206
	return (0);
207
}
207
}
208
208
209
/*
210
 * During suspend we save registers and re-initialize them
211
 * during resume. This is a list of the registers to save.
212
 *
213
 * IG4_REGS_CONTEXT_SIZE is the length of this array.
214
 *   It must be updated if this list is.
215
 *
216
 * The regs_context field of struct ig4iic_softc holds the
217
 * values of the saved registers.
218
 *
219
 * -- NOTE: IG4_REG_I2C_EN MUST be the last register in the list --
220
 *  certain registers require it to be disabled for them to be written
221
 */
222
uint32_t regs_context_ids[IG4_REGS_CONTEXT_SIZE] = {
223
	IG4_REG_CTL,
224
	IG4_REG_TAR_ADD,
225
	IG4_REG_DATA_CMD,
226
	IG4_REG_SS_SCL_HCNT,
227
	IG4_REG_SS_SCL_LCNT,
228
	IG4_REG_FS_SCL_HCNT,
229
	IG4_REG_FS_SCL_LCNT,
230
	IG4_REG_INTR_MASK,
231
	IG4_REG_RX_TL,
232
	IG4_REG_TX_TL,
233
	IG4_REG_SDA_HOLD,
234
	IG4_REG_SLV_DATA_NACK,
235
	IG4_REG_DMA_CTRL,
236
	IG4_REG_DMA_TDLR,
237
	IG4_REG_DMA_RDLR,
238
	IG4_REG_SDA_SETUP,
239
	IG4_REG_GENERAL,
240
	IG4_REG_ACK_GENERAL_CALL,
241
	IG4_REG_SW_LTR_VALUE,
242
	IG4_REG_AUTO_LTR_VALUE,
243
	IG4_REG_I2C_EN,
244
};
245
246
static int
247
ig4iic_pci_suspend(device_t dev)
248
{
249
	ig4iic_softc_t *sc;
250
251
	sc = device_get_softc(dev);
252
253
	/* RESETS spec (22.2.36) recommends saving and re-initializing registers */
254
	for (int i = 0; i < IG4_REGS_CONTEXT_SIZE; i++) {
255
		sc->regs_context[i] = reg_read(sc, regs_context_ids[i]);
256
	}
257
258
	/* 
259
	 * reset the controller before we suspend 
260
	 * Haswell and Skylake apparently have different RESET methods
261
	 */
262
	if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) {
263
		reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_ASSERT_HSW);
264
		
265
	} else if (sc->version == IG4_SKYLAKE) {
266
		/* 
267
		 *
268
		 * set IG4_DEVICE_IDLE and IG4_RESTORE_REQUIRED 
269
		 * to place the device in the idle state, just to be safe
270
		 */
271
		reg_write(sc, IG4_REG_DEVIDLE_CTRL,
272
			  IG4_DEVICE_IDLE | IG4_RESTORE_REQUIRED);
273
274
		reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL);
275
		
276
	} else {
277
		device_printf(dev, "Unable to assert reset, reset register unavailable\n");
278
	}
279
280
	/* suspend all children */
281
	return bus_generic_suspend(dev);
282
}
283
284
static int
285
ig4iic_pci_resume(device_t dev)
286
{
287
	ig4iic_softc_t *sc;
288
289
	sc = device_get_softc(dev);
290
291
	/* wake the controller before its children */
292
	if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) {
293
		reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_DEASSERT_HSW);
294
		
295
	} else if (sc->version == IG4_SKYLAKE) {
296
		/* unset IG4_DEVICE_IDLE  */
297
		reg_write(sc, IG4_REG_DEVIDLE_CTRL, 0);
298
		reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_DEASSERT_SKL);
299
		
300
	} else {
301
		device_printf(dev, "Unable to deassert reset, reset register unavailable\n");
302
	}
303
304
	/* disable the controller before restoring registers */
305
	set_controller(sc, 0);
306
	
307
	/* 
308
	 * set registers to values previously saved in regs_context 
309
	 *  this will re-enable the controller.
310
	 */
311
	for (int i = 0; i < IG4_REGS_CONTEXT_SIZE; i++) {
312
		reg_write(sc, regs_context_ids[i], sc->regs_context[i]);
313
	}
314
315
	return bus_generic_resume(dev);
316
}
317
209
static device_method_t ig4iic_pci_methods[] = {
318
static device_method_t ig4iic_pci_methods[] = {
210
	/* Device interface */
319
	/* Device interface */
211
	DEVMETHOD(device_probe, ig4iic_pci_probe),
320
	DEVMETHOD(device_probe, ig4iic_pci_probe),
212
	DEVMETHOD(device_attach, ig4iic_pci_attach),
321
	DEVMETHOD(device_attach, ig4iic_pci_attach),
213
	DEVMETHOD(device_detach, ig4iic_pci_detach),
322
	DEVMETHOD(device_detach, ig4iic_pci_detach),
323
	DEVMETHOD(device_suspend, ig4iic_pci_suspend),
324
	DEVMETHOD(device_resume, ig4iic_pci_resume),
214
325
215
	DEVMETHOD(iicbus_transfer, ig4iic_transfer),
326
	DEVMETHOD(iicbus_transfer, ig4iic_transfer),
216
	DEVMETHOD(iicbus_reset, ig4iic_reset),
327
	DEVMETHOD(iicbus_reset, ig4iic_reset),
(-)sys/dev/ichiic/ig4_var.h (+28 lines)
Lines 49-54 Link Here
49
enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE };
49
enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE };
50
enum ig4_vers { IG4_HASWELL, IG4_ATOM, IG4_SKYLAKE, IG4_APL };
50
enum ig4_vers { IG4_HASWELL, IG4_ATOM, IG4_SKYLAKE, IG4_APL };
51
51
52
/* length of the register context array (regs_context_ids) */
53
#define IG4_REGS_CONTEXT_SIZE 21
54
52
struct ig4iic_softc {
55
struct ig4iic_softc {
53
	device_t	dev;
56
	device_t	dev;
54
	struct		intr_config_hook enum_hook;
57
	struct		intr_config_hook enum_hook;
Lines 55-60 Link Here
55
	device_t	iicbus;
58
	device_t	iicbus;
56
	struct resource	*regs_res;
59
	struct resource	*regs_res;
57
	int		regs_rid;
60
	int		regs_rid;
61
	uint32_t	regs_context[IG4_REGS_CONTEXT_SIZE];
58
	struct resource	*intr_res;
62
	struct resource	*intr_res;
59
	int		intr_rid;
63
	int		intr_rid;
60
	void		*intr_handle;
64
	void		*intr_handle;
Lines 109-112 Link Here
109
extern iicbus_transfer_t ig4iic_transfer;
113
extern iicbus_transfer_t ig4iic_transfer;
110
extern iicbus_reset_t   ig4iic_reset;
114
extern iicbus_reset_t   ig4iic_reset;
111
115
116
/* enable or disable the controller. */
117
int set_controller(ig4iic_softc_t *sc, uint32_t ctl);
118
119
/*
120
 * Low-level inline support functions
121
 *  used by ig4_iic.c and ig4_pci.c
122
 */
123
static __inline void
124
reg_write(ig4iic_softc_t *sc, uint32_t reg, uint32_t value)
125
{
126
	bus_write_4(sc->regs_res, reg, value);
127
	bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_WRITE);
128
}
129
130
static __inline uint32_t
131
reg_read(ig4iic_softc_t *sc, uint32_t reg)
132
{
133
	uint32_t value;
134
135
	bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_READ);
136
	value = bus_read_4(sc->regs_res, reg);
137
	return (value);
138
}
139
112
#endif /* _ICHIIC_IG4_VAR_H_ */
140
#endif /* _ICHIIC_IG4_VAR_H_ */

Return to bug 238037