Skip to content

Commit

Permalink
usb: chipidea: split the driver code into units
Browse files Browse the repository at this point in the history
Split the driver into the following parts:
  * core  -- resources, register access, capabilities, etc;
  * udc   -- device controller functionality;
  * debug -- logging events.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Alexander Shishkin authored and Greg Kroah-Hartman committed May 11, 2012
1 parent bc25a80 commit e443b33
Show file tree
Hide file tree
Showing 13 changed files with 1,624 additions and 1,418 deletions.
20 changes: 18 additions & 2 deletions drivers/usb/chipidea/Kconfig
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
config USB_CHIPIDEA
tristate "ChipIdea Highspeed Dual Role Controller"
depends on USB && USB_GADGET
select USB_GADGET_DUALSPEED
depends on USB
help
Say Y here if your system has a dual role high speed USB
controller based on ChipIdea silicon IP. Currently, only the
peripheral mode is supported.

When compiled dynamically, the module will be called ci-hdrc.ko.

if USB_CHIPIDEA

config USB_CHIPIDEA_UDC
bool "ChipIdea device controller"
depends on USB_GADGET
select USB_GADGET_DUALSPEED
help
Say Y here to enable device controller functionality of the
ChipIdea driver.

config USB_CHIPIDEA_DEBUG
bool "ChipIdea driver debug"
help
Say Y here to enable debugging output of the ChipIdea driver.

endif
4 changes: 3 additions & 1 deletion drivers/usb/chipidea/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o

ci_hdrc-y := ci13xxx_udc.o
ci_hdrc-y := core.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o

ifneq ($(CONFIG_PCI),)
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o
Expand Down
71 changes: 71 additions & 0 deletions drivers/usb/chipidea/bits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* bits.h - register bits of the ChipIdea USB IP core
*
* Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
*
* Author: David Lopo
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifndef __DRIVERS_USB_CHIPIDEA_BITS_H
#define __DRIVERS_USB_CHIPIDEA_BITS_H

/* HCCPARAMS */
#define HCCPARAMS_LEN BIT(17)

/* DCCPARAMS */
#define DCCPARAMS_DEN (0x1F << 0)
#define DCCPARAMS_DC BIT(7)

/* TESTMODE */
#define TESTMODE_FORCE BIT(0)

/* USBCMD */
#define USBCMD_RS BIT(0)
#define USBCMD_RST BIT(1)
#define USBCMD_SUTW BIT(13)
#define USBCMD_ATDTW BIT(14)

/* USBSTS & USBINTR */
#define USBi_UI BIT(0)
#define USBi_UEI BIT(1)
#define USBi_PCI BIT(2)
#define USBi_URI BIT(6)
#define USBi_SLI BIT(8)

/* DEVICEADDR */
#define DEVICEADDR_USBADRA BIT(24)
#define DEVICEADDR_USBADR (0x7FUL << 25)

/* PORTSC */
#define PORTSC_FPR BIT(6)
#define PORTSC_SUSP BIT(7)
#define PORTSC_HSP BIT(9)
#define PORTSC_PTC (0x0FUL << 16)

/* DEVLC */
#define DEVLC_PSPD (0x03UL << 25)
#define DEVLC_PSPD_HS (0x02UL << 25)

/* USBMODE */
#define USBMODE_CM (0x03UL << 0)
#define USBMODE_CM_IDLE (0x00UL << 0)
#define USBMODE_CM_DEVICE (0x02UL << 0)
#define USBMODE_CM_HOST (0x03UL << 0)
#define USBMODE_SLOM BIT(3)
#define USBMODE_SDIS BIT(4)

/* ENDPTCTRL */
#define ENDPTCTRL_RXS BIT(0)
#define ENDPTCTRL_RXT (0x03UL << 2)
#define ENDPTCTRL_RXR BIT(6) /* reserved for port 0 */
#define ENDPTCTRL_RXE BIT(7)
#define ENDPTCTRL_TXS BIT(16)
#define ENDPTCTRL_TXT (0x03UL << 18)
#define ENDPTCTRL_TXR BIT(22) /* reserved for port 0 */
#define ENDPTCTRL_TXE BIT(23)

#endif /* __DRIVERS_USB_CHIPIDEA_BITS_H */
204 changes: 204 additions & 0 deletions drivers/usb/chipidea/ci.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* ci.h - common structures, functions, and macros of the ChipIdea driver
*
* Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
*
* Author: David Lopo
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifndef __DRIVERS_USB_CHIPIDEA_CI_H
#define __DRIVERS_USB_CHIPIDEA_CI_H

#include <linux/list.h>
#include <linux/usb/gadget.h>

/******************************************************************************
* DEFINE
*****************************************************************************/
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */
#define ENDPT_MAX 32

/******************************************************************************
* STRUCTURES
*****************************************************************************/
/* Extension of usb_ep */
struct ci13xxx_ep {
struct usb_ep ep;
u8 dir;
u8 num;
u8 type;
char name[16];
struct {
struct list_head queue;
struct ci13xxx_qh *ptr;
dma_addr_t dma;
} qh;
int wedge;

/* global resources */
struct ci13xxx *udc;
spinlock_t *lock;
struct device *device;
struct dma_pool *td_pool;
};

struct hw_bank {
unsigned lpm; /* is LPM? */
void __iomem *abs; /* bus map offset */
void __iomem *cap; /* bus map offset + CAP offset */
void __iomem *op; /* bus map offset + OP offset */
size_t size; /* bank size */
void __iomem **regmap;
};

/* CI13XXX UDC descriptor & global resources */
struct ci13xxx {
spinlock_t lock; /* ctrl register bank access */
void __iomem *regs; /* registers address space */

struct dma_pool *qh_pool; /* DMA pool for queue heads */
struct dma_pool *td_pool; /* DMA pool for transfer descs */
struct usb_request *status; /* ep0 status request */

struct device *dev;
struct usb_gadget gadget; /* USB slave device */
struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
u32 ep0_dir; /* ep0 direction */
struct ci13xxx_ep *ep0out, *ep0in;
unsigned hw_ep_max; /* number of hw endpoints */

bool setaddr;
u8 address;
u8 remote_wakeup; /* Is remote wakeup feature
enabled by the host? */
u8 suspended; /* suspended by the host */
u8 test_mode; /* the selected test mode */

struct hw_bank hw_bank;
int irq;
struct usb_gadget_driver *driver; /* 3rd party gadget driver */
struct ci13xxx_udc_driver *udc_driver; /* device controller driver */
int vbus_active; /* is VBUS active */
struct usb_phy *transceiver; /* Transceiver struct */
};

/******************************************************************************
* REGISTERS
*****************************************************************************/
/* register size */
#define REG_BITS (32)

/* register indices */
enum ci13xxx_regs {
CAP_CAPLENGTH,
CAP_HCCPARAMS,
CAP_DCCPARAMS,
CAP_TESTMODE,
CAP_LAST = CAP_TESTMODE,
OP_USBCMD,
OP_USBSTS,
OP_USBINTR,
OP_DEVICEADDR,
OP_ENDPTLISTADDR,
OP_PORTSC,
OP_DEVLC,
OP_USBMODE,
OP_ENDPTSETUPSTAT,
OP_ENDPTPRIME,
OP_ENDPTFLUSH,
OP_ENDPTSTAT,
OP_ENDPTCOMPLETE,
OP_ENDPTCTRL,
/* endptctrl1..15 follow */
OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2,
};


/**
* ffs_nr: find first (least significant) bit set
* @x: the word to search
*
* This function returns bit number (instead of position)
*/
static inline int ffs_nr(u32 x)
{
int n = ffs(x);

return n ? n-1 : 32;
}

/**
* hw_read: reads from a hw register
* @reg: register index
* @mask: bitfield mask
*
* This function returns register contents
*/
static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
{
return ioread32(udc->hw_bank.regmap[reg]) & mask;
}

/**
* hw_write: writes to a hw register
* @reg: register index
* @mask: bitfield mask
* @data: new value
*/
static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
u32 mask, u32 data)
{
if (~mask)
data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask)
| (data & mask);

iowrite32(data, udc->hw_bank.regmap[reg]);
}

/**
* hw_test_and_clear: tests & clears a hw register
* @reg: register index
* @mask: bitfield mask
*
* This function returns register contents
*/
static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
u32 mask)
{
u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask;

iowrite32(val, udc->hw_bank.regmap[reg]);
return val;
}

/**
* hw_test_and_write: tests & writes a hw register
* @reg: register index
* @mask: bitfield mask
* @data: new value
*
* This function returns register contents
*/
static inline u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
u32 mask, u32 data)
{
u32 val = hw_read(udc, reg, ~0);

hw_write(udc, reg, mask, data);
return (val & mask) >> ffs_nr(mask);
}

int hw_device_init(struct ci13xxx *udc, void __iomem *base,
uintptr_t cap_offset);
int hw_device_reset(struct ci13xxx *ci);

int hw_port_test_set(struct ci13xxx *ci, u8 mode);

u8 hw_port_test_get(struct ci13xxx *ci);

#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
3 changes: 2 additions & 1 deletion drivers/usb/chipidea/ci13xxx_msm.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/ulpi.h>
#include <linux/usb/gadget.h>
#include <linux/usb/chipidea.h>

#include "ci13xxx_udc.h"
#include "ci.h"

#define MSM_USB_BASE (udc->regs)

Expand Down
3 changes: 1 addition & 2 deletions drivers/usb/chipidea/ci13xxx_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/usb/gadget.h>

#include "ci13xxx_udc.h"
#include <linux/usb/chipidea.h>

/* driver name */
#define UDC_DRIVER_NAME "ci13xxx_pci"
Expand Down
Loading

0 comments on commit e443b33

Please sign in to comment.