Commit 097b5334 authored by Eric Miao's avatar Eric Miao Committed by Russell King

[ARM] ohci-pxa27x: introduce flags to avoid direct access to OHCI registers

Direct access to USB host controller registers is considered to be not
portable, and is usually a bad sign for poorly abstracted interface.
Introduce .flags and .power_on_delay to "struct pxaohci_platform_data"
so that most platforms don't bother to write their own .init/.exit()
sequences.
Signed-off-by: default avatarEric Miao <eric.miao@marvell.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 52358ba3
......@@ -257,18 +257,9 @@ static inline void cmx270_init_2700G(void) {}
/* PXA27x OHCI controller setup */
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int cmx270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
UHCHR = (UHCHR | UHCHR_PCPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data cmx270_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = cmx270_ohci_init,
.flags = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
};
static void __init cmx270_init_ohci(void)
......
......@@ -365,19 +365,11 @@ static inline void cm_x300_init_mmc(void) {}
#endif
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int cm_x300_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
UHCHR = (UHCHR | UHCHR_PCPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data cm_x300_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = cm_x300_ohci_init,
.flags = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
};
static void __init cm_x300_init_ohci(void)
{
pxa_set_ohci_info(&cm_x300_ohci_platform_data);
......
......@@ -373,10 +373,6 @@ static inline void em_x270_init_nand(void) {}
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int em_x270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
UHCHR = (UHCHR | UHCHR_PCPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
/* enable port 2 transiever */
UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
......@@ -385,6 +381,7 @@ static int em_x270_ohci_init(struct device *dev)
static struct pxaohci_platform_data em_x270_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.flags = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
.init = em_x270_ohci_init,
};
......
......@@ -7,6 +7,22 @@ struct pxaohci_platform_data {
int (*init)(struct device *);
void (*exit)(struct device *);
unsigned long flags;
#define ENABLE_PORT1 (1 << 0)
#define ENABLE_PORT2 (1 << 1)
#define ENABLE_PORT3 (1 << 2)
#define ENABLE_PORT_ALL (ENABLE_PORT1 | ENABLE_PORT2 | ENABLE_PORT3)
#define POWER_SENSE_LOW (1 << 3)
#define POWER_CONTROL_LOW (1 << 4)
#define NO_OC_PROTECTION (1 << 5)
#define OC_MODE_GLOBAL (0 << 6)
#define OC_MODE_PERPORT (1 << 6)
int power_on_delay; /* Power On to Power Good time - in ms
* HCD must wait for this duration before
* accessing a powered on port
*/
int port_mode;
#define PMM_NPS_MODE 1
#define PMM_GLOBAL_MODE 2
......
......@@ -784,6 +784,9 @@
#define UHCRHDA __REG(0x4C000048) /* UHC Root Hub Descriptor A */
#define UHCRHDA_NOCP (1 << 12) /* No over current protection */
#define UHCRHDA_OCPM (1 << 11) /* Over Current Protection Mode */
#define UHCRHDA_POTPGT(x) \
(((x) & 0xff) << 24) /* Power On To Power Good Time */
#define UHCRHDB __REG(0x4C00004C) /* UHC Root Hub Descriptor B */
#define UHCRHS __REG(0x4C000050) /* UHC Root Hub Status */
......
......@@ -448,19 +448,9 @@ static struct platform_device *platform_devices[] __initdata = {
&lpd270_flash_device[1],
};
static int lpd270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low and Power Sense
Polarity Low to active low. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data lpd270_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = lpd270_ohci_init,
.flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
};
static void __init lpd270_init(void)
......
......@@ -669,18 +669,10 @@ static struct pxamci_platform_data magician_mci_info = {
* USB OHCI
*/
static int magician_ohci_init(struct device *dev)
{
UHCHR = (UHCHR | UHCHR_SSEP2 | UHCHR_PCPL | UHCHR_CGR) &
~(UHCHR_SSEP1 | UHCHR_SSEP3 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data magician_ohci_info = {
.port_mode = PMM_PERPORT_MODE,
.init = magician_ohci_init,
.power_budget = 0,
.port_mode = PMM_PERPORT_MODE,
.flags = ENABLE_PORT1 | ENABLE_PORT3 | POWER_CONTROL_LOW,
.power_budget = 0,
};
......
......@@ -508,19 +508,9 @@ static struct platform_device *platform_devices[] __initdata = {
&mst_gpio_keys_device,
};
static int mainstone_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low and Power Sense
Polarity Low to active low. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data mainstone_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = mainstone_ohci_init,
.flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
};
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
......
......@@ -328,36 +328,10 @@ static struct pxamci_platform_data pcm990_mci_platform_data = {
.exit = pcm990_mci_exit,
};
/*
* init OHCI hardware to work with
*
* Note: Only USB port 1 (host only) is connected
*
* GPIO88 (USBHPWR#1): overcurrent in, overcurrent when low
* GPIO89 (USBHPEN#1): power-on out, on when low
*/
static int pcm990_ohci_init(struct device *dev)
{
/*
* disable USB port 2 and 3
* power sense is active low
*/
UHCHR = ((UHCHR) | UHCHR_PCPL | UHCHR_PSPL | UHCHR_SSEP2 |
UHCHR_SSEP3) & ~(UHCHR_SSEP1 | UHCHR_SSE);
/*
* wait 10ms after Power on
* overcurrent per port
* power switch per port
*/
UHCRHDA = (5<<24) | (1<<11) | (1<<8); /* FIXME: Required? */
return 0;
}
static struct pxaohci_platform_data pcm990_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = pcm990_ohci_init,
.exit = NULL,
.flags = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
.power_on_delay = 10,
};
/*
......
......@@ -495,19 +495,13 @@ static int spitz_ohci_init(struct device *dev)
*/
UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
gpio_direction_output(SPITZ_GPIO_USB_HOST, 1);
UHCHR = (UHCHR) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
UHCRHDA |= UHCRHDA_NOCP;
return 0;
return gpio_direction_output(SPITZ_GPIO_USB_HOST, 1);
}
static struct pxaohci_platform_data spitz_ohci_platform_data = {
.port_mode = PMM_NPS_MODE,
.init = spitz_ohci_init,
.flags = ENABLE_PORT_ALL | NO_OC_PROTECTION,
.power_budget = 150,
};
......
......@@ -425,19 +425,9 @@ static struct pxaficp_platform_data trizeps4_ficp_platform_data = {
/****************************************************************************
* OHCI USB port
****************************************************************************/
static int trizeps4_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low and Power Sense
Polarity Low to active low. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data trizeps4_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = trizeps4_ohci_init,
.flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
};
static struct map_desc trizeps4_io_desc[] __initdata = {
......
......@@ -76,6 +76,41 @@ extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
static inline void pxa27x_setup_hc(struct pxaohci_platform_data *inf)
{
uint32_t uhchr = UHCHR;
uint32_t uhcrhda = UHCRHDA;
if (inf->flags & ENABLE_PORT1)
uhchr &= ~UHCHR_SSEP1;
if (inf->flags & ENABLE_PORT2)
uhchr &= ~UHCHR_SSEP2;
if (inf->flags & ENABLE_PORT3)
uhchr &= ~UHCHR_SSEP3;
if (inf->flags & POWER_CONTROL_LOW)
uhchr |= UHCHR_PCPL;
if (inf->flags & POWER_SENSE_LOW)
uhchr |= UHCHR_PSPL;
if (inf->flags & NO_OC_PROTECTION)
uhcrhda |= UHCRHDA_NOCP;
if (inf->flags & OC_MODE_PERPORT)
uhcrhda |= UHCRHDA_OCPM;
if (inf->power_on_delay) {
uhcrhda &= ~UHCRHDA_POTPGT(0xff);
uhcrhda |= UHCRHDA_POTPGT(inf->power_on_delay / 2);
}
UHCHR = uhchr;
UHCRHDA = uhcrhda;
}
static int pxa27x_start_hc(struct device *dev)
{
int retval = 0;
......@@ -93,6 +128,8 @@ static int pxa27x_start_hc(struct device *dev)
while (UHCHR & UHCHR_FSBIR)
cpu_relax();
pxa27x_setup_hc(inf);
if (inf->init)
retval = inf->init(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment