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