xref: /OK3568_Linux_fs/kernel/arch/arm/mach-omap2/usb-tusb6010.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * linux/arch/arm/mach-omap2/usb-tusb6010.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2006 Nokia Corporation
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/err.h>
9*4882a593Smuzhiyun #include <linux/string.h>
10*4882a593Smuzhiyun #include <linux/types.h>
11*4882a593Smuzhiyun #include <linux/errno.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun #include <linux/gpio.h>
15*4882a593Smuzhiyun #include <linux/export.h>
16*4882a593Smuzhiyun #include <linux/platform_data/usb-omap.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include <linux/usb/musb.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include "gpmc.h"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static u8		async_cs, sync_cs;
23*4882a593Smuzhiyun static unsigned		refclk_psec;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static struct gpmc_settings tusb_async = {
26*4882a593Smuzhiyun 	.wait_on_read	= true,
27*4882a593Smuzhiyun 	.wait_on_write	= true,
28*4882a593Smuzhiyun 	.device_width	= GPMC_DEVWIDTH_16BIT,
29*4882a593Smuzhiyun 	.mux_add_data	= GPMC_MUX_AD,
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun static struct gpmc_settings tusb_sync = {
33*4882a593Smuzhiyun 	.burst_read	= true,
34*4882a593Smuzhiyun 	.burst_write	= true,
35*4882a593Smuzhiyun 	.sync_read	= true,
36*4882a593Smuzhiyun 	.sync_write	= true,
37*4882a593Smuzhiyun 	.wait_on_read	= true,
38*4882a593Smuzhiyun 	.wait_on_write	= true,
39*4882a593Smuzhiyun 	.burst_len	= GPMC_BURST_16,
40*4882a593Smuzhiyun 	.device_width	= GPMC_DEVWIDTH_16BIT,
41*4882a593Smuzhiyun 	.mux_add_data	= GPMC_MUX_AD,
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
45*4882a593Smuzhiyun 
tusb_set_async_mode(unsigned sysclk_ps)46*4882a593Smuzhiyun static int tusb_set_async_mode(unsigned sysclk_ps)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	struct gpmc_device_timings dev_t;
49*4882a593Smuzhiyun 	struct gpmc_timings	t;
50*4882a593Smuzhiyun 	unsigned		t_acsnh_advnh = sysclk_ps + 3000;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	memset(&dev_t, 0, sizeof(dev_t));
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	dev_t.t_ceasu = 8 * 1000;
55*4882a593Smuzhiyun 	dev_t.t_avdasu = t_acsnh_advnh - 7000;
56*4882a593Smuzhiyun 	dev_t.t_ce_avd = 1000;
57*4882a593Smuzhiyun 	dev_t.t_avdp_r = t_acsnh_advnh;
58*4882a593Smuzhiyun 	dev_t.t_oeasu = t_acsnh_advnh + 1000;
59*4882a593Smuzhiyun 	dev_t.t_oe = 300;
60*4882a593Smuzhiyun 	dev_t.t_cez_r = 7000;
61*4882a593Smuzhiyun 	dev_t.t_cez_w = dev_t.t_cez_r;
62*4882a593Smuzhiyun 	dev_t.t_avdp_w = t_acsnh_advnh;
63*4882a593Smuzhiyun 	dev_t.t_weasu = t_acsnh_advnh + 1000;
64*4882a593Smuzhiyun 	dev_t.t_wpl = 300;
65*4882a593Smuzhiyun 	dev_t.cyc_aavdh_we = 1;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	gpmc_calc_timings(&t, &tusb_async, &dev_t);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	return gpmc_cs_set_timings(async_cs, &t, &tusb_async);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
tusb_set_sync_mode(unsigned sysclk_ps)72*4882a593Smuzhiyun static int tusb_set_sync_mode(unsigned sysclk_ps)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	struct gpmc_device_timings dev_t;
75*4882a593Smuzhiyun 	struct gpmc_timings	t;
76*4882a593Smuzhiyun 	unsigned		t_scsnh_advnh = sysclk_ps + 3000;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	memset(&dev_t, 0, sizeof(dev_t));
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	dev_t.clk = 11100;
81*4882a593Smuzhiyun 	dev_t.t_bacc = 1000;
82*4882a593Smuzhiyun 	dev_t.t_ces = 1000;
83*4882a593Smuzhiyun 	dev_t.t_ceasu = 8 * 1000;
84*4882a593Smuzhiyun 	dev_t.t_avdasu = t_scsnh_advnh - 7000;
85*4882a593Smuzhiyun 	dev_t.t_ce_avd = 1000;
86*4882a593Smuzhiyun 	dev_t.t_avdp_r = t_scsnh_advnh;
87*4882a593Smuzhiyun 	dev_t.cyc_aavdh_oe = 3;
88*4882a593Smuzhiyun 	dev_t.cyc_oe = 5;
89*4882a593Smuzhiyun 	dev_t.t_ce_rdyz = 7000;
90*4882a593Smuzhiyun 	dev_t.t_avdp_w = t_scsnh_advnh;
91*4882a593Smuzhiyun 	dev_t.cyc_aavdh_we = 3;
92*4882a593Smuzhiyun 	dev_t.cyc_wpl = 6;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	gpmc_calc_timings(&t, &tusb_sync, &dev_t);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	return gpmc_cs_set_timings(sync_cs, &t, &tusb_sync);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /* tusb driver calls this when it changes the chip's clocking */
tusb6010_platform_retime(unsigned is_refclk)100*4882a593Smuzhiyun int tusb6010_platform_retime(unsigned is_refclk)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	static const char	error[] =
103*4882a593Smuzhiyun 		KERN_ERR "tusb6010 %s retime error %d\n";
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	unsigned	sysclk_ps;
106*4882a593Smuzhiyun 	int		status;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	if (!refclk_psec)
109*4882a593Smuzhiyun 		return -ENODEV;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	status = tusb_set_async_mode(sysclk_ps);
114*4882a593Smuzhiyun 	if (status < 0) {
115*4882a593Smuzhiyun 		printk(error, "async", status);
116*4882a593Smuzhiyun 		goto done;
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 	status = tusb_set_sync_mode(sysclk_ps);
119*4882a593Smuzhiyun 	if (status < 0)
120*4882a593Smuzhiyun 		printk(error, "sync", status);
121*4882a593Smuzhiyun done:
122*4882a593Smuzhiyun 	return status;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun static struct resource tusb_resources[] = {
127*4882a593Smuzhiyun 	/* Order is significant!  The start/end fields
128*4882a593Smuzhiyun 	 * are updated during setup..
129*4882a593Smuzhiyun 	 */
130*4882a593Smuzhiyun 	{ /* Asynchronous access */
131*4882a593Smuzhiyun 		.flags	= IORESOURCE_MEM,
132*4882a593Smuzhiyun 	},
133*4882a593Smuzhiyun 	{ /* Synchronous access */
134*4882a593Smuzhiyun 		.flags	= IORESOURCE_MEM,
135*4882a593Smuzhiyun 	},
136*4882a593Smuzhiyun 	{ /* IRQ */
137*4882a593Smuzhiyun 		.name	= "mc",
138*4882a593Smuzhiyun 		.flags	= IORESOURCE_IRQ,
139*4882a593Smuzhiyun 	},
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun static u64 tusb_dmamask = ~(u32)0;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun static struct platform_device tusb_device = {
145*4882a593Smuzhiyun 	.name		= "musb-tusb",
146*4882a593Smuzhiyun 	.id		= -1,
147*4882a593Smuzhiyun 	.dev = {
148*4882a593Smuzhiyun 		.dma_mask		= &tusb_dmamask,
149*4882a593Smuzhiyun 		.coherent_dma_mask	= 0xffffffff,
150*4882a593Smuzhiyun 	},
151*4882a593Smuzhiyun 	.num_resources	= ARRAY_SIZE(tusb_resources),
152*4882a593Smuzhiyun 	.resource	= tusb_resources,
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /* this may be called only from board-*.c setup code */
157*4882a593Smuzhiyun int __init
tusb6010_setup_interface(struct musb_hdrc_platform_data * data,unsigned ps_refclk,unsigned waitpin,unsigned async,unsigned sync,unsigned irq,unsigned dmachan)158*4882a593Smuzhiyun tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
159*4882a593Smuzhiyun 		unsigned ps_refclk, unsigned waitpin,
160*4882a593Smuzhiyun 		unsigned async, unsigned sync,
161*4882a593Smuzhiyun 		unsigned irq, unsigned dmachan)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	int		status;
164*4882a593Smuzhiyun 	static char	error[] __initdata =
165*4882a593Smuzhiyun 		KERN_ERR "tusb6010 init error %d, %d\n";
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* ASYNC region, primarily for PIO */
168*4882a593Smuzhiyun 	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
169*4882a593Smuzhiyun 				&tusb_resources[0].start);
170*4882a593Smuzhiyun 	if (status < 0) {
171*4882a593Smuzhiyun 		printk(error, 1, status);
172*4882a593Smuzhiyun 		return status;
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun 	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
175*4882a593Smuzhiyun 	tusb_async.wait_pin = waitpin;
176*4882a593Smuzhiyun 	async_cs = async;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	status = gpmc_cs_program_settings(async_cs, &tusb_async);
179*4882a593Smuzhiyun 	if (status < 0)
180*4882a593Smuzhiyun 		return status;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	/* SYNC region, primarily for DMA */
183*4882a593Smuzhiyun 	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
184*4882a593Smuzhiyun 				&tusb_resources[1].start);
185*4882a593Smuzhiyun 	if (status < 0) {
186*4882a593Smuzhiyun 		printk(error, 2, status);
187*4882a593Smuzhiyun 		return status;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
190*4882a593Smuzhiyun 	tusb_sync.wait_pin = waitpin;
191*4882a593Smuzhiyun 	sync_cs = sync;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	status = gpmc_cs_program_settings(sync_cs, &tusb_sync);
194*4882a593Smuzhiyun 	if (status < 0)
195*4882a593Smuzhiyun 		return status;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* IRQ */
198*4882a593Smuzhiyun 	status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
199*4882a593Smuzhiyun 	if (status < 0) {
200*4882a593Smuzhiyun 		printk(error, 3, status);
201*4882a593Smuzhiyun 		return status;
202*4882a593Smuzhiyun 	}
203*4882a593Smuzhiyun 	tusb_resources[2].start = gpio_to_irq(irq);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	/* set up memory timings ... can speed them up later */
206*4882a593Smuzhiyun 	if (!ps_refclk) {
207*4882a593Smuzhiyun 		printk(error, 4, status);
208*4882a593Smuzhiyun 		return -ENODEV;
209*4882a593Smuzhiyun 	}
210*4882a593Smuzhiyun 	refclk_psec = ps_refclk;
211*4882a593Smuzhiyun 	status = tusb6010_platform_retime(1);
212*4882a593Smuzhiyun 	if (status < 0) {
213*4882a593Smuzhiyun 		printk(error, 5, status);
214*4882a593Smuzhiyun 		return status;
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	/* finish device setup ... */
218*4882a593Smuzhiyun 	if (!data) {
219*4882a593Smuzhiyun 		printk(error, 6, status);
220*4882a593Smuzhiyun 		return -ENODEV;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 	tusb_device.dev.platform_data = data;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	/* so far so good ... register the device */
225*4882a593Smuzhiyun 	status = platform_device_register(&tusb_device);
226*4882a593Smuzhiyun 	if (status < 0) {
227*4882a593Smuzhiyun 		printk(error, 7, status);
228*4882a593Smuzhiyun 		return status;
229*4882a593Smuzhiyun 	}
230*4882a593Smuzhiyun 	return 0;
231*4882a593Smuzhiyun }
232