xref: /OK3568_Linux_fs/kernel/drivers/ide/palm_bk3710.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Palmchip bk3710 IDE controller
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2006 Texas Instruments.
6*4882a593Smuzhiyun  * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * ----------------------------------------------------------------------------
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * ----------------------------------------------------------------------------
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/types.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/kernel.h>
16*4882a593Smuzhiyun #include <linux/ioport.h>
17*4882a593Smuzhiyun #include <linux/ide.h>
18*4882a593Smuzhiyun #include <linux/delay.h>
19*4882a593Smuzhiyun #include <linux/init.h>
20*4882a593Smuzhiyun #include <linux/clk.h>
21*4882a593Smuzhiyun #include <linux/platform_device.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun /* Offset of the primary interface registers */
24*4882a593Smuzhiyun #define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /* Primary Control Offset */
27*4882a593Smuzhiyun #define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define BK3710_BMICP		0x00
30*4882a593Smuzhiyun #define BK3710_BMISP		0x02
31*4882a593Smuzhiyun #define BK3710_BMIDTP		0x04
32*4882a593Smuzhiyun #define BK3710_IDETIMP		0x40
33*4882a593Smuzhiyun #define BK3710_IDESTATUS	0x47
34*4882a593Smuzhiyun #define BK3710_UDMACTL		0x48
35*4882a593Smuzhiyun #define BK3710_MISCCTL		0x50
36*4882a593Smuzhiyun #define BK3710_REGSTB		0x54
37*4882a593Smuzhiyun #define BK3710_REGRCVR		0x58
38*4882a593Smuzhiyun #define BK3710_DATSTB		0x5C
39*4882a593Smuzhiyun #define BK3710_DATRCVR		0x60
40*4882a593Smuzhiyun #define BK3710_DMASTB		0x64
41*4882a593Smuzhiyun #define BK3710_DMARCVR		0x68
42*4882a593Smuzhiyun #define BK3710_UDMASTB		0x6C
43*4882a593Smuzhiyun #define BK3710_UDMATRP		0x70
44*4882a593Smuzhiyun #define BK3710_UDMAENV		0x74
45*4882a593Smuzhiyun #define BK3710_IORDYTMP		0x78
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun static unsigned ideclk_period; /* in nanoseconds */
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun struct palm_bk3710_udmatiming {
50*4882a593Smuzhiyun 	unsigned int rptime;	/* tRP -- Ready to pause time (nsec) */
51*4882a593Smuzhiyun 	unsigned int cycletime;	/* tCYCTYP2/2 -- avg Cycle Time (nsec) */
52*4882a593Smuzhiyun 				/* tENV is always a minimum of 20 nsec */
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
56*4882a593Smuzhiyun 	{ 160, 240 / 2 },	/* UDMA Mode 0 */
57*4882a593Smuzhiyun 	{ 125, 160 / 2 },	/* UDMA Mode 1 */
58*4882a593Smuzhiyun 	{ 100, 120 / 2 },	/* UDMA Mode 2 */
59*4882a593Smuzhiyun 	{ 100,  90 / 2 },	/* UDMA Mode 3 */
60*4882a593Smuzhiyun 	{ 100,  60 / 2 },	/* UDMA Mode 4 */
61*4882a593Smuzhiyun 	{  85,  40 / 2 },	/* UDMA Mode 5 */
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun 
palm_bk3710_setudmamode(void __iomem * base,unsigned int dev,unsigned int mode)64*4882a593Smuzhiyun static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
65*4882a593Smuzhiyun 				    unsigned int mode)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	u8 tenv, trp, t0;
68*4882a593Smuzhiyun 	u32 val32;
69*4882a593Smuzhiyun 	u16 val16;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	/* DMA Data Setup */
72*4882a593Smuzhiyun 	t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
73*4882a593Smuzhiyun 			  ideclk_period) - 1;
74*4882a593Smuzhiyun 	tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
75*4882a593Smuzhiyun 	trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
76*4882a593Smuzhiyun 			   ideclk_period) - 1;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	/* udmastb Ultra DMA Access Strobe Width */
79*4882a593Smuzhiyun 	val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
80*4882a593Smuzhiyun 	val32 |= (t0 << (dev ? 8 : 0));
81*4882a593Smuzhiyun 	writel(val32, base + BK3710_UDMASTB);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	/* udmatrp Ultra DMA Ready to Pause Time */
84*4882a593Smuzhiyun 	val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
85*4882a593Smuzhiyun 	val32 |= (trp << (dev ? 8 : 0));
86*4882a593Smuzhiyun 	writel(val32, base + BK3710_UDMATRP);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* udmaenv Ultra DMA envelop Time */
89*4882a593Smuzhiyun 	val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
90*4882a593Smuzhiyun 	val32 |= (tenv << (dev ? 8 : 0));
91*4882a593Smuzhiyun 	writel(val32, base + BK3710_UDMAENV);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	/* Enable UDMA for Device */
94*4882a593Smuzhiyun 	val16 = readw(base + BK3710_UDMACTL) | (1 << dev);
95*4882a593Smuzhiyun 	writew(val16, base + BK3710_UDMACTL);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
palm_bk3710_setdmamode(void __iomem * base,unsigned int dev,unsigned short min_cycle,unsigned int mode)98*4882a593Smuzhiyun static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
99*4882a593Smuzhiyun 				   unsigned short min_cycle,
100*4882a593Smuzhiyun 				   unsigned int mode)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	u8 td, tkw, t0;
103*4882a593Smuzhiyun 	u32 val32;
104*4882a593Smuzhiyun 	u16 val16;
105*4882a593Smuzhiyun 	struct ide_timing *t;
106*4882a593Smuzhiyun 	int cycletime;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	t = ide_timing_find_mode(mode);
109*4882a593Smuzhiyun 	cycletime = max_t(int, t->cycle, min_cycle);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	/* DMA Data Setup */
112*4882a593Smuzhiyun 	t0 = DIV_ROUND_UP(cycletime, ideclk_period);
113*4882a593Smuzhiyun 	td = DIV_ROUND_UP(t->active, ideclk_period);
114*4882a593Smuzhiyun 	tkw = t0 - td - 1;
115*4882a593Smuzhiyun 	td -= 1;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
118*4882a593Smuzhiyun 	val32 |= (td << (dev ? 8 : 0));
119*4882a593Smuzhiyun 	writel(val32, base + BK3710_DMASTB);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
122*4882a593Smuzhiyun 	val32 |= (tkw << (dev ? 8 : 0));
123*4882a593Smuzhiyun 	writel(val32, base + BK3710_DMARCVR);
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	/* Disable UDMA for Device */
126*4882a593Smuzhiyun 	val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev);
127*4882a593Smuzhiyun 	writew(val16, base + BK3710_UDMACTL);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
palm_bk3710_setpiomode(void __iomem * base,ide_drive_t * mate,unsigned int dev,unsigned int cycletime,unsigned int mode)130*4882a593Smuzhiyun static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
131*4882a593Smuzhiyun 				   unsigned int dev, unsigned int cycletime,
132*4882a593Smuzhiyun 				   unsigned int mode)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	u8 t2, t2i, t0;
135*4882a593Smuzhiyun 	u32 val32;
136*4882a593Smuzhiyun 	struct ide_timing *t;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	t = ide_timing_find_mode(XFER_PIO_0 + mode);
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	/* PIO Data Setup */
141*4882a593Smuzhiyun 	t0 = DIV_ROUND_UP(cycletime, ideclk_period);
142*4882a593Smuzhiyun 	t2 = DIV_ROUND_UP(t->active, ideclk_period);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	t2i = t0 - t2 - 1;
145*4882a593Smuzhiyun 	t2 -= 1;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
148*4882a593Smuzhiyun 	val32 |= (t2 << (dev ? 8 : 0));
149*4882a593Smuzhiyun 	writel(val32, base + BK3710_DATSTB);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
152*4882a593Smuzhiyun 	val32 |= (t2i << (dev ? 8 : 0));
153*4882a593Smuzhiyun 	writel(val32, base + BK3710_DATRCVR);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	if (mate) {
156*4882a593Smuzhiyun 		u8 mode2 = mate->pio_mode - XFER_PIO_0;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 		if (mode2 < mode)
159*4882a593Smuzhiyun 			mode = mode2;
160*4882a593Smuzhiyun 	}
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	/* TASKFILE Setup */
163*4882a593Smuzhiyun 	t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
164*4882a593Smuzhiyun 	t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	t2i = t0 - t2 - 1;
167*4882a593Smuzhiyun 	t2 -= 1;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
170*4882a593Smuzhiyun 	val32 |= (t2 << (dev ? 8 : 0));
171*4882a593Smuzhiyun 	writel(val32, base + BK3710_REGSTB);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
174*4882a593Smuzhiyun 	val32 |= (t2i << (dev ? 8 : 0));
175*4882a593Smuzhiyun 	writel(val32, base + BK3710_REGRCVR);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
palm_bk3710_set_dma_mode(ide_hwif_t * hwif,ide_drive_t * drive)178*4882a593Smuzhiyun static void palm_bk3710_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	int is_slave = drive->dn & 1;
181*4882a593Smuzhiyun 	void __iomem *base = (void __iomem *)hwif->dma_base;
182*4882a593Smuzhiyun 	const u8 xferspeed = drive->dma_mode;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	if (xferspeed >= XFER_UDMA_0) {
185*4882a593Smuzhiyun 		palm_bk3710_setudmamode(base, is_slave,
186*4882a593Smuzhiyun 					xferspeed - XFER_UDMA_0);
187*4882a593Smuzhiyun 	} else {
188*4882a593Smuzhiyun 		palm_bk3710_setdmamode(base, is_slave,
189*4882a593Smuzhiyun 				       drive->id[ATA_ID_EIDE_DMA_MIN],
190*4882a593Smuzhiyun 				       xferspeed);
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
palm_bk3710_set_pio_mode(ide_hwif_t * hwif,ide_drive_t * drive)194*4882a593Smuzhiyun static void palm_bk3710_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	unsigned int cycle_time;
197*4882a593Smuzhiyun 	int is_slave = drive->dn & 1;
198*4882a593Smuzhiyun 	ide_drive_t *mate;
199*4882a593Smuzhiyun 	void __iomem *base = (void __iomem *)hwif->dma_base;
200*4882a593Smuzhiyun 	const u8 pio = drive->pio_mode - XFER_PIO_0;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	/*
203*4882a593Smuzhiyun 	 * Obtain the drive PIO data for tuning the Palm Chip registers
204*4882a593Smuzhiyun 	 */
205*4882a593Smuzhiyun 	cycle_time = ide_pio_cycle_time(drive, pio);
206*4882a593Smuzhiyun 	mate = ide_get_pair_dev(drive);
207*4882a593Smuzhiyun 	palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
palm_bk3710_chipinit(void __iomem * base)210*4882a593Smuzhiyun static void palm_bk3710_chipinit(void __iomem *base)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	/*
213*4882a593Smuzhiyun 	 * REVISIT:  the ATA reset signal needs to be managed through a
214*4882a593Smuzhiyun 	 * GPIO, which means it should come from platform_data.  Until
215*4882a593Smuzhiyun 	 * we get and use such information, we have to trust that things
216*4882a593Smuzhiyun 	 * have been reset before we get here.
217*4882a593Smuzhiyun 	 */
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	/*
220*4882a593Smuzhiyun 	 * Program the IDETIMP Register Value based on the following assumptions
221*4882a593Smuzhiyun 	 *
222*4882a593Smuzhiyun 	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
223*4882a593Smuzhiyun 	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
224*4882a593Smuzhiyun 	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
225*4882a593Smuzhiyun 	 *
226*4882a593Smuzhiyun 	 * DM6446 silicon rev 2.1 and earlier have no observed net benefit
227*4882a593Smuzhiyun 	 * from enabling prefetch/postwrite.
228*4882a593Smuzhiyun 	 */
229*4882a593Smuzhiyun 	writew(BIT(15), base + BK3710_IDETIMP);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	/*
232*4882a593Smuzhiyun 	 * UDMACTL Ultra-ATA DMA Control
233*4882a593Smuzhiyun 	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
234*4882a593Smuzhiyun 	 * (ATA_UDMACTL_UDMAP0	, 0 )
235*4882a593Smuzhiyun 	 *
236*4882a593Smuzhiyun 	 */
237*4882a593Smuzhiyun 	writew(0, base + BK3710_UDMACTL);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/*
240*4882a593Smuzhiyun 	 * MISCCTL Miscellaneous Conrol Register
241*4882a593Smuzhiyun 	 * (ATA_MISCCTL_HWNHLD1P	, 1 cycle)
242*4882a593Smuzhiyun 	 * (ATA_MISCCTL_HWNHLD0P	, 1 cycle)
243*4882a593Smuzhiyun 	 * (ATA_MISCCTL_TIMORIDE	, 1)
244*4882a593Smuzhiyun 	 */
245*4882a593Smuzhiyun 	writel(0x001, base + BK3710_MISCCTL);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	/*
248*4882a593Smuzhiyun 	 * IORDYTMP IORDY Timer for Primary Register
249*4882a593Smuzhiyun 	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
250*4882a593Smuzhiyun 	 */
251*4882a593Smuzhiyun 	writel(0xFFFF, base + BK3710_IORDYTMP);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	/*
254*4882a593Smuzhiyun 	 * Configure BMISP Register
255*4882a593Smuzhiyun 	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
256*4882a593Smuzhiyun 	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
257*4882a593Smuzhiyun 	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
258*4882a593Smuzhiyun 	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
259*4882a593Smuzhiyun 	 * (ATA_BMISP_DMAERROR	, CLEAR)
260*4882a593Smuzhiyun 	 */
261*4882a593Smuzhiyun 	writew(0, base + BK3710_BMISP);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
264*4882a593Smuzhiyun 	palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
palm_bk3710_cable_detect(ide_hwif_t * hwif)267*4882a593Smuzhiyun static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun 	return ATA_CBL_PATA80;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
palm_bk3710_init_dma(ide_hwif_t * hwif,const struct ide_port_info * d)272*4882a593Smuzhiyun static int palm_bk3710_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	if (ide_allocate_dma_engine(hwif))
277*4882a593Smuzhiyun 		return -1;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	return 0;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun static const struct ide_port_ops palm_bk3710_ports_ops = {
285*4882a593Smuzhiyun 	.set_pio_mode		= palm_bk3710_set_pio_mode,
286*4882a593Smuzhiyun 	.set_dma_mode		= palm_bk3710_set_dma_mode,
287*4882a593Smuzhiyun 	.cable_detect		= palm_bk3710_cable_detect,
288*4882a593Smuzhiyun };
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun static struct ide_port_info palm_bk3710_port_info __initdata = {
291*4882a593Smuzhiyun 	.init_dma		= palm_bk3710_init_dma,
292*4882a593Smuzhiyun 	.port_ops		= &palm_bk3710_ports_ops,
293*4882a593Smuzhiyun 	.dma_ops		= &sff_dma_ops,
294*4882a593Smuzhiyun 	.host_flags		= IDE_HFLAG_MMIO,
295*4882a593Smuzhiyun 	.pio_mask		= ATA_PIO4,
296*4882a593Smuzhiyun 	.mwdma_mask		= ATA_MWDMA2,
297*4882a593Smuzhiyun 	.chipset		= ide_palm3710,
298*4882a593Smuzhiyun };
299*4882a593Smuzhiyun 
palm_bk3710_probe(struct platform_device * pdev)300*4882a593Smuzhiyun static int __init palm_bk3710_probe(struct platform_device *pdev)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	struct clk *clk;
303*4882a593Smuzhiyun 	struct resource *mem, *irq;
304*4882a593Smuzhiyun 	void __iomem *base;
305*4882a593Smuzhiyun 	unsigned long rate, mem_size;
306*4882a593Smuzhiyun 	int i, rc;
307*4882a593Smuzhiyun 	struct ide_hw hw, *hws[] = { &hw };
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	clk = clk_get(&pdev->dev, NULL);
310*4882a593Smuzhiyun 	if (IS_ERR(clk))
311*4882a593Smuzhiyun 		return -ENODEV;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	clk_enable(clk);
314*4882a593Smuzhiyun 	rate = clk_get_rate(clk);
315*4882a593Smuzhiyun 	if (!rate)
316*4882a593Smuzhiyun 		return -EINVAL;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	/* NOTE:  round *down* to meet minimum timings; we count in clocks */
319*4882a593Smuzhiyun 	ideclk_period = 1000000000UL / rate;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
322*4882a593Smuzhiyun 	if (mem == NULL) {
323*4882a593Smuzhiyun 		printk(KERN_ERR "failed to get memory region resource\n");
324*4882a593Smuzhiyun 		return -ENODEV;
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
328*4882a593Smuzhiyun 	if (irq == NULL) {
329*4882a593Smuzhiyun 		printk(KERN_ERR "failed to get IRQ resource\n");
330*4882a593Smuzhiyun 		return -ENODEV;
331*4882a593Smuzhiyun 	}
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	mem_size = resource_size(mem);
334*4882a593Smuzhiyun 	if (request_mem_region(mem->start, mem_size, "palm_bk3710") == NULL) {
335*4882a593Smuzhiyun 		printk(KERN_ERR "failed to request memory region\n");
336*4882a593Smuzhiyun 		return -EBUSY;
337*4882a593Smuzhiyun 	}
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	base = ioremap(mem->start, mem_size);
340*4882a593Smuzhiyun 	if (!base) {
341*4882a593Smuzhiyun 		printk(KERN_ERR "failed to map IO memory\n");
342*4882a593Smuzhiyun 		release_mem_region(mem->start, mem_size);
343*4882a593Smuzhiyun 		return -ENOMEM;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	/* Configure the Palm Chip controller */
347*4882a593Smuzhiyun 	palm_bk3710_chipinit(base);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	memset(&hw, 0, sizeof(hw));
350*4882a593Smuzhiyun 	for (i = 0; i < IDE_NR_PORTS - 2; i++)
351*4882a593Smuzhiyun 		hw.io_ports_array[i] = (unsigned long)
352*4882a593Smuzhiyun 				(base + IDE_PALM_ATA_PRI_REG_OFFSET + i);
353*4882a593Smuzhiyun 	hw.io_ports.ctl_addr = (unsigned long)
354*4882a593Smuzhiyun 			(base + IDE_PALM_ATA_PRI_CTL_OFFSET);
355*4882a593Smuzhiyun 	hw.irq = irq->start;
356*4882a593Smuzhiyun 	hw.dev = &pdev->dev;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
359*4882a593Smuzhiyun 							     ATA_UDMA5;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/* Register the IDE interface with Linux */
362*4882a593Smuzhiyun 	rc = ide_host_add(&palm_bk3710_port_info, hws, 1, NULL);
363*4882a593Smuzhiyun 	if (rc)
364*4882a593Smuzhiyun 		goto out;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	return 0;
367*4882a593Smuzhiyun out:
368*4882a593Smuzhiyun 	printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
369*4882a593Smuzhiyun 	return rc;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun /* work with hotplug and coldplug */
373*4882a593Smuzhiyun MODULE_ALIAS("platform:palm_bk3710");
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun static struct platform_driver platform_bk_driver = {
376*4882a593Smuzhiyun 	.driver = {
377*4882a593Smuzhiyun 		.name = "palm_bk3710",
378*4882a593Smuzhiyun 	},
379*4882a593Smuzhiyun };
380*4882a593Smuzhiyun 
palm_bk3710_init(void)381*4882a593Smuzhiyun static int __init palm_bk3710_init(void)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe);
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun module_init(palm_bk3710_init);
387*4882a593Smuzhiyun MODULE_LICENSE("GPL");
388