Loading drivers/mfd/tc6393xb.c +114 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ enum { TC6393XB_CELL_NAND, TC6393XB_CELL_MMC, TC6393XB_CELL_OHCI, TC6393XB_CELL_FB, }; /*--------------------------------------------------------------------------*/ Loading Loading @@ -199,6 +200,29 @@ const static struct resource tc6393xb_ohci_resources[] = { }, }; static struct resource __devinitdata tc6393xb_fb_resources[] = { { .start = 0x5000, .end = 0x51ff, .flags = IORESOURCE_MEM, }, { .start = 0x0500, .end = 0x05ff, .flags = IORESOURCE_MEM, }, { .start = 0x100000, .end = 0x1fffff, .flags = IORESOURCE_MEM, }, { .start = IRQ_TC6393_FB, .end = IRQ_TC6393_FB, .flags = IORESOURCE_IRQ, }, }; static int tc6393xb_ohci_enable(struct platform_device *dev) { struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); Loading Loading @@ -243,6 +267,81 @@ static int tc6393xb_ohci_disable(struct platform_device *dev) return 0; } static int tc6393xb_fb_enable(struct platform_device *dev) { struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); unsigned long flags; u16 ccr; spin_lock_irqsave(&tc6393xb->lock, flags); ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR); ccr &= ~SCR_CCR_MCLK_MASK; ccr |= SCR_CCR_MCLK_48; tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } static int tc6393xb_fb_disable(struct platform_device *dev) { struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); unsigned long flags; u16 ccr; spin_lock_irqsave(&tc6393xb->lock, flags); ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR); ccr &= ~SCR_CCR_MCLK_MASK; ccr |= SCR_CCR_MCLK_OFF; tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } int tc6393xb_lcd_set_power(struct platform_device *fb, bool on) { struct platform_device *dev = to_platform_device(fb->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); u8 fer; unsigned long flags; spin_lock_irqsave(&tc6393xb->lock, flags); fer = ioread8(tc6393xb->scr + SCR_FER); if (on) fer |= SCR_FER_SLCDEN; else fer &= ~SCR_FER_SLCDEN; iowrite8(fer, tc6393xb->scr + SCR_FER); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } EXPORT_SYMBOL(tc6393xb_lcd_set_power); int tc6393xb_lcd_mode(struct platform_device *fb, const struct fb_videomode *mode) { struct platform_device *dev = to_platform_device(fb->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&tc6393xb->lock, flags); iowrite16(mode->pixclock, tc6393xb->scr + SCR_PLL1CR + 0); iowrite16(mode->pixclock >> 16, tc6393xb->scr + SCR_PLL1CR + 2); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } EXPORT_SYMBOL(tc6393xb_lcd_mode); static struct mfd_cell __devinitdata tc6393xb_cells[] = { [TC6393XB_CELL_NAND] = { .name = "tmio-nand", Loading @@ -264,6 +363,15 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { .resume = tc6393xb_ohci_enable, .disable = tc6393xb_ohci_disable, }, [TC6393XB_CELL_FB] = { .name = "tmio-fb", .num_resources = ARRAY_SIZE(tc6393xb_fb_resources), .resources = tc6393xb_fb_resources, .enable = tc6393xb_fb_enable, .suspend = tc6393xb_fb_disable, .resume = tc6393xb_fb_enable, .disable = tc6393xb_fb_disable, }, }; /*--------------------------------------------------------------------------*/ Loading Loading @@ -547,6 +655,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) &tc6393xb_cells[TC6393XB_CELL_NAND]; tc6393xb_cells[TC6393XB_CELL_NAND].data_size = sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]); tc6393xb_cells[TC6393XB_CELL_MMC].platform_data = &tc6393xb_cells[TC6393XB_CELL_MMC]; tc6393xb_cells[TC6393XB_CELL_MMC].data_size = Loading @@ -557,6 +666,11 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) tc6393xb_cells[TC6393XB_CELL_OHCI].data_size = sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]); tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data; tc6393xb_cells[TC6393XB_CELL_FB].platform_data = &tc6393xb_cells[TC6393XB_CELL_FB]; tc6393xb_cells[TC6393XB_CELL_FB].data_size = sizeof(tc6393xb_cells[TC6393XB_CELL_FB]); ret = mfd_add_devices(&dev->dev, dev->id, tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), Loading include/linux/mfd/tc6393xb.h +8 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef MFD_TC6393XB_H #define MFD_TC6393XB_H #include <linux/fb.h> /* Also one should provide the CK3P6MI clock */ struct tc6393xb_platform_data { u16 scr_pll2cr; /* PLL2 Control */ Loading @@ -33,18 +35,24 @@ struct tc6393xb_platform_data { void (*teardown)(struct platform_device *dev); struct tmio_nand_data *nand_data; struct tmio_fb_data *fb_data; unsigned resume_restore : 1; /* make special actions to preserve the state on suspend/resume */ }; extern int tc6393xb_lcd_mode(struct platform_device *fb, const struct fb_videomode *mode); extern int tc6393xb_lcd_set_power(struct platform_device *fb, bool on); /* * Relative to irq_base */ #define IRQ_TC6393_NAND 0 #define IRQ_TC6393_MMC 1 #define IRQ_TC6393_OHCI 2 #define IRQ_TC6393_FB 4 #define TC6393XB_NR_IRQS 8 Loading Loading
drivers/mfd/tc6393xb.c +114 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ enum { TC6393XB_CELL_NAND, TC6393XB_CELL_MMC, TC6393XB_CELL_OHCI, TC6393XB_CELL_FB, }; /*--------------------------------------------------------------------------*/ Loading Loading @@ -199,6 +200,29 @@ const static struct resource tc6393xb_ohci_resources[] = { }, }; static struct resource __devinitdata tc6393xb_fb_resources[] = { { .start = 0x5000, .end = 0x51ff, .flags = IORESOURCE_MEM, }, { .start = 0x0500, .end = 0x05ff, .flags = IORESOURCE_MEM, }, { .start = 0x100000, .end = 0x1fffff, .flags = IORESOURCE_MEM, }, { .start = IRQ_TC6393_FB, .end = IRQ_TC6393_FB, .flags = IORESOURCE_IRQ, }, }; static int tc6393xb_ohci_enable(struct platform_device *dev) { struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); Loading Loading @@ -243,6 +267,81 @@ static int tc6393xb_ohci_disable(struct platform_device *dev) return 0; } static int tc6393xb_fb_enable(struct platform_device *dev) { struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); unsigned long flags; u16 ccr; spin_lock_irqsave(&tc6393xb->lock, flags); ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR); ccr &= ~SCR_CCR_MCLK_MASK; ccr |= SCR_CCR_MCLK_48; tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } static int tc6393xb_fb_disable(struct platform_device *dev) { struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); unsigned long flags; u16 ccr; spin_lock_irqsave(&tc6393xb->lock, flags); ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR); ccr &= ~SCR_CCR_MCLK_MASK; ccr |= SCR_CCR_MCLK_OFF; tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } int tc6393xb_lcd_set_power(struct platform_device *fb, bool on) { struct platform_device *dev = to_platform_device(fb->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); u8 fer; unsigned long flags; spin_lock_irqsave(&tc6393xb->lock, flags); fer = ioread8(tc6393xb->scr + SCR_FER); if (on) fer |= SCR_FER_SLCDEN; else fer &= ~SCR_FER_SLCDEN; iowrite8(fer, tc6393xb->scr + SCR_FER); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } EXPORT_SYMBOL(tc6393xb_lcd_set_power); int tc6393xb_lcd_mode(struct platform_device *fb, const struct fb_videomode *mode) { struct platform_device *dev = to_platform_device(fb->dev.parent); struct tc6393xb *tc6393xb = platform_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&tc6393xb->lock, flags); iowrite16(mode->pixclock, tc6393xb->scr + SCR_PLL1CR + 0); iowrite16(mode->pixclock >> 16, tc6393xb->scr + SCR_PLL1CR + 2); spin_unlock_irqrestore(&tc6393xb->lock, flags); return 0; } EXPORT_SYMBOL(tc6393xb_lcd_mode); static struct mfd_cell __devinitdata tc6393xb_cells[] = { [TC6393XB_CELL_NAND] = { .name = "tmio-nand", Loading @@ -264,6 +363,15 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { .resume = tc6393xb_ohci_enable, .disable = tc6393xb_ohci_disable, }, [TC6393XB_CELL_FB] = { .name = "tmio-fb", .num_resources = ARRAY_SIZE(tc6393xb_fb_resources), .resources = tc6393xb_fb_resources, .enable = tc6393xb_fb_enable, .suspend = tc6393xb_fb_disable, .resume = tc6393xb_fb_enable, .disable = tc6393xb_fb_disable, }, }; /*--------------------------------------------------------------------------*/ Loading Loading @@ -547,6 +655,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) &tc6393xb_cells[TC6393XB_CELL_NAND]; tc6393xb_cells[TC6393XB_CELL_NAND].data_size = sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]); tc6393xb_cells[TC6393XB_CELL_MMC].platform_data = &tc6393xb_cells[TC6393XB_CELL_MMC]; tc6393xb_cells[TC6393XB_CELL_MMC].data_size = Loading @@ -557,6 +666,11 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) tc6393xb_cells[TC6393XB_CELL_OHCI].data_size = sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]); tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data; tc6393xb_cells[TC6393XB_CELL_FB].platform_data = &tc6393xb_cells[TC6393XB_CELL_FB]; tc6393xb_cells[TC6393XB_CELL_FB].data_size = sizeof(tc6393xb_cells[TC6393XB_CELL_FB]); ret = mfd_add_devices(&dev->dev, dev->id, tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), Loading
include/linux/mfd/tc6393xb.h +8 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef MFD_TC6393XB_H #define MFD_TC6393XB_H #include <linux/fb.h> /* Also one should provide the CK3P6MI clock */ struct tc6393xb_platform_data { u16 scr_pll2cr; /* PLL2 Control */ Loading @@ -33,18 +35,24 @@ struct tc6393xb_platform_data { void (*teardown)(struct platform_device *dev); struct tmio_nand_data *nand_data; struct tmio_fb_data *fb_data; unsigned resume_restore : 1; /* make special actions to preserve the state on suspend/resume */ }; extern int tc6393xb_lcd_mode(struct platform_device *fb, const struct fb_videomode *mode); extern int tc6393xb_lcd_set_power(struct platform_device *fb, bool on); /* * Relative to irq_base */ #define IRQ_TC6393_NAND 0 #define IRQ_TC6393_MMC 1 #define IRQ_TC6393_OHCI 2 #define IRQ_TC6393_FB 4 #define TC6393XB_NR_IRQS 8 Loading