Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e78cfe5 authored by Dmitry Eremin-Solenikov's avatar Dmitry Eremin-Solenikov Committed by Samuel Ortiz
Browse files

mfd: support tmiofb cell on tc6393xb



Add support for tmiofb cell found in tc6393xb chip.

Signed-off-by: default avatarDmitry Baryshkov <dbaryshkov@gmail.com>
Cc: Ian Molton <spyro@f2s.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@openedhand.com>
parent 51a55623
Loading
Loading
Loading
Loading
+114 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ enum {
	TC6393XB_CELL_NAND,
	TC6393XB_CELL_MMC,
	TC6393XB_CELL_OHCI,
	TC6393XB_CELL_FB,
};

/*--------------------------------------------------------------------------*/
@@ -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);
@@ -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",
@@ -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,
	},
};

/*--------------------------------------------------------------------------*/
@@ -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 =
@@ -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),
+8 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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