aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/tc6393xb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/tc6393xb.c')
-rw-r--r--drivers/mfd/tc6393xb.c296
1 files changed, 249 insertions, 47 deletions
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index e4c1c788b5f8..f856e9463a9f 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -113,6 +113,8 @@ struct tc6393xb {
113enum { 113enum {
114 TC6393XB_CELL_NAND, 114 TC6393XB_CELL_NAND,
115 TC6393XB_CELL_MMC, 115 TC6393XB_CELL_MMC,
116 TC6393XB_CELL_OHCI,
117 TC6393XB_CELL_FB,
116}; 118};
117 119
118/*--------------------------------------------------------------------------*/ 120/*--------------------------------------------------------------------------*/
@@ -170,6 +172,176 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
170 }, 172 },
171}; 173};
172 174
175const static struct resource tc6393xb_ohci_resources[] = {
176 {
177 .start = 0x3000,
178 .end = 0x31ff,
179 .flags = IORESOURCE_MEM,
180 },
181 {
182 .start = 0x0300,
183 .end = 0x03ff,
184 .flags = IORESOURCE_MEM,
185 },
186 {
187 .start = 0x010000,
188 .end = 0x017fff,
189 .flags = IORESOURCE_MEM,
190 },
191 {
192 .start = 0x018000,
193 .end = 0x01ffff,
194 .flags = IORESOURCE_MEM,
195 },
196 {
197 .start = IRQ_TC6393_OHCI,
198 .end = IRQ_TC6393_OHCI,
199 .flags = IORESOURCE_IRQ,
200 },
201};
202
203static struct resource __devinitdata tc6393xb_fb_resources[] = {
204 {
205 .start = 0x5000,
206 .end = 0x51ff,
207 .flags = IORESOURCE_MEM,
208 },
209 {
210 .start = 0x0500,
211 .end = 0x05ff,
212 .flags = IORESOURCE_MEM,
213 },
214 {
215 .start = 0x100000,
216 .end = 0x1fffff,
217 .flags = IORESOURCE_MEM,
218 },
219 {
220 .start = IRQ_TC6393_FB,
221 .end = IRQ_TC6393_FB,
222 .flags = IORESOURCE_IRQ,
223 },
224};
225
226static int tc6393xb_ohci_enable(struct platform_device *dev)
227{
228 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
229 unsigned long flags;
230 u16 ccr;
231 u8 fer;
232
233 spin_lock_irqsave(&tc6393xb->lock, flags);
234
235 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
236 ccr |= SCR_CCR_USBCK;
237 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
238
239 fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
240 fer |= SCR_FER_USBEN;
241 tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
242
243 spin_unlock_irqrestore(&tc6393xb->lock, flags);
244
245 return 0;
246}
247
248static int tc6393xb_ohci_disable(struct platform_device *dev)
249{
250 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
251 unsigned long flags;
252 u16 ccr;
253 u8 fer;
254
255 spin_lock_irqsave(&tc6393xb->lock, flags);
256
257 fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
258 fer &= ~SCR_FER_USBEN;
259 tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
260
261 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
262 ccr &= ~SCR_CCR_USBCK;
263 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
264
265 spin_unlock_irqrestore(&tc6393xb->lock, flags);
266
267 return 0;
268}
269
270static int tc6393xb_fb_enable(struct platform_device *dev)
271{
272 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
273 unsigned long flags;
274 u16 ccr;
275
276 spin_lock_irqsave(&tc6393xb->lock, flags);
277
278 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
279 ccr &= ~SCR_CCR_MCLK_MASK;
280 ccr |= SCR_CCR_MCLK_48;
281 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
282
283 spin_unlock_irqrestore(&tc6393xb->lock, flags);
284
285 return 0;
286}
287
288static int tc6393xb_fb_disable(struct platform_device *dev)
289{
290 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
291 unsigned long flags;
292 u16 ccr;
293
294 spin_lock_irqsave(&tc6393xb->lock, flags);
295
296 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
297 ccr &= ~SCR_CCR_MCLK_MASK;
298 ccr |= SCR_CCR_MCLK_OFF;
299 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
300
301 spin_unlock_irqrestore(&tc6393xb->lock, flags);
302
303 return 0;
304}
305
306int tc6393xb_lcd_set_power(struct platform_device *fb, bool on)
307{
308 struct platform_device *dev = to_platform_device(fb->dev.parent);
309 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
310 u8 fer;
311 unsigned long flags;
312
313 spin_lock_irqsave(&tc6393xb->lock, flags);
314
315 fer = ioread8(tc6393xb->scr + SCR_FER);
316 if (on)
317 fer |= SCR_FER_SLCDEN;
318 else
319 fer &= ~SCR_FER_SLCDEN;
320 iowrite8(fer, tc6393xb->scr + SCR_FER);
321
322 spin_unlock_irqrestore(&tc6393xb->lock, flags);
323
324 return 0;
325}
326EXPORT_SYMBOL(tc6393xb_lcd_set_power);
327
328int tc6393xb_lcd_mode(struct platform_device *fb,
329 const struct fb_videomode *mode) {
330 struct platform_device *dev = to_platform_device(fb->dev.parent);
331 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
332 unsigned long flags;
333
334 spin_lock_irqsave(&tc6393xb->lock, flags);
335
336 iowrite16(mode->pixclock, tc6393xb->scr + SCR_PLL1CR + 0);
337 iowrite16(mode->pixclock >> 16, tc6393xb->scr + SCR_PLL1CR + 2);
338
339 spin_unlock_irqrestore(&tc6393xb->lock, flags);
340
341 return 0;
342}
343EXPORT_SYMBOL(tc6393xb_lcd_mode);
344
173static struct mfd_cell __devinitdata tc6393xb_cells[] = { 345static struct mfd_cell __devinitdata tc6393xb_cells[] = {
174 [TC6393XB_CELL_NAND] = { 346 [TC6393XB_CELL_NAND] = {
175 .name = "tmio-nand", 347 .name = "tmio-nand",
@@ -182,6 +354,24 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
182 .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), 354 .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
183 .resources = tc6393xb_mmc_resources, 355 .resources = tc6393xb_mmc_resources,
184 }, 356 },
357 [TC6393XB_CELL_OHCI] = {
358 .name = "tmio-ohci",
359 .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
360 .resources = tc6393xb_ohci_resources,
361 .enable = tc6393xb_ohci_enable,
362 .suspend = tc6393xb_ohci_disable,
363 .resume = tc6393xb_ohci_enable,
364 .disable = tc6393xb_ohci_disable,
365 },
366 [TC6393XB_CELL_FB] = {
367 .name = "tmio-fb",
368 .num_resources = ARRAY_SIZE(tc6393xb_fb_resources),
369 .resources = tc6393xb_fb_resources,
370 .enable = tc6393xb_fb_enable,
371 .suspend = tc6393xb_fb_disable,
372 .resume = tc6393xb_fb_enable,
373 .disable = tc6393xb_fb_disable,
374 },
185}; 375};
186 376
187/*--------------------------------------------------------------------------*/ 377/*--------------------------------------------------------------------------*/
@@ -369,41 +559,12 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
369 559
370/*--------------------------------------------------------------------------*/ 560/*--------------------------------------------------------------------------*/
371 561
372static int tc6393xb_hw_init(struct platform_device *dev)
373{
374 struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
375 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
376 int i;
377
378 iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
379 iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
380 iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
381 iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
382 SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
383 BIT(15), tc6393xb->scr + SCR_MCR);
384 iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
385 iowrite8(0, tc6393xb->scr + SCR_IRR);
386 iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
387
388 for (i = 0; i < 3; i++) {
389 iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
390 tc6393xb->scr + SCR_GPO_DSR(i));
391 iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
392 tc6393xb->scr + SCR_GPO_DOECR(i));
393 iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
394 tc6393xb->scr + SCR_GPI_BCR(i));
395 }
396
397 return 0;
398}
399
400static int __devinit tc6393xb_probe(struct platform_device *dev) 562static int __devinit tc6393xb_probe(struct platform_device *dev)
401{ 563{
402 struct tc6393xb_platform_data *tcpd = dev->dev.platform_data; 564 struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
403 struct tc6393xb *tc6393xb; 565 struct tc6393xb *tc6393xb;
404 struct resource *iomem, *rscr; 566 struct resource *iomem, *rscr;
405 int ret, temp; 567 int ret, temp;
406 int i;
407 568
408 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); 569 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
409 if (!iomem) 570 if (!iomem)
@@ -458,21 +619,16 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
458 if (ret) 619 if (ret)
459 goto err_enable; 620 goto err_enable;
460 621
461 tc6393xb->suspend_state.fer = 0; 622 iowrite8(0, tc6393xb->scr + SCR_FER);
462 623 iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
463 for (i = 0; i < 3; i++) { 624 iowrite16(SCR_CCR_UNK1 | SCR_CCR_HCLK_48,
464 tc6393xb->suspend_state.gpo_dsr[i] = 625 tc6393xb->scr + SCR_CCR);
465 (tcpd->scr_gpo_dsr >> (8 * i)) & 0xff; 626 iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
466 tc6393xb->suspend_state.gpo_doecr[i] = 627 SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
467 (tcpd->scr_gpo_doecr >> (8 * i)) & 0xff; 628 BIT(15), tc6393xb->scr + SCR_MCR);
468 } 629 iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
469 630 iowrite8(0, tc6393xb->scr + SCR_IRR);
470 tc6393xb->suspend_state.ccr = SCR_CCR_UNK1 | 631 iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
471 SCR_CCR_HCLK_48;
472
473 ret = tc6393xb_hw_init(dev);
474 if (ret)
475 goto err_hw_init;
476 632
477 printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n", 633 printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
478 tmio_ioread8(tc6393xb->scr + SCR_REVID), 634 tmio_ioread8(tc6393xb->scr + SCR_REVID),
@@ -488,16 +644,33 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
488 644
489 tc6393xb_attach_irq(dev); 645 tc6393xb_attach_irq(dev);
490 646
647 if (tcpd->setup) {
648 ret = tcpd->setup(dev);
649 if (ret)
650 goto err_setup;
651 }
652
491 tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data; 653 tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
492 tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = 654 tc6393xb_cells[TC6393XB_CELL_NAND].platform_data =
493 &tc6393xb_cells[TC6393XB_CELL_NAND]; 655 &tc6393xb_cells[TC6393XB_CELL_NAND];
494 tc6393xb_cells[TC6393XB_CELL_NAND].data_size = 656 tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
495 sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]); 657 sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
658
496 tc6393xb_cells[TC6393XB_CELL_MMC].platform_data = 659 tc6393xb_cells[TC6393XB_CELL_MMC].platform_data =
497 &tc6393xb_cells[TC6393XB_CELL_MMC]; 660 &tc6393xb_cells[TC6393XB_CELL_MMC];
498 tc6393xb_cells[TC6393XB_CELL_MMC].data_size = 661 tc6393xb_cells[TC6393XB_CELL_MMC].data_size =
499 sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]); 662 sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]);
500 663
664 tc6393xb_cells[TC6393XB_CELL_OHCI].platform_data =
665 &tc6393xb_cells[TC6393XB_CELL_OHCI];
666 tc6393xb_cells[TC6393XB_CELL_OHCI].data_size =
667 sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]);
668
669 tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
670 tc6393xb_cells[TC6393XB_CELL_FB].platform_data =
671 &tc6393xb_cells[TC6393XB_CELL_FB];
672 tc6393xb_cells[TC6393XB_CELL_FB].data_size =
673 sizeof(tc6393xb_cells[TC6393XB_CELL_FB]);
501 674
502 ret = mfd_add_devices(&dev->dev, dev->id, 675 ret = mfd_add_devices(&dev->dev, dev->id,
503 tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), 676 tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
@@ -506,12 +679,15 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
506 if (!ret) 679 if (!ret)
507 return 0; 680 return 0;
508 681
682 if (tcpd->teardown)
683 tcpd->teardown(dev);
684
685err_setup:
509 tc6393xb_detach_irq(dev); 686 tc6393xb_detach_irq(dev);
510 687
511err_gpio_add: 688err_gpio_add:
512 if (tc6393xb->gpio.base != -1) 689 if (tc6393xb->gpio.base != -1)
513 temp = gpiochip_remove(&tc6393xb->gpio); 690 temp = gpiochip_remove(&tc6393xb->gpio);
514err_hw_init:
515 tcpd->disable(dev); 691 tcpd->disable(dev);
516err_clk_enable: 692err_clk_enable:
517 clk_disable(tc6393xb->clk); 693 clk_disable(tc6393xb->clk);
@@ -535,6 +711,10 @@ static int __devexit tc6393xb_remove(struct platform_device *dev)
535 int ret; 711 int ret;
536 712
537 mfd_remove_devices(&dev->dev); 713 mfd_remove_devices(&dev->dev);
714
715 if (tcpd->teardown)
716 tcpd->teardown(dev);
717
538 tc6393xb_detach_irq(dev); 718 tc6393xb_detach_irq(dev);
539 719
540 if (tc6393xb->gpio.base != -1) { 720 if (tc6393xb->gpio.base != -1) {
@@ -585,15 +765,37 @@ static int tc6393xb_resume(struct platform_device *dev)
585 struct tc6393xb_platform_data *tcpd = dev->dev.platform_data; 765 struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
586 struct tc6393xb *tc6393xb = platform_get_drvdata(dev); 766 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
587 int ret; 767 int ret;
768 int i;
588 769
589 clk_enable(tc6393xb->clk); 770 clk_enable(tc6393xb->clk);
590 771
591 ret = tcpd->resume(dev); 772 ret = tcpd->resume(dev);
592
593 if (ret) 773 if (ret)
594 return ret; 774 return ret;
595 775
596 return tc6393xb_hw_init(dev); 776 if (!tcpd->resume_restore)
777 return 0;
778
779 iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
780 iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
781 iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
782 iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
783 SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
784 BIT(15), tc6393xb->scr + SCR_MCR);
785 iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
786 iowrite8(0, tc6393xb->scr + SCR_IRR);
787 iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
788
789 for (i = 0; i < 3; i++) {
790 iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
791 tc6393xb->scr + SCR_GPO_DSR(i));
792 iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
793 tc6393xb->scr + SCR_GPO_DOECR(i));
794 iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
795 tc6393xb->scr + SCR_GPI_BCR(i));
796 }
797
798 return 0;
597} 799}
598#else 800#else
599#define tc6393xb_suspend NULL 801#define tc6393xb_suspend NULL