1/*-
2 * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/limits.h>
35#include <sys/lock.h>
36#include <sys/module.h>
37#include <sys/mutex.h>
38#include <sys/resource.h>
39#include <sys/rman.h>
40#include <sys/sysctl.h>
41
42#include <machine/bus.h>
43
44#include <dev/fdt/fdt_common.h>
45#include <dev/ofw/openfirm.h>
46#include <dev/ofw/ofw_bus.h>
47#include <dev/ofw/ofw_bus_subr.h>
48
49#include <arm/ti/ti_prcm.h>
50#include <arm/ti/ti_scm.h>
51
52#include "am335x_pwm.h"
53#include "am335x_scm.h"
54
55/* In ticks */
56#define	DEFAULT_PWM_PERIOD	1000
57#define	PWM_CLOCK		100000000UL
58
59#define	PWM_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
60#define	PWM_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
61#define	PWM_LOCK_INIT(_sc)	mtx_init(&(_sc)->sc_mtx, \
62    device_get_nameunit(_sc->sc_dev), "am335x_pwm softc", MTX_DEF)
63#define	PWM_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
64
65static struct resource_spec am335x_pwm_mem_spec[] = {
66	{ SYS_RES_MEMORY, 0, RF_ACTIVE }, /* PWMSS */
67	{ SYS_RES_MEMORY, 1, RF_ACTIVE }, /* eCAP */
68	{ SYS_RES_MEMORY, 2, RF_ACTIVE }, /* eQEP */
69	{ SYS_RES_MEMORY, 3, RF_ACTIVE }, /*ePWM */
70	{ -1, 0, 0 }
71};
72
73#define	PWMSS_READ4(_sc, reg)	bus_read_4((_sc)->sc_mem_res[0], reg);
74#define	PWMSS_WRITE4(_sc, reg, value)	\
75    bus_write_4((_sc)->sc_mem_res[0], reg, value);
76
77#define	ECAP_READ2(_sc, reg)	bus_read_2((_sc)->sc_mem_res[1], reg);
78#define	ECAP_WRITE2(_sc, reg, value)	\
79    bus_write_2((_sc)->sc_mem_res[1], reg, value);
80#define	ECAP_READ4(_sc, reg)	bus_read_4((_sc)->sc_mem_res[1], reg);
81#define	ECAP_WRITE4(_sc, reg, value)	\
82    bus_write_4((_sc)->sc_mem_res[1], reg, value);
83
84#define	EPWM_READ2(_sc, reg)	bus_read_2((_sc)->sc_mem_res[3], reg);
85#define	EPWM_WRITE2(_sc, reg, value)	\
86    bus_write_2((_sc)->sc_mem_res[3], reg, value);
87
88#define	PWMSS_IDVER		0x00
89#define	PWMSS_SYSCONFIG		0x04
90#define	PWMSS_CLKCONFIG		0x08
91#define		CLKCONFIG_EPWMCLK_EN	(1 << 8)
92#define	PWMSS_CLKSTATUS		0x0C
93
94#define	ECAP_TSCTR		0x00
95#define	ECAP_CAP1		0x08
96#define	ECAP_CAP2		0x0C
97#define	ECAP_CAP3		0x10
98#define	ECAP_CAP4		0x14
99#define	ECAP_ECCTL2		0x2A
100#define		ECCTL2_MODE_APWM		(1 << 9)
101#define		ECCTL2_SYNCO_SEL		(3 << 6)
102#define		ECCTL2_TSCTRSTOP_FREERUN	(1 << 4)
103
104#define	EPWM_TBCTL		0x00
105#define		TBCTL_FREERUN		(2 << 14)
106#define		TBCTL_PHDIR_UP		(1 << 13)
107#define		TBCTL_PHDIR_DOWN	(0 << 13)
108#define		TBCTL_CLKDIV(x)		((x) << 10)
109#define		TBCTL_CLKDIV_MASK	(3 << 10)
110#define		TBCTL_HSPCLKDIV(x)	((x) << 7)
111#define		TBCTL_HSPCLKDIV_MASK	(3 << 7)
112#define		TBCTL_SYNCOSEL_DISABLED	(3 << 4)
113#define		TBCTL_PRDLD_SHADOW	(0 << 3)
114#define		TBCTL_PRDLD_IMMEDIATE	(0 << 3)
115#define		TBCTL_PHSEN_ENABLED	(1 << 2)
116#define		TBCTL_PHSEN_DISABLED	(0 << 2)
117#define		TBCTL_CTRMODE_MASK	(3)
118#define		TBCTL_CTRMODE_UP	(0 << 0)
119#define		TBCTL_CTRMODE_DOWN	(1 << 0)
120#define		TBCTL_CTRMODE_UPDOWN	(2 << 0)
121#define		TBCTL_CTRMODE_FREEZE	(3 << 0)
122
123#define	EPWM_TBSTS		0x02
124#define	EPWM_TBPHSHR		0x04
125#define	EPWM_TBPHS		0x06
126#define	EPWM_TBCNT		0x08
127#define	EPWM_TBPRD		0x0a
128/* Counter-compare */
129#define	EPWM_CMPCTL		0x0e
130#define		CMPCTL_SHDWBMODE_SHADOW		(1 << 6)
131#define		CMPCTL_SHDWBMODE_IMMEDIATE	(0 << 6)
132#define		CMPCTL_SHDWAMODE_SHADOW		(1 << 4)
133#define		CMPCTL_SHDWAMODE_IMMEDIATE	(0 << 4)
134#define		CMPCTL_LOADBMODE_ZERO		(0 << 2)
135#define		CMPCTL_LOADBMODE_PRD		(1 << 2)
136#define		CMPCTL_LOADBMODE_EITHER		(2 << 2)
137#define		CMPCTL_LOADBMODE_FREEZE		(3 << 2)
138#define		CMPCTL_LOADAMODE_ZERO		(0 << 0)
139#define		CMPCTL_LOADAMODE_PRD		(1 << 0)
140#define		CMPCTL_LOADAMODE_EITHER		(2 << 0)
141#define		CMPCTL_LOADAMODE_FREEZE		(3 << 0)
142#define	EPWM_CMPAHR		0x10
143#define	EPWM_CMPA		0x12
144#define	EPWM_CMPB		0x14
145/* CMPCTL_LOADAMODE_ZERO */
146#define	EPWM_AQCTLA		0x16
147#define	EPWM_AQCTLB		0x18
148#define		AQCTL_CBU_NONE		(0 << 8)
149#define		AQCTL_CBU_CLEAR		(1 << 8)
150#define		AQCTL_CBU_SET		(2 << 8)
151#define		AQCTL_CBU_TOGGLE	(3 << 8)
152#define		AQCTL_CAU_NONE		(0 << 4)
153#define		AQCTL_CAU_CLEAR		(1 << 4)
154#define		AQCTL_CAU_SET		(2 << 4)
155#define		AQCTL_CAU_TOGGLE	(3 << 4)
156#define		AQCTL_ZRO_NONE		(0 << 0)
157#define		AQCTL_ZRO_CLEAR		(1 << 0)
158#define		AQCTL_ZRO_SET		(2 << 0)
159#define		AQCTL_ZRO_TOGGLE	(3 << 0)
160#define	EPWM_AQSFRC		0x1a
161#define	EPWM_AQCSFRC		0x1c
162
163/* Trip-Zone module */
164#define	EPWM_TZCTL		0x28
165#define	EPWM_TZFLG		0x2C
166/* High-Resolution PWM */
167#define	EPWM_HRCTL		0x40
168#define		HRCTL_DELMODE_BOTH	3
169#define		HRCTL_DELMODE_FALL	2
170#define		HRCTL_DELMODE_RISE	1
171
172static device_probe_t am335x_pwm_probe;
173static device_attach_t am335x_pwm_attach;
174static device_detach_t am335x_pwm_detach;
175
176static int am335x_pwm_clkdiv[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
177
178struct am335x_pwm_softc {
179	device_t		sc_dev;
180	struct mtx		sc_mtx;
181	struct resource		*sc_mem_res[4];
182	int			sc_id;
183	/* sysctl for configuration */
184	int			sc_pwm_clkdiv;
185	int			sc_pwm_freq;
186	struct sysctl_oid	*sc_clkdiv_oid;
187	struct sysctl_oid	*sc_freq_oid;
188	struct sysctl_oid	*sc_period_oid;
189	struct sysctl_oid	*sc_chanA_oid;
190	struct sysctl_oid	*sc_chanB_oid;
191	uint32_t		sc_pwm_period;
192	uint32_t		sc_pwm_dutyA;
193	uint32_t		sc_pwm_dutyB;
194};
195
196static device_method_t am335x_pwm_methods[] = {
197	DEVMETHOD(device_probe,		am335x_pwm_probe),
198	DEVMETHOD(device_attach,	am335x_pwm_attach),
199	DEVMETHOD(device_detach,	am335x_pwm_detach),
200
201	DEVMETHOD_END
202};
203
204static driver_t am335x_pwm_driver = {
205	"am335x_pwm",
206	am335x_pwm_methods,
207	sizeof(struct am335x_pwm_softc),
208};
209
210static devclass_t am335x_pwm_devclass;
211
212/*
213 * API function to set period/duty cycles for ECASx
214 */
215int
216am335x_pwm_config_ecas(int unit, int period, int duty)
217{
218	device_t dev;
219	struct am335x_pwm_softc *sc;
220	uint16_t reg;
221
222	dev = devclass_get_device(am335x_pwm_devclass, unit);
223	if (dev == NULL)
224		return (ENXIO);
225
226	if (duty > period)
227		return (EINVAL);
228
229	if (period == 0)
230		return (EINVAL);
231
232	sc = device_get_softc(dev);
233	PWM_LOCK(sc);
234
235	reg = ECAP_READ2(sc, ECAP_ECCTL2);
236	reg |= ECCTL2_MODE_APWM | ECCTL2_TSCTRSTOP_FREERUN | ECCTL2_SYNCO_SEL;
237	ECAP_WRITE2(sc, ECAP_ECCTL2, reg);
238
239	/* CAP3 in APWM mode is APRD shadow register */
240	ECAP_WRITE4(sc, ECAP_CAP3, period - 1);
241
242	/* CAP4 in APWM mode is ACMP shadow register */
243	ECAP_WRITE4(sc, ECAP_CAP4, duty);
244	/* Restart counter */
245	ECAP_WRITE4(sc, ECAP_TSCTR, 0);
246
247	PWM_UNLOCK(sc);
248
249	return (0);
250}
251
252static void
253am335x_pwm_freq(struct am335x_pwm_softc *sc)
254{
255	int clkdiv;
256
257	clkdiv = am335x_pwm_clkdiv[sc->sc_pwm_clkdiv];
258	sc->sc_pwm_freq = PWM_CLOCK / (1 * clkdiv) / sc->sc_pwm_period;
259}
260
261static int
262am335x_pwm_sysctl_freq(SYSCTL_HANDLER_ARGS)
263{
264	int clkdiv, error, freq, i, period;
265	struct am335x_pwm_softc *sc;
266	uint32_t reg;
267
268	sc = (struct am335x_pwm_softc *)arg1;
269
270	PWM_LOCK(sc);
271	freq = sc->sc_pwm_freq;
272	PWM_UNLOCK(sc);
273
274	error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
275	if (error != 0 || req->newptr == NULL)
276		return (error);
277
278	if (freq > PWM_CLOCK)
279		freq = PWM_CLOCK;
280
281	PWM_LOCK(sc);
282	if (freq != sc->sc_pwm_freq) {
283		for (i = nitems(am335x_pwm_clkdiv) - 1; i >= 0; i--) {
284			clkdiv = am335x_pwm_clkdiv[i];
285			period = PWM_CLOCK / clkdiv / freq;
286			if (period > USHRT_MAX)
287				break;
288			sc->sc_pwm_clkdiv = i;
289			sc->sc_pwm_period = period;
290		}
291		/* Reset the duty cycle settings. */
292		sc->sc_pwm_dutyA = 0;
293		sc->sc_pwm_dutyB = 0;
294		EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
295		EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
296		/* Update the clkdiv settings. */
297		reg = EPWM_READ2(sc, EPWM_TBCTL);
298		reg &= ~TBCTL_CLKDIV_MASK;
299		reg |= TBCTL_CLKDIV(sc->sc_pwm_clkdiv);
300		EPWM_WRITE2(sc, EPWM_TBCTL, reg);
301		/* Update the period settings. */
302		EPWM_WRITE2(sc, EPWM_TBPRD, sc->sc_pwm_period - 1);
303		am335x_pwm_freq(sc);
304	}
305	PWM_UNLOCK(sc);
306
307	return (0);
308}
309
310static int
311am335x_pwm_sysctl_clkdiv(SYSCTL_HANDLER_ARGS)
312{
313	int error, i, clkdiv;
314	struct am335x_pwm_softc *sc;
315	uint32_t reg;
316
317	sc = (struct am335x_pwm_softc *)arg1;
318
319	PWM_LOCK(sc);
320	clkdiv = am335x_pwm_clkdiv[sc->sc_pwm_clkdiv];
321	PWM_UNLOCK(sc);
322
323	error = sysctl_handle_int(oidp, &clkdiv, sizeof(clkdiv), req);
324	if (error != 0 || req->newptr == NULL)
325		return (error);
326
327	PWM_LOCK(sc);
328	if (clkdiv != am335x_pwm_clkdiv[sc->sc_pwm_clkdiv]) {
329		for (i = 0; i < nitems(am335x_pwm_clkdiv); i++)
330			if (clkdiv >= am335x_pwm_clkdiv[i])
331				sc->sc_pwm_clkdiv = i;
332
333		reg = EPWM_READ2(sc, EPWM_TBCTL);
334		reg &= ~TBCTL_CLKDIV_MASK;
335		reg |= TBCTL_CLKDIV(sc->sc_pwm_clkdiv);
336		EPWM_WRITE2(sc, EPWM_TBCTL, reg);
337		am335x_pwm_freq(sc);
338	}
339	PWM_UNLOCK(sc);
340
341	return (0);
342}
343
344static int
345am335x_pwm_sysctl_duty(SYSCTL_HANDLER_ARGS)
346{
347	struct am335x_pwm_softc *sc = (struct am335x_pwm_softc*)arg1;
348	int error;
349	uint32_t duty;
350
351	if (oidp == sc->sc_chanA_oid)
352		duty = sc->sc_pwm_dutyA;
353	else
354		duty = sc->sc_pwm_dutyB;
355	error = sysctl_handle_int(oidp, &duty, 0, req);
356
357	if (error != 0 || req->newptr == NULL)
358		return (error);
359
360	if (duty > sc->sc_pwm_period) {
361		device_printf(sc->sc_dev, "Duty cycle can't be greater then period\n");
362		return (EINVAL);
363	}
364
365	PWM_LOCK(sc);
366	if (oidp == sc->sc_chanA_oid) {
367		sc->sc_pwm_dutyA = duty;
368		EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
369	}
370	else {
371		sc->sc_pwm_dutyB = duty;
372		EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
373	}
374	PWM_UNLOCK(sc);
375
376	return (error);
377}
378
379static int
380am335x_pwm_sysctl_period(SYSCTL_HANDLER_ARGS)
381{
382	struct am335x_pwm_softc *sc = (struct am335x_pwm_softc*)arg1;
383	int error;
384	uint32_t period;
385
386	period = sc->sc_pwm_period;
387	error = sysctl_handle_int(oidp, &period, 0, req);
388
389	if (error != 0 || req->newptr == NULL)
390		return (error);
391
392	if (period < 1)
393		return (EINVAL);
394
395	if (period > USHRT_MAX)
396		period = USHRT_MAX;
397
398	PWM_LOCK(sc);
399	/* Reset the duty cycle settings. */
400	sc->sc_pwm_dutyA = 0;
401	sc->sc_pwm_dutyB = 0;
402	EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
403	EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
404	/* Update the period settings. */
405	sc->sc_pwm_period = period;
406	EPWM_WRITE2(sc, EPWM_TBPRD, period - 1);
407	am335x_pwm_freq(sc);
408	PWM_UNLOCK(sc);
409
410	return (error);
411}
412
413static int
414am335x_pwm_probe(device_t dev)
415{
416
417	if (!ofw_bus_status_okay(dev))
418		return (ENXIO);
419
420	if (!ofw_bus_is_compatible(dev, "ti,am335x-pwm"))
421		return (ENXIO);
422
423	device_set_desc(dev, "AM335x PWM");
424
425	return (BUS_PROBE_DEFAULT);
426}
427
428static int
429am335x_pwm_attach(device_t dev)
430{
431	struct am335x_pwm_softc *sc;
432	int err;
433	uint32_t reg;
434	phandle_t node;
435	pcell_t did;
436	struct sysctl_ctx_list *ctx;
437	struct sysctl_oid *tree;
438
439	sc = device_get_softc(dev);
440	sc->sc_dev = dev;
441	/* Get the PWM module id */
442	node = ofw_bus_get_node(dev);
443	if ((OF_getprop(node, "pwm-device-id", &did, sizeof(did))) <= 0) {
444		device_printf(dev, "missing pwm-device-id attribute in FDT\n");
445		return (ENXIO);
446	}
447	sc->sc_id = fdt32_to_cpu(did);
448
449	PWM_LOCK_INIT(sc);
450
451	err = bus_alloc_resources(dev, am335x_pwm_mem_spec,
452	    sc->sc_mem_res);
453	if (err) {
454		device_printf(dev, "cannot allocate memory resources\n");
455		goto fail;
456	}
457
458	ti_prcm_clk_enable(PWMSS0_CLK + sc->sc_id);
459	ti_scm_reg_read_4(SCM_PWMSS_CTRL, &reg);
460	reg |= (1 << sc->sc_id);
461	ti_scm_reg_write_4(SCM_PWMSS_CTRL, reg);
462
463	/* Init backlight interface */
464	ctx = device_get_sysctl_ctx(sc->sc_dev);
465	tree = device_get_sysctl_tree(sc->sc_dev);
466
467	sc->sc_clkdiv_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
468	    "clkdiv", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
469	    am335x_pwm_sysctl_clkdiv, "I", "PWM clock prescaler");
470
471	sc->sc_freq_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
472	    "freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
473	    am335x_pwm_sysctl_freq, "I", "PWM frequency");
474
475	sc->sc_period_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
476	    "period", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
477	    am335x_pwm_sysctl_period, "I", "PWM period");
478
479	sc->sc_chanA_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
480	    "dutyA", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
481	    am335x_pwm_sysctl_duty, "I", "Channel A duty cycles");
482
483	sc->sc_chanB_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
484	    "dutyB", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
485	    am335x_pwm_sysctl_duty, "I", "Channel B duty cycles");
486
487	/* CONFIGURE EPWM1 */
488	reg = EPWM_READ2(sc, EPWM_TBCTL);
489	reg &= ~(TBCTL_CLKDIV_MASK | TBCTL_HSPCLKDIV_MASK);
490	EPWM_WRITE2(sc, EPWM_TBCTL, reg);
491
492	sc->sc_pwm_period = DEFAULT_PWM_PERIOD;
493	sc->sc_pwm_dutyA = 0;
494	sc->sc_pwm_dutyB = 0;
495	am335x_pwm_freq(sc);
496
497	EPWM_WRITE2(sc, EPWM_TBPRD, sc->sc_pwm_period - 1);
498	EPWM_WRITE2(sc, EPWM_CMPA, sc->sc_pwm_dutyA);
499	EPWM_WRITE2(sc, EPWM_CMPB, sc->sc_pwm_dutyB);
500
501	EPWM_WRITE2(sc, EPWM_AQCTLA, (AQCTL_ZRO_SET | AQCTL_CAU_CLEAR));
502	EPWM_WRITE2(sc, EPWM_AQCTLB, (AQCTL_ZRO_SET | AQCTL_CBU_CLEAR));
503
504	/* START EPWM */
505	reg &= ~TBCTL_CTRMODE_MASK;
506	reg |= TBCTL_CTRMODE_UP | TBCTL_FREERUN;
507	EPWM_WRITE2(sc, EPWM_TBCTL, reg);
508
509	EPWM_WRITE2(sc, EPWM_TZCTL, 0xf);
510	reg = EPWM_READ2(sc, EPWM_TZFLG);
511
512	return (0);
513fail:
514	PWM_LOCK_DESTROY(sc);
515	if (sc->sc_mem_res[0])
516		bus_release_resources(dev, am335x_pwm_mem_spec,
517		    sc->sc_mem_res);
518
519	return(ENXIO);
520}
521
522static int
523am335x_pwm_detach(device_t dev)
524{
525	struct am335x_pwm_softc *sc;
526
527	sc = device_get_softc(dev);
528
529	PWM_LOCK(sc);
530	if (sc->sc_mem_res[0])
531		bus_release_resources(dev, am335x_pwm_mem_spec,
532		    sc->sc_mem_res);
533	PWM_UNLOCK(sc);
534
535	PWM_LOCK_DESTROY(sc);
536
537	return (0);
538}
539
540DRIVER_MODULE(am335x_pwm, simplebus, am335x_pwm_driver, am335x_pwm_devclass, 0, 0);
541MODULE_VERSION(am335x_pwm, 1);
542MODULE_DEPEND(am335x_pwm, simplebus, 1, 1, 1);
543